Builder examples
Using remote builder for single-arch
If you’re developing on ARM64 (like Apple Silicon), but you want to deploy on AMD64 (x86 64-bit), by default, Kamal will set up a local buildx configuration that does this through QEMU emulation. However, this can be quite slow, especially on the first build.
If you want to speed up this process by using a remote AMD64 host to natively build the AMD64 part of the image, you can set a remote builder:
builder:
arch: amd64
remote: ssh://[email protected]
Kamal will use the remote to build when deploying from an ARM64 machine, or build locally when deploying from an AMD64 machine.
Note: You must have Docker running on the remote host being used as a builder. This instance should only be shared for builds using the same registry and credentials.
Using remote builder for multi-arch
You can also build a multi-arch image. If a remote is set, Kamal will build the architecture matching your deployment server locally and the other architecture remotely.
So if you’re developing on ARM64 (like Apple Silicon), it will build the ARM64 architecture locally and the AMD64 architecture remotely.
builder:
arch:
- amd64
- arm64
remote: ssh://[email protected]
Using local builder for single-arch
If you always want to build locally for a single architecture, Kamal will build the image using a local buildx instance.
builder:
arch: amd64
Using a different Dockerfile or context when building
If you need to pass a different Dockerfile or context to the build command (e.g., if you’re using a monorepo or you have different Dockerfiles), you can do so in the builder options:
# Use a different Dockerfile
builder:
dockerfile: Dockerfile.xyz
# Set context
builder:
context: ".."
# Set Dockerfile and context
builder:
dockerfile: "../Dockerfile.xyz"
context: ".."
Using multistage builder cache
Docker multistage build cache can speed up your builds. Currently, Kamal only supports using the GHA cache or the Registry cache:
# Using GHA cache
builder:
cache:
type: gha
# Using Registry cache
builder:
cache:
type: registry
# Using Registry cache with different cache image
builder:
cache:
type: registry
# default image name is <image>-build-cache
image: application-cache-image
# Using Registry cache with additional cache-to options
builder:
cache:
type: registry
options: mode=max,image-manifest=true,oci-mediatypes=true
GHA cache configuration
To make it work on the GitHub action workflow, you need to set up the buildx and expose authentication configuration for the cache.
Example setup (in .github/workflows/sample-ci.yml):
- name: Set up Docker Buildx for cache
uses: docker/setup-buildx-action@v3
- name: Expose GitHub Runtime for cache
uses: crazy-max/ghaction-github-runtime@v3
When set up correctly, you should see the cache entry/entries on the GHA workflow actions cache section.
For further insights into build cache optimization, check out the documentation on Docker’s official website: https://docs.docker.com/build/cache/.
Using build secrets for new images
Some images need a secret passed in during build time, like a GITHUB_TOKEN, to give access to private gem repositories. This can be done by setting the secret in .kamal/secrets
, then referencing it in the builder configuration:
# .kamal/secrets
GITHUB_TOKEN=$(gh config get -h github.com oauth_token)
# config/deploy.yml
builder:
secrets:
- GITHUB_TOKEN
This build secret can then be referenced in the Dockerfile:
# Copy Gemfiles
COPY Gemfile Gemfile.lock ./
# Install dependencies, including private repositories via access token (then remove bundle cache with exposed GITHUB_TOKEN)
RUN --mount=type=secret,id=GITHUB_TOKEN \
BUNDLE_GITHUB__COM=x-access-token:$(cat /run/secrets/GITHUB_TOKEN) \
bundle install && \
rm -rf /usr/local/bundle/cache
Configuring build args for new images
Build arguments that aren’t secret can also be configured:
builder:
args:
RUBY_VERSION: 3.2.0
This build argument can then be used in the Dockerfile:
ARG RUBY_VERSION
FROM ruby:$RUBY_VERSION-slim as base