PyCharm and Docker Compose remote debugging

October 25, 2018 3 minutes

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.

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.

Run/Debug configuration window for remote Gunicorn inside 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.