Builder examples
Using remote builder for native multi-arch
If you’re developing on ARM64 (like Apple Silicon), but you want to deploy on AMD64 (x86 64-bit), you can use multi-architecture images. By default, Kamal will setup a local buildx configuration that does this through QEMU emulation. But 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, while natively building the ARM64 part locally, you can do so using builder options:
builder:
local:
arch: arm64
host: unix:///Users/<%= `whoami`.strip %>/.docker/run/docker.sock
remote:
arch: amd64
host: ssh://[email protected]
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 single-arch
If you’re developing on ARM64 (like Apple Silicon), want to deploy on AMD64 (x86 64-bit), but don’t need to run the image locally (or on other ARM64 hosts), you can configure a remote builder that just targets AMD64. This is a bit faster than building with multi-arch, as there’s nothing to build locally.
builder:
remote:
arch: amd64
host: ssh://[email protected]
Using local builder for single-arch
If you’re developing on multiple architectures, always deploy on a specific architecture(e.g. AMD64), and want to build locally, you can configure a remote builder without a host. Kamal will build the image using a local buildx instance.
builder:
remote:
arch: amd64
Using native builder when multi-arch isn’t needed
If you’re developing on the same architecture as the one you’re deploying on, you can speed up the build by forgoing both multi-arch and remote building:
builder:
multiarch: false
This is also a good option if you’re running Kamal from a CI server that shares architecture with the deployment servers.
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 singlehandedly speed up your builds by a lot. 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 setup 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 setup correctly you should see the cache entry/entries on the GHA workflow actions cache section.
For further insights into build cache optimization, check out 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 having the secret in ENV, then referencing it in the builder configuration:
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