How to Build Enterprise‑Ready Docker Images in 5 Minutes
This guide walks you through the four essential principles for production Docker images, demonstrates a complete multi‑stage Dockerfile for a Flask app, shows how to tag, build, verify, and deploy with docker‑compose, and warns against unsafe shortcuts like docker commit.
Production Image Core Principles
Reproducible : Anyone can recreate the exact same image from the configuration, eliminating "it works on my machine" issues.
Auditable : Every step is recorded, enabling security audits without extra effort.
Securely Controlled : Run as a non‑root user, manage ports, permissions, and users explicitly.
Small Size : Remove unnecessary dependencies to keep the image lightweight and fast to transfer.
Hands‑on: Build a Production‑grade Flask Image
Step 1 – Prepare project files
Create a working directory and add the source files: mkdir flask-prod-app && cd flask-prod-app app.py (minimal Flask app)
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "This is a production‑grade Docker image!"requirements.txt (pin exact versions)
flask==2.3.3 # web framework
gunicorn==21.2.0 # production WSGI server.dockerignore (exclude unnecessary files)
# version control
.git
.gitignore
# local development artifacts
__pycache__/
*.pyc
.venv
# sensitive files
.env
*.logStep 2 – Multi‑stage Dockerfile
The builder stage installs dependencies; the final stage contains only the runtime environment.
# ===== Builder stage =====
FROM docker.xuanyuan.run/python:3.10-slim AS builder
# Optional: fast Chinese pip mirror
RUN mkdir -p /root/.pip && \
echo "[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple" > /root/.pip/pip.conf
WORKDIR /build
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt -t ./vendor && \
rm -rf /root/.cache/pip
# ===== Final stage =====
FROM docker.xuanyuan.run/python:3.10-slim
# Set timezone and install curl (optional)
RUN apt update && apt install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/* && \
ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo Asia/Shanghai > /etc/timezone && \
useradd -m -u 1001 appuser
USER appuser
WORKDIR /app
COPY --from=builder /build/vendor ./vendor
ENV PYTHONPATH=/app/vendor
COPY --chown=appuser:appuser app.py .
ENV WORKERS=2
EXPOSE 5000
CMD ["sh", "-c", "gunicorn --bind 0.0.0.0:5000 --workers ${WORKERS} --graceful-timeout 30 app:app"]Step 3 – Build and verify the image
Build with an explicit tag (avoid latest): docker build -t flask-prod-app:1.0-prod . Run locally to test:
docker run -d -p 5000:5000 --name flask-test flask-prod-app:1.0-prodCheck the response: curl http://localhost:5000 Verify the container runs as appuser: docker exec -it flask-test whoami Clean up:
docker stop flask-test && docker rm flask-testStep 4 – Deploy with Docker Compose
Compose file enforces the non‑root user, resource limits, and health checks.
version: '3.8'
services:
flask-app:
image: flask-prod-app:1.0-prod
user: 1001
ports:
- "5000:5000"
restart: always
mem_limit: 512m
cpus: 0.5
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:5000/')"]
interval: 30s
timeout: 10s
retries: 3
networks:
- app-net
networks:
app-net:
driver: bridgeDeploy with docker-compose -f docker-compose.prod.yml up -d.
Temporary Scenarios (Never Use in Production)
docker commit : Quick debugging only; lacks reproducibility and audit trail.
docker save/load : Suitable for offline migration; export the image to a tar file, transfer, then load on the target host.
Ops Veteran Red‑Line Checklist
Never run the application as root.
Do not promote images created with docker commit to production.
Avoid exposing ports directly to the internet; use a load balancer or ingress.
Never use the latest tag; always version your images explicitly.
Key Takeaways
Production images should be built with a multi‑stage Dockerfile, run as a non‑root user, and use explicit versioned tags.
Temporary tricks like docker commit or rootfs imports are for debugging only and must not reach production.
Following these practices ensures images pass security audits, stay lightweight, and run reliably in production environments.
Xiao Liu Lab
An operations lab passionate about server tinkering 🔬 Sharing automation scripts, high-availability architecture, alert optimization, and incident reviews. Using technology to reduce overtime and experience to avoid major pitfalls. Follow me for easier, more reliable operations!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
