By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
A hyper-practical, zero-fluff guide for engineers who need to write production-grade Dockerfiles—fast.
A Dockerfile is the blueprint for your container. It defines: - What OS and dependencies your app runs on (FROM, RUN).- How files get into the container (COPY).- What command runs when the container starts (CMD, ENTRYPOINT).
FROM
RUN
COPY
CMD
ENTRYPOINT
Why this matters in production:- Security: A poorly written Dockerfile can expose secrets, bloat attack surfaces, or run as root.- Performance: Unoptimized layers waste disk space, slow down builds, and increase CI/CD pipeline time.- Reliability: If CMD and ENTRYPOINT conflict, your container might fail silently or behave unpredictably.- Cost: Bloated images cost more in storage, bandwidth, and deployment time.
root
Real-world scenario:You inherit a legacy Python app with a 2GB Docker image. The Dockerfile installs every dependency under the sun, copies the entire repo (including .git), and runs as root. Your job: 1. Shrink the image to <200MB.2. Remove secrets accidentally baked into layers.3. Ensure the app starts reliably in Kubernetes.
Dockerfile
.git
This guide will show you how.
alpine
ubuntu
python:3.9-slim
python:3.9
-slim
python:3.9.18-slim
latest
apt-get install
pip install
&&
RUN apt-get update && apt-get install -y curl
&& rm -rf /var/lib/apt/lists/*
USER
COPY ./app /app
.dockerignore
node_modules
ADD
Permission denied
docker run
CMD python app.py
CMD ["python", "app.py"]
SIGTERM
["python", "app.py"]
CMD ["--port", "8080"]
Task: Containerize a Python Flask app with these requirements: - Base image: python:3.9-slim.- Install dependencies from requirements.txt.- Copy only the app code (not .git or __pycache__).- Run as a non-root user.- Start the app on port 5000.
requirements.txt
__pycache__
5000
docker --version
/my-flask-app ├── app.py ├── requirements.txt └── .dockerignore
# .dockerignore .git __pycache__ *.pyc .env
# Dockerfile # 1. Use a pinned, slim base image FROM python:3.9.18-slim # 2. Set environment variables (optional but recommended) ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 # 3. Create and switch to a non-root user RUN useradd -m appuser && \ mkdir /app && \ chown appuser:appuser /app USER appuser WORKDIR /app # 4. Install dependencies (clean up in the same layer) COPY --chown=appuser:appuser requirements.txt .RUN pip install --no-cache-dir -r requirements.txt # 5. Copy app code COPY --chown=appuser:appuser . . # 6. Set the entrypoint and default command ENTRYPOINT ["python"] CMD ["app.py"]
docker build -t my-flask-app:1.0 .
docker run -p 5000:5000 --name flask-app my-flask-app:1.0
bash docker logs flask-app
bash curl http://localhost:5000
docker scan my-flask-app:1.0
docker secret
.env
python:3.9.18
docker run my-flask-app --port 8080
docker stop
docker logs
HEALTHCHECK
HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost:5000/health || exit 1
apt
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
COPY . .
Typical question patterns:1. Layer caching: "Which Dockerfile order optimizes build cache?" - ❌ COPY . . → RUN pip install (invalidates cache on every code change). - ✅ COPY requirements.txt . → RUN pip install → COPY . . (cache-friendly).
RUN pip install
COPY requirements.txt .
"What happens if you run docker run my-image --help?"
docker run my-image --help
ENTRYPOINT ["python"]
CMD ["app.py"]
python app.py --help
python --help
Security:
USER 1000
RUN chmod 777 /app
Key trap distinctions:- COPY vs ADD: ADD auto-extracts tar/URLs, but COPY is more predictable.- Shell form (CMD python app.py) vs exec form (CMD ["python", "app.py"]): Exec form handles signals properly.
Task: Fix this broken Dockerfile:
FROM ubuntu:latest RUN apt-get update && apt-get install -y python3 COPY . /app CMD python3 /app/app.py
Problems to fix:1. Uses latest tag.2. Runs as root.3. No cleanup after apt-get.4. No .dockerignore.
apt-get
Solution:
FROM ubuntu:22.04 RUN apt-get update && \ apt-get install -y --no-install-recommends python3 && \ rm -rf /var/lib/apt/lists/* && \ useradd -m appuser USER appuser WORKDIR /app COPY --chown=appuser:appuser . .CMD ["python3", "app.py"]
Why it works:- Pinned Ubuntu version (22.04).- Cleaned up apt cache in the same layer.- Runs as non-root user.- Uses exec form for CMD.
22.04
FROM python:3.9.18-slim
COPY --chown=user:user . /app
WORKDIR
WORKDIR /app
ENV
ENV PYTHONUNBUFFERED=1
HEALTHCHECK CMD curl -f http://localhost
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.