Examples · Cloud & Cybersecurity
A Dockerfile, reviewed and rewritten
Give Qwen3-Coder a Dockerfile full of classic mistakes, get a security review and a corrected version, then prove the difference with Docker.
Advanced · 60 min
What you need
Docker on your computer, a key and the openai library, as in Your first API call in Python.
The model
Qwen3-Coder 30B (qwen3-coder-30b), the model for programming.
A small app and a bad Dockerfile
app.py:
from flask import Flask
app = Flask(__name__)
@app.get("/")
def hello():
return "Hello from ITS INCOM\n"
Dockerfile, with the mistakes you find in many real projects:
FROM python:latest
COPY . /app
WORKDIR /app
RUN pip install flask
ENV ADMIN_PASSWORD=changeme
EXPOSE 5000 22
CMD flask run --host 0.0.0.0
The review
import os
import pathlib
from openai import OpenAI
client = OpenAI(
base_url="https://api.ai.itsincom.org/v1",
api_key=os.environ["API_KEY"],
)
dockerfile = pathlib.Path("Dockerfile").read_text()
answer = client.chat.completions.create(
model="qwen3-coder-30b",
temperature=0,
messages=[
{"role": "system", "content": "You are a senior DevOps engineer. Be concrete and brief."},
{"role": "user", "content": (
"Review this Dockerfile for a Flask app for security and good practice. For each problem "
"give the line and why it matters. Then write the corrected Dockerfile, with a production "
"server instead of the Flask development server, and a .dockerignore.\n\n" + dockerfile
)},
],
)
print(answer.choices[0].message.content)
Prove it
Rename the old file to Dockerfile.old and save the corrected one as Dockerfile, with its .dockerignore and the requirements.txt it asks for (Flask and gunicorn, with their versions). Build both images and compare:
docker build -t hello:old -f Dockerfile.old .
docker build -t hello:new .
docker images hello
docker run --rm hello:old whoami
docker run --rm hello:new whoami
docker history --no-trunc hello:old | grep ADMIN_PASSWORD
The old one runs as root and keeps the password in its layers, for anyone who downloads the image. If the new one answers root too, the review missed it. When we tried it, the model only listed “add a non-root user” among the extra advice, and left it out of the Dockerfile. Ask it to add the user, build again, and check.
What a good review finds
python:latestchanges under your feet: pin a version, better a slim one (python:3.13-slim).COPY . /appcopies everything,.gitand secret files included: add a.dockerignore.- Flask is not pinned: use a
requirements.txtwith versions. - A password in
ENVstays in the image forever. Pass secrets at run time. EXPOSE 22: there is no SSH in a container, and there should not be.- It runs as root: add a user and
USER. - The Flask development server is not for production: use gunicorn, with the
CMDin exec form (["gunicorn", ...]) so that Docker can stop it cleanly.
Exercise
- Ask the model to add a
HEALTHCHECK, then check it withdocker ps. - Ask for a multi-stage build and compare the sizes in
docker images. - Scan both images with a vulnerability scanner such as Trivy (
trivy image hello:old) and compare the results.
