Writing Dockerfiles
A Dockerfile for a Flask app
FROM python:3.12-slim
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1
WORKDIR /app
# 1. dependencies first (cached unless requirements change)
COPY requirements.txt .
RUN pip install -r requirements.txt
# 2. then the source code (changes often)
COPY . .
ENV PORT=8000
EXPOSE 8000
CMD ["gunicorn", "wsgi:app", "-c", "gunicorn.conf.py"]
docker build -t myapp:dev .
docker run --rm -p 8000:8000 --env-file .env myapp:dev
Layers and the build cache
Each instruction creates a layer. Docker reuses cached layers until something changes, then rebuilds everything after it. Copying requirements.txt and installing before copying the code means a code change does not reinstall every package, turning a 3-minute build into 5 seconds.
.dockerignore
Keep junk and secrets out of the build context:
.git
.venv
__pycache__/
*.pyc
.env
*.db
node_modules/
uploads/
tests/
Without it, COPY . . can bake your .env file into the image, where anyone with the image can read it.
Instructions you will use
| Instruction | Purpose |
|---|---|
FROM |
base image |
WORKDIR |
working directory |
COPY |
copy files into the image |
RUN |
run a command at build time |
ENV |
environment variable |
EXPOSE |
document the listening port |
USER |
run as a non-root user |
CMD |
default command when the container starts |
HEALTHCHECK |
how to tell if the app is healthy |
Use the exec form CMD ["gunicorn", ...] (a JSON array) so signals reach your app and it shuts down gracefully.
Choosing a base image
python:3.12-slim: small Debian-based image; the best default.python:3.12-alpine: smaller, but uses musl libc, so many Python packages must compile from source. Often slower to build and occasionally incompatible.- Pin the version (
3.12-slim, notlatest) so builds are reproducible.
Exercise
Containerise a small Flask app with a .dockerignore, build it, run it with an env file, change a template and confirm the rebuild reuses the dependency layer.
Check yourself
- Why copy
requirements.txtbefore the rest of the code? - What can happen without a
.dockerignore? - Why prefer the exec form of
CMD?
Votre progression est enregistrée dans ce navigateur uniquement.
Envoyer pour relecture (10 points)