Chapter 07 • Image Engineering

Building & Publishing Container Images

Modern container workflows go far beyond simple docker build invocations. DevOps engineers must leverage the BuildKit engine for parallel stage caching, construct multi-platform binaries across ARM64 and AMD64 with docker buildx, and publish cryptographically signed manifests to cloud registries.

1. The Build Context & .dockerignore

When you run docker build -t my-app ., the final dot (.) specifies the build context. Before building the first layer, the Docker CLI bundles every file in that directory into a tarball and transfers it across the UNIX socket to the daemon.

If your project contains a node_modules/ folder or .git/ repository, uploading the unpruned context can add hundreds of megabytes of latency and accidentally bake sensitive secrets into image layers. Always place a strict .dockerignore in your root directory:

# Comprehensive Production .dockerignore
**/.git
**/.gitignore
**/.github
**/.vscode
**/.idea

# Dependency directories (must be installed inside container)
node_modules/
vendor/
.venv/
__pycache__/
*.pyc

# Sensitive environment credentials (CRITICAL)
.env
.env.*
*.pem
*.key
credentials.json

# Local build artifacts and test coverage
dist/
build/
.next/
coverage/
*.log

2. Next-Gen Builds with BuildKit

BuildKit is Docker's modern build engine. It delivers substantial speed improvements over the legacy builder:

  • Parallel Execution: Independent build stages compile simultaneously across multiple CPU threads.
  • Dead Code Elimination: BuildKit automatically skips any intermediate Dockerfile stages that don't contribute to the final target image.
  • Secret Mounts (--mount=type=secret): Allows build commands to access private SSH keys or API tokens without leaking them into image layers.
  • Persistent Package Cache Mounts: Keeps package manager caches (npm, pip, cargo, apt) across builds without bloating the image.
# Enable BuildKit explicitly (enabled by default in modern Docker):
export DOCKER_BUILDKIT=1

# Example: Using cache mounts inside Dockerfile for 10x faster pip installs:
# RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt

3. Multi-Architecture Images with docker buildx

Today's computing environment is heterogeneous: developers often work on ARM64 Apple Silicon Macs, while cloud Kubernetes nodes frequently run AMD64 (x86_64) Intel/AMD servers. An image compiled solely on ARM64 will crash with exec format error on AMD64 servers.

Using Docker Buildx (powered by QEMU emulation), you can build a unified multi-architecture manifest list that automatically runs natively on both architectures:

# Step 1: Create and switch to a custom multi-architecture builder
docker buildx create --name enterprise-builder --driver docker-container --use
docker buildx inspect --bootstrap

# Step 2: Build and push multi-arch images simultaneously to Docker Hub
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myusername/ecommerce-api:v1.2.0 \
  -t myusername/ecommerce-api:latest \
  --push .
How Multi-Arch Works: Docker Hub stores a high-level OCI Index Manifest. When an ARM64 server pulls myusername/ecommerce-api:latest, Docker automatically downloads the ARM64 layers. When an AMD64 server pulls the identical tag, it receives the AMD64 layers!

4. Authenticating & Publishing to Cloud Registries

Enterprise workflows deploy images to managed registries such as GitHub Container Registry (GHCR)or AWS Elastic Container Registry (ECR):

A. GitHub Container Registry (ghcr.io)
# Login using Personal Access Token (PAT) with write:packages permission
echo "$CR_PAT" | docker login ghcr.io -u GITHUB_USERNAME --password-stdin

# Tag and push
docker tag my-api:latest ghcr.io/my-org/my-api:v1.0.0
docker push ghcr.io/my-org/my-api:v1.0.0
B. Amazon Web Services (AWS ECR)
# Retrieve temporary authorization token and authenticate Docker to AWS ECR
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com

# Tag and push to private repository
docker tag my-api:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-api:v1.0.0
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-api:v1.0.0

Next Up: Container Lifecycle & Runtime Flags

In Chapter 8, explore container process state machines, automated restart policies, and CPU/memory quotas.

Chapter 08: Container Lifecycle & Options →

Explore Related Tools

Hand-picked utilities and calculators related to this tool.

Related Tools