Skip to content
Fondazione ITS INCOM

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

Exercise

All examples