Configuring a Docker Build Server
Building Docker Images with DeployHQ
This guide outlines how to configure DeployHQ to build Docker images from your repository and optionally push them to a container registry. This feature requires a Dockerfile in your repository.
Prerequisites:
- Dockerfile: Your repository must contain a valid Dockerfile
- Registry Account: For pushing images, you need credentials for your chosen container registry
Supported Container Registries
DeployHQ supports building and pushing Docker images to:
- Docker Hub - The default Docker container registry
- Google Container Registry (GCR) - Google Cloud's container registry
- GitHub Container Registry (GHCR) - GitHub's container registry
- Azure Container Registry (ACR) - Microsoft Azure's container registry
Step-by-Step Configuration
Select Protocol: Navigate to your server settings within DeployHQ and select Docker Build as your server's protocol.
Push to Registry: Choose whether to push the built image to a registry after building. Disable this option if you only want to test that your Dockerfile builds successfully.

- Registry Configuration: Select your target container registry and enter your credentials (see registry-specific instructions below).
- Registry Type: Docker Hub, Google Container Registry (GCR), GitHub Container Registry (GHCR), or Azure Container Registry (ACR)
- Username: Your registry username
- Password/Token: Your registry password or access token
- Registry Namespace: The namespace/project for your image path (see registry-specific details below)

- Image Configuration: Set the image name and tag pattern.
- Image Name: The name for your Docker image (without registry prefix or tag)
- Tag Pattern: How to tag your images (e.g.,
{revision},latest,v1.0.{timestamp})

- Build Configuration: Configure the Dockerfile path and any build arguments.
- Dockerfile Path: Path to your Dockerfile or directory containing it (default:
.) - Build with BuildKit: Use Docker's BuildKit builder instead of the legacy builder (default: off)
- Build Arguments: Optional build-time variables in
KEY=valueformat, one per line

Registry Configuration
Docker Hub
Docker Hub is the default public registry for Docker images.
Credentials:
- Username: Your Docker Hub username
- Password/Token: Your Docker Hub access token (recommended) or password
- Registry Namespace: (Optional) Your Docker Hub username or organization name. If not set, defaults to your username.
Required Permissions:
When creating an access token, select the following permissions:
- Read - Required to verify authentication
- Write - Required to push images
For organization repositories, ensure your Docker Hub account has "Editor" or "Owner" role on the repository.
Creating an Access Token:
- Log in to Docker Hub
- Go to Account Settings then Security
- Click New Access Token
- Give it a descriptive name (e.g., "DeployHQ")
- Select Read and Write access permissions
- Click Generate and copy the token for use in DeployHQ
Important: Access tokens are more secure than passwords and are recommended. If your Docker Hub account has 2FA enabled, you must use an access token.
Image Reference Format:
Your images will be pushed as: username/image-name:tag
Google Container Registry (GCR)
GCR is Google Cloud's private container registry integrated with Google Cloud Platform.
Credentials:
- Username:
_json_key(exactly as shown, this is a literal string) - Password/Token: Your service account JSON key (the entire JSON content)
- Registry Namespace: Your Google Cloud project ID (required)
Important: The Registry Namespace field must be set to your GCP project ID (e.g., my-project-123). This is the project where your images will be stored. Do not confuse this with the username field, which is always _json_key for service account authentication.
Required IAM Permissions:
The service account needs the following IAM roles on your Google Cloud project:
| Role | Description |
|---|---|
roles/storage.objectAdmin |
Push and pull images (recommended minimum) |
roles/storage.admin |
Full control over GCR bucket (alternative) |
For more granular control, these individual permissions are required:
storage.buckets.get- Access the GCR bucketstorage.objects.create- Push new image layersstorage.objects.delete- Overwrite existing tagsstorage.objects.get- Verify uploadsstorage.objects.list- List image layers
Creating Service Account Credentials:
- Go to the Google Cloud Console
- Navigate to IAM and Admin then Service Accounts
- Click Create Service Account
- Give it a name (e.g., "deployhq-gcr")
- Grant the Storage Object Admin role (
roles/storage.objectAdmin) - Click Done to create the service account
- Click on the service account, go to Keys tab
- Click Add Key then Create new key
- Select JSON format and download the key file
- Copy the entire JSON content as the password in DeployHQ
Important: The password field should contain the complete JSON object, starting with { and ending with }. Do not extract just the private key.
GCR Endpoint:
DeployHQ uses the gcr.io endpoint for pushes. Your images will be stored in the GCR repository for your project.
Image Reference Format:
Your images will be pushed as: gcr.io/PROJECT_ID/image-name:tag
GitHub Container Registry (GHCR)
GHCR is GitHub's container registry, tightly integrated with GitHub repositories and packages.
Credentials:
- Username: Your GitHub username
- Password/Token: A GitHub Personal Access Token (PAT) with package permissions
- Registry Namespace: (Optional) Your GitHub username or organization name. If not set, defaults to your username. Set this to your organization name when pushing to organization packages.
Required Token Scopes:
| Scope | Description | Required |
|---|---|---|
write:packages |
Upload packages to GitHub Package Registry | Yes |
read:packages |
Download packages from GitHub Package Registry | Yes |
delete:packages |
Delete packages (optional, for cleanup) | No |
If your package is linked to a repository, you may also need:
repo- Full control of private repositories (for private repo packages)
Creating a Personal Access Token (Classic):
- Go to GitHub Settings - Tokens
- Click Generate new token then Generate new token (classic)
- Give it a descriptive name (e.g., "DeployHQ Docker Build")
- Set an expiration (or "No expiration" for persistent access)
- Select the following scopes:
write:packagesread:packagesrepo(if pushing to private repository packages)
- Click Generate token
- Copy the token immediately (it won't be shown again)
Creating a Fine-grained Personal Access Token:
- Go to GitHub Settings - Tokens
- Click Generate new token
- Give it a descriptive name
- Select the repository or organization
- Under Permissions, set:
- Packages: Read and write
- Click Generate token
Organization Packages:
For organization-owned packages:
- Use the organization name as the username
- Ensure your GitHub account has "Write" or "Admin" access to the package
- The PAT must be authorized for the organization (SSO authorization if required)
Package Visibility:
- Public packages can be pulled without authentication
- Private packages require authentication for both push and pull
- Package visibility can be set in GitHub package settings
Image Reference Format:
Your images will be pushed as: ghcr.io/OWNER/image-name:tag
Where OWNER is your GitHub username or organization name.
Azure Container Registry (ACR)
ACR is Azure's managed container registry service.
Credentials:
- Username: Your registry username (admin user) or service principal app ID
- Password/Token: Your registry password or service principal client secret
- Registry Namespace: Your registry name (e.g.,
myregistry) or full login server (e.g.,myregistry.azurecr.io) (required)
Image Reference Format:
Your images will be pushed as: myregistry.azurecr.io/image-name:tag
Tag Patterns
DeployHQ supports dynamic tag patterns using placeholders:
| Placeholder | Description | Example Output |
|---|---|---|
{revision} |
Short commit hash (8 characters) | a1b2c3d4 |
{branch} |
Branch name (sanitized) | main, feature-login |
{timestamp} |
Build timestamp | 20240115143022 |
Example Patterns:
{revision}- Tag with commit hash (default)latest- Always use the latest tag{branch}-{revision}- Include branch name:main-a1b2c3d4v1.0.{timestamp}- Version with timestamp:v1.0.20240115143022
Build Arguments
Pass build-time variables to your Docker build using the Build Arguments field. Enter one argument per line in KEY=value format:
NODE_ENV=production
API_URL=https://api.example.com
BUILD_NUMBER=123
These arguments are passed to docker build using the --build-arg flag and can be referenced in your Dockerfile using ARG instructions.
BuildKit
By default your image is built with Docker's legacy builder. Tick Build with BuildKit to use BuildKit instead.
You need this if your Dockerfile uses syntax that only BuildKit understands, such as:
RUN --mount=type=cache, which mounts a writable directory for a package manager's cache- Heredocs, which let you write a multi-line script inside a single
RUNinstruction
A Dockerfile using either of these fails to build with the legacy builder, usually with a parse error pointing at the line in question. If you see that, turning this option on is the fix.
Cache mounts do not currently carry over between builds. Each build gets its own isolated cache, so the directory starts empty every time. The instruction builds correctly and the cache works within a single build, but it will not speed up the next one.
RUN --mount=type=secret is not supported. BuildKit will parse the instruction, but there is no way to supply the secret, so the mount is empty: a step declaring required=true errors out, and otherwise the command runs without the credentials it expected and usually fails further on. This applies whether or not this option is enabled.
Build Arguments are not a substitute. Docker records their values in image metadata, provenance and build history, so they are for non-secret build-time values only. This build flow has no way to pass a credential to a build step, so a Dockerfile that needs one cannot be built here.
Leave it off if your Dockerfile does not use those features. The legacy builder handles standard Dockerfiles perfectly well, and leaving the setting unchanged keeps your builds behaving exactly as before.
This setting applies to the Docker Build server you set it on. If your project has more than one, each is configured separately.
Build-Only Mode
If you want to test your Dockerfile without pushing to a registry, uncheck the "Push image to registry after build" option. This is useful for:
- Validating Dockerfile syntax and build process
- Testing builds before configuring registry credentials
- CI/CD pipelines where pushing is handled separately
Build Timeout Limits
Docker build durations are capped by plan:
- Free / Free v2: 15 minutes
- Deprecated plans / Solo / Pro: 1 hour
- Business / Enterprise: 3 hours
If a build exceeds the limit, it will be stopped automatically.
Deployment Behavior
Unlike traditional file-based deployments, Docker Build:
- Does not transfer files to a destination server
- Builds the Docker image using DeployHQ's build infrastructure
- Optionally pushes the built image to your configured registry
- Records the built image reference in deployment metadata
Troubleshooting
Build Fails:
- Verify your Dockerfile syntax is correct
- Check that all referenced files exist in your repository
- Review build logs for specific error messages
- If the error points at a
RUN --mount=...line or a heredoc, tick Build with BuildKit in the Build Configuration section and deploy again
Authentication Fails:
- Verify your credentials are correct
- For GCR, ensure the entire JSON key is pasted (not just the private key)
- For GHCR, verify your PAT has the
write:packagesscope - For Docker Hub, use an access token rather than your password
- For ACR, verify your registry username/password or service principal credentials
Push Fails:
- Verify you have push permissions to the registry
- Check that the image name is valid for your registry
- Ensure your registry quota has not been exceeded
- For GCR, ensure the Registry Namespace is set to your GCP project ID (not
_json_key)