78

I see that I'm not the first one to ask the question but there was no clear answer to this:

How to use pdb with docker-composer in Python development?

When you ask uncle Google about django docker you get awesome docker-composer examples and tutorials and I have an environment working - I can run docker-compose up and I have a neat developer environment but the PDB is not working (which is very sad).

I can settle with running docker-compose run my-awesome-app python app.py 0.0.0.0:8000 but then I can access my application over http://127.0.0.1:8000 from the host (I can with docker-compose up) and it seems that each time I use run new containers are made like: dir_app_13 and dir_db_4 which I don't desire at all.

People of good will please aid me.

PS
I'm using pdb++ for that example and a basic docker-compose.yml from this django example. Also I experimented but nothing seems to help me. And I'm using docker-composer 1.3.0rc3 as it has Dockerfile pointing support.

McAbra
  • 2,382
  • 2
  • 21
  • 29
  • None of the solutions here worked for me. [This one](https://stackoverflow.com/a/58540510/8285811) using `remote-pdb` did however. – Akaisteph7 Dec 19 '22 at 17:24

4 Answers4

152

Use the following steps to attach pdb on any python script.

Step 1. Add the following in your yml file

stdin_open: true
tty: true

This will enable interactive mode and will attach stdin. This is equivalent for -it mode.

Step 2.

docker attach <generated_containerid>

You'll now get the pdb shell

Arun Kumar Nagarajan
  • 2,347
  • 3
  • 17
  • 28
57

Try running your web container with the --service-ports option: docker-compose run --service-ports web

Jamey
  • 4,420
  • 2
  • 24
  • 20
  • 3
    That did it! Thank you kind sir. I'm now using docker-compose to create my environment and running my service or it's tests with `docker-compose run --rm --service-ports my-awesome-app python app.py 0.0.0.0:8000`. Goodbye Vagrant! – McAbra Jun 17 '15 at 19:51
  • I am having some issue with this method. My terminal is blank when I am typing something in pdb – Jitu Jan 03 '16 at 12:16
  • You get to the pdb prompt, though? I don't know how to help without more information, like what framework you're using, what services, etc. – Jamey Jan 04 '16 at 19:30
  • I think you also need something like -it: check the answer below – jpic Mar 05 '17 at 11:20
  • 1
    There's no reason to avoid `docker-compose up` for this functionality, as pointed out below. – Two-Bit Alchemist Dec 23 '17 at 18:23
  • i'm trying to do this with a `Make` instruction but it does not work, it executes the correct option but it shows me the `docker-compose` menu. – SalahAdDin Oct 23 '18 at 10:28
  • I always end up using `--rm` to remove the container after it stops and `--name ` to name the container so you don't get an autogenerated name, like so: `docker-compose run --rm --service-ports --name my-awesome-app my-awesome-app` and that will run the entrypoint command from the docker-compose file, or as you noticed you can specify your own command to run your server, or you can just specify `bash` as the command and go from there :) – Brendan Goggin Oct 17 '19 at 18:27
  • you saved my hours of time man. thank you so much – Jacky Supit Jun 27 '21 at 10:21
  • But how do you guys do a debug session with docker-compose run? what about all the services in the docker-compose like db etc how are you running them? – Joel Blum Feb 22 '23 at 07:26
1

If after the adding of

stdin_open: true
tty: true

you started to get issues similar to that:

        fd = self._input_fileno()
        if fd is not None and fd in ready:
>           return ord(os.read(fd, 1))
E           TypeError: ord() expected a character, but string of length 0 found

You can try to add ENV LC_ALL en_US.UTF-8 at the top of your Docker file

FROM python:3.8.2-slim-buster as build_base
ENV LC_ALL en_US.UTF-8

alexche8
  • 1,270
  • 3
  • 19
  • 26
0

In my experience, docker-compose up command does not provide an interactive shell, but it starts the printing STDOUT to default read-only shell.

Or if you have specified and mapped logs directory, docker-compose up command will print nothing on the attached shell but it sends output to your mapped logs. So you have to attach the container separately once it is running.

when you do docker-compose up, make it in detached mode via -d like docker-compose up -d, and connect to the container via

docker exec -it your_container_name bash

Nick
  • 396
  • 2
  • 15
Bhuro
  • 348
  • 4
  • 22
  • HI there, Can you specify the reason to downvote my answer? It would help me to improve myself and correct the mistakes. Thanks! – Bhuro Aug 10 '20 at 03:40
  • 1
    `exec` will get you a shell inside your running container, and with `-it` yes it’s interractive, but you will not connect to the running application, so no connection to pdb stdin/stdout. The correct way is to let compose start the service with stdin open and a tty and then attach to the process (for stdin to work). – Cyrille Pontvieux Sep 11 '20 at 06:33
  • Got your point, ..... it is like starting another instance when we try with exec, ... Although for PDB,... I have a better alternative which is web-based and running awesome with docker .... https://github.com/Kozea/wdb#docker – Bhuro Sep 11 '20 at 14:15