Welcome to from-docker-to-kubernetes

Docker Buildx

Learn about Docker Buildx for advanced container image building capabilities and multi-platform support

Docker Buildx

Docker Buildx is an extended and improved version of the Docker build command, offering advanced features like multi-architecture builds, build cache management, and concurrent building processes. It represents Docker's next-generation builder that is designed to replace the legacy docker build command with additional functionality while maintaining backward compatibility.

Buildx is built on top of the BuildKit build system, which enables superior performance, enhanced caching, and parallel processing capabilities that were not available in the traditional builder. This allows developers to create more efficient container images across various platforms from a single build command.

Core Features

Multi-platform Builds

  • Build for multiple architectures simultaneously (e.g., AMD64, ARM64, ARM/v7)
  • Support for diverse CPU architectures and operating systems
  • Single command to create cross-platform images
  • Simplified CI/CD pipelines for heterogeneous environments
  • Future-proof container strategy for edge computing, IoT, and cloud deployments
  • Eliminates the need for separate build infrastructure for different architectures

BuildKit Integration

  • Modern build system architecture with directed acyclic graph (DAG) execution
  • Advanced caching mechanisms that understand source code dependencies
  • Concurrent dependency resolution for faster builds
  • Efficient layer creation with automatic deduplication
  • Enhanced build performance through parallelization of build steps
  • Reduced build times and resource consumption compared to legacy builders

Getting Started with Buildx

Multi-architecture Builds

# Build and push multi-platform image
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 \
  -t username/myapp:latest \
  --push .
# This builds images for three different architectures simultaneously and pushes them to a registry
# The registry will store these as a multi-arch manifest that Docker clients can automatically select from

# Build multi-platform image locally
docker buildx build --platform linux/amd64,linux/arm64 \
  -t username/myapp:latest \
  --load .
# The --load flag imports the image into Docker's local image store
# Note: --load currently only works with single-platform builds, so this will build only for your current architecture

Advanced Caching

Local Cache

# Use inline cache with local filesystem
docker buildx build \
  --cache-from type=local,src=./cache \
  --cache-to type=local,dest=./cache \
  -t myimage:latest .
# This stores build cache layers to the ./cache directory
# Future builds can reuse this cache even if the Docker daemon is restarted
# Ideal for local development or CI systems with persistent storage

Registry Cache

# Use registry for distributed caching
docker buildx build \
  --cache-from type=registry,ref=username/myapp:cache \
  --cache-to type=registry,ref=username/myapp:cache,mode=max \
  -t username/myapp:latest \
  --push .
# Stores build cache in a separate tag in your registry
# Allows teams to share build cache across different machines and CI/CD pipelines
# The mode=max option stores all layers including intermediate ones
# Reduces build times in distributed environments by avoiding redundant work

GitHub Cache

# Cache in GitHub Actions
docker buildx build \
  --cache-from type=gha \
  --cache-to type=gha,mode=max \
  -t username/myapp:latest .
# Specifically optimized for GitHub Actions workflows
# Uses GitHub's built-in cache system for faster CI builds
# Works automatically with GitHub's runner architecture
# Persists between workflow runs to speed up repeated builds

Build Contexts

Build Arguments and Secrets

# Build with build arguments
docker buildx build --build-arg VERSION=1.2.3 -t myapp .
# Build arguments can be used in Dockerfile with ARG instructions
# Useful for injecting version numbers, configuration, or environment-specific values
# Values are available during build time but not in the resulting container unless explicitly copied

# Use secrets in build
docker buildx build \
  --secret id=mysecret,src=./secret.txt \
  -t secure-app .
# Secrets are temporarily mounted during build but not stored in the final image
# Perfect for passing API keys, credentials, or certificates to the build process
# The secret is available at /run/secrets/mysecret inside the build container
# After the build completes, the secret is removed from the build environment

Dockerfile Examples

Multi-platform Dockerfile

# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM golang:1.18 AS builder

# These ARGs are automatically set by buildx
ARG TARGETPLATFORM   # Platform for the target image (e.g., linux/amd64)
ARG BUILDPLATFORM    # Platform where the build is running (e.g., linux/arm64)
RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM"

WORKDIR /app
COPY . .
# Parse the platform values to set Go environment variables
RUN GOOS=$(echo $TARGETPLATFORM | cut -d/ -f1) \
    GOARCH=$(echo $TARGETPLATFORM | cut -d/ -f2) \
    go build -o /app/myapp .
# This enables cross-compilation: Go code is compiled for the target platform
# regardless of where the build is actually running

FROM alpine
COPY --from=builder /app/myapp /usr/local/bin/
CMD ["myapp"]
# The resulting image contains only the compiled binary for the target platform
# Multi-stage builds help create smaller, more secure images

Using Secrets

# syntax=docker/dockerfile:1
FROM alpine

# Use secret from buildx directly mounted during build
RUN --mount=type=secret,id=mysecret \
    cat /run/secrets/mysecret > /app/secret-data
# This is the most secure method - the secret is never stored in any image layer
# Secret is only available during this specific RUN instruction

# Use secret as file (NOT RECOMMENDED FOR SENSITIVE DATA)
COPY mysecret.txt /app/
# This method adds the secret file to an image layer, making it retrievable
# Only use for non-sensitive data or development environments

# Use secret as environment variable (USE WITH CAUTION)
ARG SECRET_ENV
ENV APP_SECRET=$SECRET_ENV
# Build args can be viewed in image history
# Environment variables might be exposed in container metadata
# For production, prefer the --mount=type=secret approach

Buildx Drivers

# Create builder with container driver
docker buildx create --name mybuilder --driver docker-container
# This creates a new builder that runs in a container
# The container provides isolation and full BuildKit features
# Automatically starts a BuildKit container on your Docker host

# Use Kubernetes driver
docker buildx create --name k8s-builder \
  --driver kubernetes \
  --driver-opt namespace=buildkitd \
  --driver-opt replicas=3
# Deploys BuildKit pods into your Kubernetes cluster
# The 'namespace' option specifies which Kubernetes namespace to use
# 'replicas=3' creates three BuildKit pods for parallel processing
# Requires an active Kubernetes connection (configured kubectl)

Output Types

Container Images

# Output to Docker daemon
docker buildx build --output type=docker -t myimage .
# Loads the resulting image directly into the Docker daemon
# Equivalent to the traditional 'docker build' behavior
# Only works with the 'docker' driver or single-platform builds

# Output to registry
docker buildx build --output type=registry -t username/myapp .
# Pushes the image directly to a container registry
# Requires being logged into the registry (docker login)
# Doesn't load the image into the local Docker daemon
# Efficient for CI/CD pipelines that push directly to registries

# Output to local image
docker buildx build --load -t myimage .
# Imports the built image into Docker's local image store
# Shorthand for '--output type=docker'
# Allows immediate use with 'docker run' after building

Files and Directories

# Output to local directory
docker buildx build --output type=local,dest=./output .
# Instead of creating a container image, exports the build result to a directory
# Useful for extracting compiled binaries or static files from the build
# Perfect for build workflows that need artifacts rather than full images

# Output to tar file
docker buildx build --output type=tar,dest=./image.tar .
# Creates a tarball containing the build result
# Can be transported between systems and loaded manually
# Useful for air-gapped environments or custom distribution methods

CI/CD Integration

Build Groups and Concurrent Builds

# Create a build group using bake file
docker buildx bake --file docker-bake.hcl
# Reads build configurations from the HCL or JSON file
# Executes all targets defined in the default group
# Handles dependencies between targets automatically
# Similar to Docker Compose but specialized for builds

# Parallel builds with specific targets
docker buildx bake prod dev
# Builds both 'prod' and 'dev' targets simultaneously
# Takes advantage of parallel processing
# Each target can have different build contexts, platforms, tags, etc.
# Dramatically speeds up building multiple related images

Bake Files

HCL Format (docker-bake.hcl)

group "default" {
  targets = ["app", "worker"]
}

target "app" {
  dockerfile = "Dockerfile.app"
  tags = ["myapp:latest"]
  platforms = ["linux/amd64", "linux/arm64"]
}

target "worker" {
  dockerfile = "Dockerfile.worker"
  tags = ["myworker:latest"]
  args = {
    WORKER_VERSION = "1.0"
  }
}

JSON Format (docker-bake.json)

{
  "group": {
    "default": {
      "targets": ["app", "worker"]
    }
  },
  "target": {
    "app": {
      "dockerfile": "Dockerfile.app",
      "tags": ["myapp:latest"],
      "platforms": ["linux/amd64", "linux/arm64"]
    },
    "worker": {
      "dockerfile": "Dockerfile.worker",
      "tags": ["myworker:latest"],
      "args": {
        "WORKER_VERSION": "1.0"
      }
    }
  }
}

Buildx Performance Tips

Advanced Techniques

SSH Mounting

# Clone private repository using SSH key
FROM alpine
RUN --mount=type=ssh mkdir -p -m 0700 ~/.ssh && \
    ssh-keyscan github.com >> ~/.ssh/known_hosts && \
    git clone git@github.com:username/private-repo.git
# The --mount=type=ssh exposes the host's SSH agent to the build process
# Requires passing --ssh default when running buildx build
# Example: docker buildx build --ssh default=~/.ssh/id_rsa --no-cache .
# No SSH keys are stored in the image, maintaining security

Cache Mounts

# Cache package manager
RUN --mount=type=cache,target=/var/cache/apt \
    apt-get update && apt-get install -y package
# Creates a persistent cache volume mounted at /var/cache/apt
# Cache persists between builds, significantly speeding up package installations
# Does not affect the final image size - cache exists only during build
# Multiple builds can share the same cache concurrently
# Unlike volume mounts in regular Docker, this is build-specific

Temporary Mounts

# Use temporary bind mount
RUN --mount=type=bind,source=./config,target=/config \
    cp /config/app.conf /etc/app/config.conf
# Mounts the ./config directory from build context into /config in container
# Files can be read and copied but don't become part of any layer
# Useful for configuration files, templates, or any content needed only during build
# The readonly option can be added for additional security: type=bind,source=./config,target=/config,readonly

Troubleshooting

Best Practices

Efficiency

  • Use appropriate caching strategies based on your workflow patterns
  • Implement multi-stage builds to minimize final image size
  • Order instructions by change frequency (least to most frequent)
  • Leverage build contexts efficiently by using .dockerignore files
  • Optimize Dockerfile instructions by combining commands where appropriate
  • Use BuildKit's parallelization capabilities by structuring independent operations
  • Benchmark different build configurations to find optimal settings
  • Consider layer reuse patterns in your development workflow

CI/CD Integration

  • Implement matrix builds for testing across multiple platforms
  • Use distributed caching with registry or CI-specific caches
  • Share cache between pipeline runs to speed up repeated builds
  • Parallelize build steps using bake files and multiple targets
  • Choose appropriate output types (registry for CI, docker for local testing)
  • Implement proper tagging strategies for build artifacts
  • Set up automated testing of built images
  • Create dedicated builder instances for CI/CD environments
  • Design pipelines to leverage incremental builds

Security

  • Scan built images with tools like Trivy, Clair, or Snyk
  • Use secrets appropriately with --mount=type=secret
  • Implement least privilege principles in both build and runtime
  • Control build arguments to avoid leaking sensitive information
  • Validate build contexts from external sources
  • Use SSH forwarding instead of embedding keys
  • Implement proper signing and verification of images
  • Audit Dockerfiles for security best practices
  • Maintain a secure base image strategy with regular updates
  • Implement runtime security controls for containers

Migration from Legacy Build