Python > Deployment and Distribution > Containerization > Creating Dockerfiles for Python Applications
Dockerfile for a Flask Application with Multi-Stage Build
This snippet demonstrates a Dockerfile using a multi-stage build to create a smaller and more secure image for a Flask application.
Dockerfile Content
FROM python:3.9-slim-buster AS builder
: Defines the first stage, named 'builder', using a Python base image.
WORKDIR /app
: Sets the working directory in the first stage.
COPY requirements.txt .
: Copies the requirements file to the working directory in the first stage.
RUN pip install --no-cache-dir -r requirements.txt
: Installs the Python dependencies in the first stage.
COPY . .
: Copies the application code to the working directory in the first stage.
FROM python:3.9-slim-buster
: Defines the second stage, using another Python base image.
WORKDIR /app
: Sets the working directory in the second stage.
COPY --from=builder /app/venv /app/venv
: Copies only the virtual environment, the app.py, the static folder and templates folder from the 'builder' stage.
ENV FLASK_APP=app.py
and ENV FLASK_RUN_HOST=0.0.0.0
: Sets environment variables for the Flask application.
EXPOSE 5000
: Exposes port 5000.
CMD ["flask", "run"]
: Defines the command to run the Flask application.
# Stage 1: Build the application
FROM python:3.9-slim-buster AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# Stage 2: Create a minimal image for deployment
FROM python:3.9-slim-buster
WORKDIR /app
COPY --from=builder /app/venv /app/venv
COPY --from=builder /app/app.py /app/app.py
COPY --from=builder /app/static /app/static
COPY --from=builder /app/templates /app/templates
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
EXPOSE 5000
CMD ["flask", "run"]
Explanation of Multi-Stage Builds
Multi-stage builds allow you to use multiple FROM
statements in your Dockerfile. Each FROM
instruction starts a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind unnecessary dependencies and tools. This results in a smaller, more efficient, and more secure final image.
Real-Life Use Case
Consider a Flask web application. The first stage can install all build dependencies (e.g., compilers, libraries). The second stage then copies only the necessary artifacts (e.g., compiled code, static assets) from the first stage into a clean base image. This way, the final image doesn't contain any build tools, reducing its size and potential attack surface.
Best Practices
AS
for clarity.slim-buster
) for the final stage.
Interview Tip
Be prepared to explain the benefits of multi-stage builds, such as smaller image sizes, improved security, and faster deployment times. Also, be ready to discuss how to selectively copy artifacts between stages.
When to use them
Use multi-stage builds when you want to create optimized Docker images, especially for applications that require build dependencies. This is particularly useful for compiled languages (e.g., Go, C++) and applications with complex build processes.
Memory footprint
Multi-stage builds significantly reduce the image size, leading to a smaller memory footprint. By only including the necessary artifacts in the final image, you avoid including unnecessary dependencies and build tools.
Alternatives
If multi-stage builds are too complex, consider using techniques like optimizing your base image by removing unnecessary packages or using a smaller base image. However, multi-stage builds are generally the most effective approach for minimizing image size.
Pros
Cons
FAQ
-
What is the purpose of the
AS builder
?
TheAS builder
assigns a name to the first stage, allowing you to reference it later in the Dockerfile when copying artifacts. -
Why do I need to copy static and template files?
These files contains the application logic and user interface that must be provided from the service. -
How can I optimize the Dockerfile further?
You can further optimize the Dockerfile by using a.dockerignore
file, optimizing the base images, and combiningRUN
commands.