Flask + Docker + VSCode: How to Simplify Debugging and Improve Your Development Experience
A Comprehensive Guide to Debugging Flask Applications Running in Docker with VSCode
Introduction
Debugging Flask Python applications can be challenging, and things get even more complicated when running Flask inside a Docker container. Fortunately, with the right setup, debugging Flask running inside Docker locally in VSCode can be made much easier. In this article, we'll guide you through the process of setting up your Flask Python application to run inside a Docker container and show you how to leverage VSCode's powerful debugging features to troubleshoot any issues that arise. With our step-by-step instructions, you'll be able to streamline your development workflow and solve even the most complex bugs in no time!
What is debugpy?
Debugpy is a Python debugger that provides a simple way to debug Python code remotely. It can be used to debug Python code running inside a Docker container, as well as code running on a remote machine. Debugpy can be used with a variety of editors and IDEs, including VSCode.
Step 1: Create a Flask app
Before we can start debugging, we need a Flask app to work with. Here is a simple Flask app that we will use as an example:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
if __name__ == '__main__':
app.run()
Step 2: Create a Dockerfile
Next, we need to create a Dockerfile that will define the Docker image for our Flask app. Here is an example Dockerfile:
FROM --platform=linux/amd64 ubuntu:latest
COPY . /app
WORKDIR /app
RUN apt-get update \
&& apt-get install -y python3-pip python3-dev \
&& cd /usr/local/bin \
&& ln -s /usr/bin/python3 python \
&& pip3 install --upgrade pip
RUN pip install -r requirements.txt
EXPOSE 5000
RUN pip install debugpy
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV DEBIAN_FRONTEND=noninteractive
CMD ["python", "-m", "debugpy", "--listen", "0.0.0.0:5679", "app.py"]
In this Dockerfile, we start with an Ubuntu base image and copy the contents of our current directory to the /app
directory inside the Docker image. We install the necessary dependencies, including debugpy, and expose port 5000. Finally, we start debugpy and set it to listen on port 5679.
Step 3: Create a docker-compose file
We will use a docker-compose file to simplify the process of running our Docker container. Here is an example docker-compose file:
version: '3'
services:
api:
container_name: api
command: python -u app.py
build:
context: ./api
dockerfile: Dockerfile
restart: unless-stopped
networks:
- frontend
- backend
ports:
- 12005:5000
- 5679:5679
volumes:
- ./api:/app
- /etc/localtime:/etc/localtime
entrypoint: [ "python", "-m", "debugpy", "--listen", "0.0.0.0:5679", "-m", "app", "--wait-for-client", "--multiprocess", "-m", "flask", "run", "-h", "0.0.0.0", "-p", "5000" ]
networks:
frontend:
driver: bridge
backend:
driver: bridge
In this docker-compose file, we define a networks
section to specify the communication between containers. In this case, we define two networks: frontend
and backend
. The frontend
network will allow communication between the web
container and any other container in the frontend
network, while the backend
network will allow communication between the web
container and any other container in the backend
network.
Lastly, we define the volumes
section to mount the application code directory (./app
) on the host to the /app
directory in the container. This allows us to make changes to the application code on the host and have those changes reflected in the container immediately without needing to rebuild the container.
Now that we have our docker-compose.yml
file set up, we can use the following command to start our application:
docker-compose up
This will start the api
container, along with any other containers specified in the docker-compose.yml
file.
Debugging the Flask application with VSCode and Docker
Now that we have our Flask application running inside a Docker container, let's see how we can debug it using VSCode.
The first thing we need to do is to add a .vscode/launch.json
configuration file to our project. This file specifies the configuration for the debugger, such as the type of debugger, the port to connect to, and the source code location. Here is an example launch.json
configuration file:
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Remote Attach",
"type": "python",
"request": "attach",
"port": 5679,
"host": "0.0.0.0",
"pathMappings": [
{
"localRoot": "${workspaceFolder}/app",
"remoteRoot": "/app"
}
]
}
]
}
In this configuration file, we specify that we want to attach to a remote Python process on port 5679, which is the same port that we exposed in our docker-compose.yml
file. We also specify the pathMappings
property to map the local source code directory (${workspaceFolder}/app
) to the /app
directory in the container.
With our launch.json
configuration file set up, we can now start the Flask application with the --wait-for-client
option and the debugpy
module. This will start the application in debug mode and wait for a debugger to connect before executing any code.
Now that we have our application running in debug mode, we can go back to VSCode and start the debugger by selecting the Python: Remote Attach
configuration from the VSCode debugger dropdown menu and clicking the green "play" button.
This will attach the VSCode debugger to the running Flask application inside the Docker container, allowing us to set breakpoints
Conclusion
In this article, we've walked through the process of debugging a Flask application running inside a Docker container in VSCode. By leveraging the power of debugpy, we're able to connect the VSCode debugger to our running container, set breakpoints, and step through our code as if it were running locally.
With the use of a Dockerfile, we've created a containerized environment with all the necessary dependencies to run our Flask application, including debugpy. We've also updated our docker-compose file to include debugpy as the entrypoint for our container and created a new port mapping for the debugger to connect to.
By following these steps, we can easily debug our Flask application running inside a Docker container in VSCode, making it easier to identify and resolve any issues that may arise during development.
If you'd like to try this out for yourself, you can check out our example repository at repo(https://github.com/kartikpuri95/flask-vscode-debug) and see how we've implemented these techniques to debug a Flask application inside a Docker container using VSCode.