Building Production-Ready Docker Images in CI: Multi-Stage Builds, Buildx, and Automated Tagging
For many teams, containerization starts with a simple command:

Build smarter Docker images: smaller, faster, traceable, and ready for every platform.
Building Production-Ready Docker Images in CI: Multi-Stage Builds, Buildx, and Automated Tagging
For many teams, containerization starts with a simple command:
docker build -t my-app .
The image builds successfully, gets pushed to a registry, and eventually reaches production.
Job done.
Or is it?
As applications grow and deployment pipelines mature, teams often encounter new challenges:
- Container images become unnecessarily large
- Tags become difficult to track
- Multiple CPU architectures need support
- Build times increase
- Debugging deployments becomes harder
The reality is that building a Docker image is easy.
Building a production-ready Docker image pipeline is a different challenge altogether.
In this article, we’ll explore how to use multi-stage Docker builds, Docker Buildx, and automated metadata generation to create smaller, traceable, and deployment-friendly container images in CI.
Why Image Build Strategy Matters
Consider a common Dockerfile:
FROM node:20
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["npm", "start"]
This works.
But it often produces images that contain:
- Build dependencies
- Source files
- Package managers
- Temporary artifacts
Everything used during the build ends up inside the final image.
The result?
Large Image
↓
Slower Pulls
↓
Longer Deployments
↓
Higher Storage Costs
A better strategy is to separate build-time requirements from runtime requirements.
Multi-Stage Builds: Build Once, Ship Less
Multi-stage builds allow you to use multiple Docker images within a single Dockerfile.
A typical pattern looks like:
Build Stage
↓
Compile Application
↓
Copy Artifacts
↓
Runtime Stage
Only the final runtime artifacts are included in the production image.
A Practical Example
Instead of:
FROM node:20
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["npm", "start"]
Use:
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
The result:
Builder Image
↓
Contains Tooling
↓
Production Image
↓
Contains Only Static Assets
This often reduces image size dramatically.
Real-World Impact
A frontend application might produce:
ApproachImage SizeSingle Stage900 MBMulti-Stage90 MB
That’s a 10x reduction.
Benefits include:
- Faster deployments
- Lower bandwidth usage
- Smaller attack surface
- Reduced storage costs
These improvements become significant at scale.
Why Traditional Docker Builds Fall Short
Historically, Docker builds targeted a single platform:
docker build .
This works when all infrastructure uses the same architecture.
But today’s environments often include:
- AMD64 cloud servers
- ARM-based instances
- Apple Silicon developer machines
- Edge devices
Building separate images for each platform quickly becomes difficult to manage.
Enter Docker Buildx
Buildx extends Docker’s build capabilities and enables:
- Multi-platform builds
- Advanced caching
- Faster builds
- Improved reproducibility
Think of it as:
docker build
+
Modern Build Features
=
docker buildx
Building Multi-Platform Images
With Buildx:
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t my-app:1.0.0 \
--push .
A single command produces:
linux/amd64
linux/arm64
under the same image tag.
Consumers pull the correct architecture automatically.
Why Multi-Platform Images Matter
Imagine a development team using:
MacBook M3
↓
ARM64
while production runs:
AWS EC2
↓
AMD64
Without multi-platform builds:
Works Locally
↓
Fails in Production
Buildx helps eliminate architecture-related surprises.
The Problem with Poor Tagging
One of the most common container management issues is:
latest
Ask yourself:
What exactly is running in production?
If the answer is:
my-app:latest
you don’t actually know.
The tag may point to different images over time.
Better Tagging Strategies
A more reliable approach combines:
- Semantic versions
- Git commit SHAs
- Branch information
Example:
my-app:v2.3.1
and:
my-app:8f4e2d7
and:
my-app:main
Multiple tags provide flexibility while maintaining traceability.

One build, multiple architectures, complete traceability from commit to production.
Real-World Tagging Example
Suppose a release is built from:
Version: 2.3.1
Commit:
8f4e2d7
Generated tags:
my-app:v2.3.1
my-app:2.3
my-app:8f4e2d7
my-app:latest
Now teams can:
- Deploy specific versions
- Roll back quickly
- Trace deployments to source code
Automating Metadata Generation
Managing tags manually becomes tedious.
GitHub Actions can generate image metadata automatically.
A popular approach uses:
- name: Extract Docker Metadata
uses: docker/metadata-action@v5
with:
images: ghcr.io/my-org/my-app
The action automatically creates tags based on:
- Git tags
- Branches
- Pull requests
- Commit SHAs
This removes much of the manual work.
Building Images in GitHub Actions
A production-ready workflow often looks like:
name: Build Container
on:
push:
branches:
- main
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set Up Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker Metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/my-org/my-app
- name: Build and Push
uses: docker/build-push-action@v6
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
This workflow automatically:
- Builds images
- Generates metadata
- Creates tags
- Supports multiple architectures
- Pushes to a registry
Adding Useful OCI Labels
Tags identify images.
Labels provide additional context.
Example:
labels:
org.opencontainers.image.source=https://github.com/org/repo
org.opencontainers.image.version=2.3.1
org.opencontainers.image.revision=8f4e2d7
Now image metadata includes:
Repository
Version
Commit SHA
Build Source
This becomes valuable during troubleshooting and audits.
Integrating with Artifact Traceability
A mature container pipeline often produces:
Docker Image
+
Version Metadata
+
SBOM
+
Vulnerability Scan Results
Everything becomes traceable back to:
Git Commit
↓
CI Build
↓
Production Deployment
This aligns closely with modern software supply chain security practices.
Common Mistakes to Avoid
Building Huge Images
If build tools end up inside production images, you’re likely missing multi-stage builds.
Using Only latest
latest is convenient.
It is not traceable.
Always include immutable version tags.
Ignoring Multi-Platform Support
Modern environments increasingly mix AMD64 and ARM64 workloads.
Buildx makes supporting both architectures straightforward.
Manually Managing Tags
Automated metadata generation reduces human error and improves consistency.
Missing Build Metadata
Without labels and version information:
Which source code created this image?
becomes difficult to answer.
A Production-Ready Container Pipeline
A mature container workflow often looks like:
Source Code
↓
Quality Checks
↓
Dockerfile Linting
↓
Multi-Stage Build
↓
Buildx Multi-Platform Build
↓
Metadata Generation
↓
SBOM Creation
↓
Container Scanning
↓
Registry Push
Each step contributes to reliability, traceability, and security.
Final Thoughts
Building Docker images is no longer just about packaging an application.
Modern CI pipelines must produce images that are:
- Small
- Reproducible
- Multi-platform
- Traceable
- Easy to deploy and roll back
By combining multi-stage builds, Docker Buildx, automated metadata generation, and intelligent tagging strategies, teams can create container artifacts that scale with both engineering and operational requirements.
The best container pipelines don’t just build images — they create trustworthy deployment artifacts that can be traced all the way back to the source code that produced them.
How is your team currently building and tagging Docker images? Are you using Buildx, automated metadata generation, multi-platform builds, or custom tagging strategies? Share your approach and lessons learned in the comments — I’d love to hear how others are evolving their container delivery pipelines.
메타데이터
- post_id
- 7e3dd613ba14
- slug
- building-production-ready-docker-images-in-ci-multi-stage-builds-buildx-and-automated-tagging-7e3dd613ba14
- url
- https://medium.com/@sharathkumarlokesh/building-production-ready-docker-images-in-ci-multi-stage-builds-buildx-and-automated-tagging-7e3dd613ba14
- canonical_url
- https://medium.com/@sharathkumarlokesh/building-production-ready-docker-images-in-ci-multi-stage-builds-buildx-and-automated-tagging-7e3dd613ba14
- author_url
- https://medium.com/@sharathkumarlokesh
- status
- ok
- fetched_at
- 2026-06-10 10:12:36