personal web log written by izabeera and dryobates

gunicorn docker pudb python debugging docker-compose

Debugging gunicorn on docker with pudb

by dryobates

Debugging code run in webservers like gunicorn is not very convenient. Even less convenient is debugging them running in docker. Pudb can give you comfort like GUI debugger but run in TUI remote environment.

Normally if you want to debug code you put`set_trace` in code (or use some more sophisticated methods like automatic post mortem debugging).

Now if you run gunicorn as a daemon with detached terminal then you have no possibility to see debugging console.

Remote debuggers

In cases like this you can use remote debuggers like rpdb or winpdb. They all work in the same manner - you start debugging like set_trace and they listen to incoming connections on some port. Then you can connect with telnet.

The best thing with that debuggers is that I can use them even on headless hosts. The bad part is that rpdb (or celery's rdb) has poor console support and winpdb doesn't work with python3.

Today I have tried pudb [1] and I really liked it. It's the missing chain in evolution between pure console debuggers and GUI debuggers. It's TUI debugger. Just the same like you can remember from the times of Turbo Pascal for DOS!


You can use pudb just like normal pdb using:

import pudb; pu.db

But for remote debugging will try it's other form:

from pudb.remote import set_trace; set_trace(term_size=(160, 40), host='', port=6900)

Now if you start gunicorn with code that has above line it will stop at this line and listen for connections on given port. You can connect to that port with telnet:

telnet 6900

You should see TUI interface and code of your program. If you have started gunicorn with default timeout settings you can enjoy beautiful debugger interface only for 30 seconds ;)

To prevent this just pass longer time out (e.g. 5min.=120s):

gunicorn wsgi -D -b -t 120


So now we can debug code inside gunicorn process even if it's started as daemon. No it's time for adjusting docker-compose. The only thing you have to change is to map ports on which debugger will connect. In docker-compose.yml put:

    - "6900:6900"

in container definition.

Now docker-compose up will start your docker and if line with set_trace will execute then you could connect to debugger.

Jakub Stolarski. Software engineer. I work professionally as programmer since 2005. Speeding up software development with Test Driven Development, task automation and optimization for performance are things that focus my mind from my early career up to now. If you ask me for my religion: Python, Vim and FreeBSD are my trinity ;) Email:


Tag cloud