PyCharm and Docker Compose remote debugging
PyCharm includes built-in support for easily running Flask applications with its included development server. It’s also easy to remotely attach the debugger to a Python instance running inside a Docker container. You can even remotely debug the Flask development server in the same manner!
What’s not to like?
Problem
Of course, we don’t use the Flask development server in our Docker images. More likely, we’re using a proper WSGI application container. I like Gunicorn, for example.
There’s no run configuration template for debugging a Gunicorn instance in a Just Werkz™ manner.
Solution
Just as it was possible to use the Flask CLI before official support was added for it, it’s possible to debug a remote Gunicorn instance by being somewhat creative with the Python run/debug configuration template.
As a reminder though, you first need to setup the remote Docker/DockerCompose Python interpreter you’ll use, if you haven’t done so already.
- https://www.jetbrains.com/help/pycharm/using-docker-compose-as-a-remote-interpreter.html
- https://www.jetbrains.com/help/pycharm/using-docker-as-a-remote-interpreter.html
It should work without further issue, just remember that if you haven’t followed the steps to allow non-root Docker usage, then you’ll probably get a permissions error if you aren’t running the IDE as root. Don’t run the IDE as root, add your user to the docker group instead.
Custom Python run/debug configuration
The following is based on suggestions made by user Streak Flash in the following support request thread: Debugging Flask under gunicorn in docker container.
Parameters: -b 0.0.0.0:8966 --access-logfile - --error-logfile - "dnshare:create_app()"
Yes, it’s the same as what appears in the Dockerfile, so we’re repeating ourselves here. But I already said that this was going to be somewhat of a hack, err, creative solution. Some things to note, to prevent confusion:
- Our docker-compose.yml file binds the port 8000 to the container’s 8966, we’ll be able to access our application
at
http://localhost:8000
. - The script path obviously points to the gunicorn executable inside the running container.
- The working directory points to our project’s root. You could leave it blank, but then the breakpoints are ignored completely when debugging… kinda defeating the point of this whole duct tape adventure.
With this, by running this configuration, the debugged container will be started and stopped as needed.
Starting and stopping other containers in docker-compose.yml
Unless you’re building a very simple application, then you probably have more than one service defined in your
docker-compose.yml file. Running docker-compose up
starts all the services defined in the file, but when
using a remote Python interpreter with docker-compose in PyCharm, it doesn’t work like that.
Pycharm-173.2941.3 docker-compose does not start all services
You need to be explicit regarding service dependencies, as PyCharm will only start containers required by the service that’s defined as the one that contains the Python interpreter.
The following commit is an example of that: Add explicit “depends_on” in docker-compose.yml.
By doing so, the required containers will be started as needed, and re-built if they’re out of date. They won’t be stopped automatically, though.