Docker Build Overview
Docker Build is the feature that allows you to create Docker images from a Dockerfile. Modern Docker builds are powered by BuildKit, which provides improved performance, caching, and features compared to the legacy builder.
How Docker Build Works
When you run docker build, the following process occurs:
┌───────────────────┐
│ Dockerfile │
│ + Build Context │
└────────┬──────────┘
│
▼
┌───────────────────┐ ┌──────────────────────────┐
│ Docker Client │────▶│ BuildKit Backend │
│ (docker build) │ │ │
└───────────────────┘ │ 1. Parse Dockerfile │
│ 2. Create build graph │
│ 3. Execute stages │
│ 4. Cache intermediate │
│ 5. Export final image │
│ │
└────────────┬─────────────┘
│
▼
┌──────────────────────────┐
│ Docker Image │
│ (stored in image store) │
└──────────────────────────┘Build Command
Basic Usage
bash
# Build from current directory
docker build -t my-app:1.0 .
# Build with a specific Dockerfile
docker build -f Dockerfile.prod -t my-app:prod .
# Build with build arguments
docker build --build-arg NODE_ENV=production -t my-app:1.0 .
# Build without cache
docker build --no-cache -t my-app:1.0 .
# Build and show full output
docker build --progress=plain -t my-app:1.0 .
# Build for a specific platform
docker build --platform linux/amd64 -t my-app:1.0 .
# Build and push in one step (using buildx)
docker buildx build --push -t myuser/my-app:1.0 .Build Command Options
| Option | Description | Example |
|---|---|---|
-t, --tag | Name and tag for the image | -t my-app:1.0 |
-f, --file | Path to Dockerfile | -f Dockerfile.prod |
--build-arg | Set build-time variable | --build-arg VERSION=2.0 |
--no-cache | Do not use cache | --no-cache |
--pull | Always pull base image | --pull |
--target | Set target build stage | --target production |
--platform | Set target platform | --platform linux/amd64 |
--progress | Set output type | --progress=plain |
--secret | Expose a secret to the build | --secret id=key,src=key.pem |
--ssh | SSH agent forwarding | --ssh default |
--cache-from | External cache source | --cache-from type=registry,ref=cache:latest |
--cache-to | External cache destination | --cache-to type=registry,ref=cache:latest |
--output | Output destination | --output type=local,dest=./out |
--load | Load into Docker images | --load |
--push | Push to registry | --push |
Build Context
The build context is the set of files sent to the Docker daemon for the build. By default, it is the current directory.
Context Types
bash
# Local directory (most common)
docker build -t my-app:1.0 .
# Local directory with specific path
docker build -t my-app:1.0 /path/to/project
# Git repository
docker build -t my-app:1.0 https://github.com/user/repo.git
# Git with specific branch/tag
docker build -t my-app:1.0 https://github.com/user/repo.git#main
# Tarball URL
docker build -t my-app:1.0 https://example.com/context.tar.gz
# Stdin (no context)
docker build -t my-app:1.0 - < Dockerfile
# Stdin with context from tar
tar czf - . | docker build -t my-app:1.0 -.dockerignore
The .dockerignore file excludes files from the build context:
# .dockerignore
# Version control
.git
.gitignore
.svn
# Dependencies
node_modules
vendor
__pycache__
# IDE and editor files
.vscode
.idea
*.swp
*.swo
# Build artifacts
dist
build
*.o
*.a
# Docker files
Dockerfile*
docker-compose*.yml
.dockerignore
# Documentation
*.md
docs/
LICENSE
# Test files
tests/
test/
coverage/
.nyc_output/
# Environment and secrets
.env
.env.*
*.pem
*.key
secrets/
# OS files
.DS_Store
Thumbs.dbContext Size Impact
| Context Size | Build Time Impact | Recommendation |
|---|---|---|
| < 10 MB | Minimal | Good |
| 10-100 MB | Noticeable | Optimize .dockerignore |
| 100+ MB | Significant | Must optimize |
| 1+ GB | Very slow | Critical issue |
bash
# Check your build context size
du -sh --exclude=.git .
# See what's being sent as context
docker build --no-cache --progress=plain -t test . 2>&1 | head -5Docker Buildx
Docker Buildx is an extended build tool that provides additional features on top of BuildKit:
bash
# Check buildx is available
docker buildx version
# List builders
docker buildx ls
# Create a new builder
docker buildx create --name mybuilder --use
# Inspect a builder
docker buildx inspect mybuilder
# Build for multiple platforms simultaneously
docker buildx build \
--platform linux/amd64,linux/arm64,linux/arm/v7 \
-t myuser/my-app:1.0 \
--push .Multi-platform Builds
bash
# Create a multi-platform builder
docker buildx create --name multiplatform --driver docker-container --use
# Build for multiple architectures
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t myuser/my-app:1.0 \
--push .
# Inspect the multi-platform manifest
docker buildx imagetools inspect myuser/my-app:1.0Platform Support Matrix
| Platform | Architecture | Common Use Case |
|---|---|---|
linux/amd64 | x86_64 | Standard servers, Intel/AMD desktops |
linux/arm64 | ARM 64-bit | AWS Graviton, Apple Silicon, Raspberry Pi 4 |
linux/arm/v7 | ARM 32-bit | Raspberry Pi 3, older ARM devices |
linux/arm/v6 | ARM 32-bit | Raspberry Pi Zero/1 |
linux/386 | x86 32-bit | Legacy systems |
linux/s390x | IBM Z | IBM mainframes |
linux/ppc64le | PowerPC | IBM Power systems |
Build Output Types
bash
# Load into local Docker images (default)
docker buildx build --load -t my-app:1.0 .
# Push directly to registry
docker buildx build --push -t myuser/my-app:1.0 .
# Export as a tar archive
docker buildx build --output type=tar,dest=image.tar .
# Export to local directory
docker buildx build --output type=local,dest=./output .
# Export as OCI image layout
docker buildx build --output type=oci,dest=image-oci.tar .
# Create image but don't export (cache only)
docker buildx build --output type=cacheonly .Build Arguments and Variables
ARG vs ENV
| Feature | ARG | ENV |
|---|---|---|
| Available during build | ✅ Yes | ✅ Yes |
| Available at runtime | ❌ No | ✅ Yes |
| Can be overridden at build | ✅ Yes (--build-arg) | ❌ No (set in Dockerfile) |
| Visible in image history | ✅ Yes (⚠️ security risk) | ✅ Yes |
| Scope | From definition to end of stage | From definition to container |
dockerfile
# ARG: Build-time only
ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-alpine
# ARG must be redeclared after FROM
ARG APP_VERSION=1.0
# ENV: Available at build and runtime
ENV NODE_ENV=production
ENV APP_VERSION=${APP_VERSION}
RUN echo "Building version ${APP_VERSION}"
COPY . .
CMD ["node", "server.js"]bash
# Override build arguments
docker build --build-arg NODE_VERSION=18 --build-arg APP_VERSION=2.0 -t my-app .Build Secrets
dockerfile
# syntax=docker/dockerfile:1
FROM node:20-alpine
WORKDIR /app
COPY package.json package-lock.json ./
# Mount a secret file during build (not stored in image)
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
npm ci --only=production
COPY . .
CMD ["node", "server.js"]bash
# Pass the secret during build
docker build --secret id=npmrc,src=.npmrc -t my-app:1.0 .SSH Forwarding
dockerfile
# syntax=docker/dockerfile:1
FROM alpine:3.19
RUN apk add --no-cache git openssh-client
# Use SSH agent forwarding to clone private repos
RUN --mount=type=ssh \
git clone [email protected]:private/repo.git /appbash
# Build with SSH forwarding
docker build --ssh default -t my-app:1.0 .Next Steps
- BuildKit Guide — Deep dive into BuildKit features
- Build Optimization — Optimize build performance
- Build Cache — Master build caching strategies
- Multi-stage Builds — Reduce image sizes
- Image Building Best Practices — Production-ready images