Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
openaec-foundation avatar

Docker Syntax Multistage

  • 8 installs
  • 9 repo stars
  • Updated July 8, 2026
  • openaec-foundation/docker-claude-skill-package

Helps with devops & ci/cd tasks.

About

docker-syntax-multistage is a Claude Code skill for devops & ci/cd. It helps solo builders move faster with AI-assisted development.

  • docker-syntax-multistage
  • DevOps & CI/CD
  • AI-coding skill

Docker Syntax Multistage by the numbers

  • 8 all-time installs (skills.sh)
  • Ranked #1,044 of 1,435 DevOps & CI/CD skills by installs in the Skillselion catalog
  • Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/openaec-foundation/docker-claude-skill-package --skill docker-syntax-multistage

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs8
repo stars9
Last updatedJuly 8, 2026
Repositoryopenaec-foundation/docker-claude-skill-package

What it does

Helps with devops & ci/cd tasks.

Files

SKILL.mdMarkdownGitHub ↗

docker-syntax-multistage

Quick Reference

Multi-Stage Build Concept

A multi-stage build uses multiple FROM instructions in a single Dockerfile. Each FROM starts a new stage. Only the final stage (or the --target stage) produces the output image. Earlier stages exist solely to generate artifacts that are copied into later stages.

Stage Types

Stage TypePurposeFinal Image?
BuilderCompile code, run bundlers, generate artifactsNo
TestRun test suites, linting, static analysisNo
DependenciesInstall and cache shared dependenciesNo
ProductionMinimal runtime with only required artifactsYes
DebugProduction + debugging toolsYes (dev only)

Image Size Impact

LanguageWithout Multi-StageWith Multi-StageReduction
Go~800 MB (golang:1.22)~0 MB (scratch) or ~7 MB (alpine)99%
Node.js~1.1 GB (node:20)~180 MB (node:20-slim)83%
Python~1.0 GB (python:3.12)~150 MB (python:3.12-slim)85%
Java~700 MB (eclipse-temurin:21-jdk)~220 MB (eclipse-temurin:21-jre)69%
Rust~1.4 GB (rust:1.77)~0 MB (scratch) or ~7 MB (alpine)99%
.NET~900 MB (mcr.microsoft.com/dotnet/sdk:8.0)~220 MB (mcr.microsoft.com/dotnet/aspnet:8.0)76%

Final Stage Base Image Selection

Base ImageSizeUse When
scratch0 MBStatically compiled binaries (Go, Rust with musl)
alpine:3.19~7 MBNeed a shell and minimal OS utilities
gcr.io/distroless/static-debian12~2 MBStatic binaries without shell access
gcr.io/distroless/base-debian12~20 MBBinaries needing glibc but no shell
*-slim variants30-80 MBNeed package manager for runtime deps

Critical Warnings

ALWAYS use multi-stage builds for production images. Single-stage builds ship compilers, source code, and build tools to production -- a security risk and a waste of space.

ALWAYS name stages with AS <name>. NEVER reference stages by numeric index (--from=0) because indexes break when stages are added or removed.

NEVER install build tools (gcc, make, npm devDependencies) in the final production stage. Build tools belong in the builder stage only.

NEVER copy the entire build stage filesystem into the production stage. ALWAYS copy only the specific artifacts needed (binaries, compiled assets, config files).

ALWAYS include # syntax=docker/dockerfile:1 as the first line to enable BuildKit features including parallel stage execution.

---

Core Syntax

FROM ... AS (Stage Naming)

FROM <image>[:<tag>] AS <stage-name>

Every stage MUST have a descriptive name. Names are case-insensitive but ALWAYS use lowercase by convention.

FROM golang:1.22 AS build
FROM alpine:3.19 AS runtime
FROM build AS test

COPY --from (Artifact Extraction)

# Copy from a named stage
COPY --from=<stage-name> <src> <dest>

# Copy from an external image (auto-pulled)
COPY --from=<image>:<tag> <src> <dest>

Examples:

# From a build stage
COPY --from=build /app/binary /usr/local/bin/app

# From an external image
COPY --from=nginx:1.25 /etc/nginx/nginx.conf /etc/nginx/nginx.conf

# Multiple artifacts from different stages
COPY --from=build-backend /app/server /usr/local/bin/server
COPY --from=build-frontend /app/dist /var/www/html

--target (Partial Builds)

Build only a specific stage and its dependencies:

# Build only the test stage
docker build --target test -t myapp:test .

# Build only the debug stage
docker build --target debug -t myapp:debug .

# Build the default (last) stage
docker build -t myapp:latest .

BuildKit optimization: when using --target, BuildKit ONLY builds the target stage and stages it depends on. Unrelated stages are skipped entirely.

---

Decision Tree

When to Use Multi-Stage

Need to build/compile code in the container?
  YES --> Use multi-stage (builder + runtime)
  NO  --> Does the image include dev dependencies or build tools?
    YES --> Use multi-stage to separate them
    NO  --> Single stage MAY be acceptable for simple runtime images

Is the final image > 500 MB?
  YES --> Multi-stage with a minimal base will likely reduce it significantly
  NO  --> Still consider multi-stage for security (no build tools in production)

Choosing the Final Stage Base

Is the binary statically compiled? (Go with CGO_ENABLED=0, Rust with musl)
  YES --> Use `scratch` or `gcr.io/distroless/static-debian12`
  NO  --> Does it need glibc?
    YES --> Does it need a shell for debugging?
      YES --> Use `alpine` or `*-slim` variant
      NO  --> Use `gcr.io/distroless/base-debian12`
    NO  --> Use `alpine`

Does the runtime need a language runtime? (Node, Python, Java, .NET)
  YES --> Use the slim/JRE variant of that runtime
  NO  --> Use alpine or distroless

---

Patterns

1. Basic Builder Pattern

The foundation of all multi-stage builds. Build in a full SDK image, run in a minimal image.

# syntax=docker/dockerfile:1

FROM golang:1.22 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app/server ./cmd/server

FROM alpine:3.19 AS production
RUN addgroup -S app && adduser -S app -G app
COPY --from=build /app/server /usr/local/bin/server
USER app
ENTRYPOINT ["/usr/local/bin/server"]

2. Build + Test + Production Pipeline

Run tests as a build gate. The production stage only depends on the build stage, so test failures do not affect the production image -- but CI pipelines MUST target the test stage first.

# syntax=docker/dockerfile:1

FROM golang:1.22 AS build
WORKDIR /src
COPY . .
RUN go build -o /app/server ./cmd/server

FROM build AS test
RUN go test -v -race ./...

FROM alpine:3.19 AS production
COPY --from=build /app/server /usr/local/bin/server
USER nobody:nobody
ENTRYPOINT ["/usr/local/bin/server"]

CI usage -- ALWAYS build test target before production:

docker build --target test .
docker build --target production -t myapp:latest .

3. Shared Dependency Stage

When multiple stages need the same dependencies, create a shared base to avoid duplication.

# syntax=docker/dockerfile:1

FROM node:20-slim AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --ignore-scripts

FROM deps AS build
COPY . .
RUN npm run build

FROM deps AS test
COPY . .
RUN npm run test

FROM node:20-slim AS production
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY package.json ./
USER node
CMD ["node", "dist/index.js"]

4. Parallel Build Stages

BuildKit automatically parallelizes independent stages. Design your Dockerfile to maximize parallelism.

# syntax=docker/dockerfile:1

FROM node:20-slim AS frontend-build
WORKDIR /frontend
COPY frontend/package.json frontend/package-lock.json ./
RUN npm ci
COPY frontend/ .
RUN npm run build

FROM golang:1.22 AS backend-build
WORKDIR /backend
COPY backend/go.mod backend/go.sum ./
RUN go mod download
COPY backend/ .
RUN CGO_ENABLED=0 go build -o /server ./cmd/server

FROM alpine:3.19 AS production
COPY --from=backend-build /server /usr/local/bin/server
COPY --from=frontend-build /frontend/dist /var/www/html
USER nobody:nobody
ENTRYPOINT ["/usr/local/bin/server"]

frontend-build and backend-build execute simultaneously because neither depends on the other.

5. Debug Stage Pattern

Add debugging tools without polluting the production image:

# syntax=docker/dockerfile:1

FROM golang:1.22 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /app/server ./cmd/server

FROM alpine:3.19 AS production
COPY --from=build /app/server /usr/local/bin/server
USER nobody:nobody
ENTRYPOINT ["/usr/local/bin/server"]

FROM production AS debug
USER root
RUN apk add --no-cache curl strace busybox-extras
USER nobody:nobody
# Production: lean
docker build -t myapp:latest .

# Debug: with tools
docker build --target debug -t myapp:debug .

6. Cross-Platform Build Pattern

Use BuildKit platform ARGs for multi-architecture builds:

# syntax=docker/dockerfile:1

FROM --platform=$BUILDPLATFORM golang:1.22 AS build
ARG TARGETOS TARGETARCH
WORKDIR /src
COPY . .
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 \
    go build -o /app/server ./cmd/server

FROM alpine:3.19
COPY --from=build /app/server /usr/local/bin/server
ENTRYPOINT ["/usr/local/bin/server"]
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest .

---

Reference Links

  • references/patterns.md -- Complete multi-stage patterns with full Dockerfiles
  • references/examples.md -- Language-specific multi-stage examples (Node, Python, Go, Java, Rust, .NET)
  • references/anti-patterns.md -- Multi-stage mistakes and how to fix them

Official Sources

  • https://docs.docker.com/build/building/multi-stage/
  • https://docs.docker.com/reference/dockerfile/
  • https://docs.docker.com/build/building/best-practices/
  • https://docs.docker.com/build/buildkit/

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.