Docker lets you package your app and everything it needs, like libraries and tools, into one container so it runs the same anywhere.
When you use it with Flask, a lightweight Python web framework, you get a solid middle ground between running your own servers and using fully managed platforms like Heroku.
Flask works well with Docker because containers are much lighter than virtual machines. They don’t need to simulate a whole computer; they just share the host system’s core while staying isolated. This means fewer environment issues and easier, more reliable deployments.
In this guide, you'll containerize a Flask app with Docker.
Prerequisites
Before you begin, ensure you have the following installed:
Setting up the project structure
In this section, you'll build a simple Flask app structure that works well with Docker. The setup is straightforward, with just one application file.
Start by creating a new directory for your project and navigating into it:
Next, set up a virtual environment to manage your Python dependencies separately:
Activate the virtual environment:
Install Flask and Gunicorn:
Create a requirements.txt file to track dependencies:
Now, create a simple app.py file as the single entry point for your application:
This straightforward structure provides:
- A simple Flask application in a single file
- A welcome endpoint that returns JSON
- A health check endpoint for container monitoring
- Configured to listen on all interfaces (required for Docker)
Let's start by testing our Flask application without Docker. Launch the Flask development server with:
Visit http://127.0.0.1:5000/ in your browser, and you should see a JSON response:
After verifying it works, stop the server.
Getting started with Docker
In this section, you'll enhance your Flask application by adding Docker. With Docker, your application will gain portability, consistency, and isolation, making it easier to deploy and scale.
First, create a simple Dockerfile in the root of your project:
Open the Dockerfile and add the following straightforward configuration:
Open the Dockerfile and add the following configuration. This Dockerfile will define how Docker builds your application image.
It starts with a slim Python 3.13.3 base image to keep the image lightweight. The working directory inside the container is set to /app, and it installs dependencies from the requirements.txt file.
It also installs Gunicorn for serving the app in production. The application code, app.py, is copied into the container, and port 5000 is exposed to handle incoming connections. Finally, the application is run with Gunicorn as the production WSGI server, binding it to 0.0.0.0:4000.
Next, create a simple .dockerignore file to prevent unnecessary files from being included:
Add the following contents:
Now, build the Docker image:
After the build completes, run the container:
The -d flag runs the container in detached mode (background), and the -p flag maps port 5000 in the container to port 5000 on your host.
Your Flask application is now running inside a Docker container! Visit http://localhost:4000/ to verify it's working:
This confirms the app is up and running.
Working with container logs
Managing logs is essential when working with containerized applications. Docker automatically captures everything written to standard output (stdout) and standard error (stderr) by your application, making it easy to inspect what's happening inside the container.
You can view the logs of your running container with:
These logs show the Gunicorn WSGI server starting up successfully. The first line indicates Gunicorn's version, followed by the listening address and port. The third line shows it's using the default synchronous worker type, and the last line confirms a worker process has started with process ID 7.
You can follow the logs in real-time (similar to tail -f) with:
This is particularly useful during development or when troubleshooting issues, as you'll see log entries appear as they happen.
To see only the most recent entries:
And for logs within a specific time range:
When you're done with the container, you need to stop and remove it:
For simplicity and automatic cleanup, use the --rm flag when starting, which will automatically remove the container when it stops:
This prevents accumulating stopped containers that take up disk space on your system.
Setting up Docker Compose for development
Now that you've successfully containerized your Flask application with Docker, let's improve your development workflow using Docker Compose. This tool simplifies managing Docker applications, especially when you need multiple containers working together.
Before proceeding, make sure to stop your currently running container from the previous section:
First, create a docker-compose.yml file in your project root:
Add the following configuration:
This configuration builds your application using the Dockerfile, maps port 4000 on the host to port 5000 in the container, and mounts the local app.py to the container for live code reloading.
It sets the FLASK_DEBUG environment variable for development, uses Flask's development server by overriding the default command, and ensures the container restarts automatically if it crashes.
Start your development environment:
You'll see output showing your application starting up:
Now, you can edit your app.py file locally, and the changes will be reflected immediately in the running container thanks to the volume mapping. Try adding a new route to app.py:
Save the file and visit http://localhost:4000/hello in your browser:
You'll see the changes without rebuilding the image or restarting the container.
To run the containers in the background, use the -d flag:
View logs from Docker Compose:
And to shut it down when you're done:
This Docker Compose setup gives you a more flexible development workflow than plain Docker commands and prepares you to add additional services like databases.
Final thoughts
Containerizing your Flask app with Docker ensures consistent deployment and scalability across environments. Docker Compose simplifies managing multi-container applications, making setting up, scaling, and maintaining development and production environments easier.
For more detailed documentation on Docker and Docker Compose, refer to the official Docker documentation and Docker Compose documentation. These resources provide deeper insights into container management, multi-container setups, and best practices for production-ready applications