[Django]-Django_debug_toolbar and Docker

55πŸ‘

Using the configuration SHOW_TOOLBAR_CALLBACK woked for me

def show_toolbar(request):
        return True

DEBUG_TOOLBAR_CONFIG = {
    'SHOW_TOOLBAR_CALLBACK': show_toolbar,
}

I hope that helped πŸ™‚

πŸ‘€Ouss ziat

26πŸ‘

If you would like to do this programatically and not copy/pasting your container IP, I’d suggest you do like the django-cookiecutter folks. In your local settings file:

INTERNAL_IPS = ['127.0.0.1', ]
import socket

# tricks to have debug toolbar when developing with docker
ip = socket.gethostbyname(socket.gethostname())
INTERNAL_IPS += [ip[:-1] + '1']

For reference, this is the link to the django-cookiecutter local.py settings file.

πŸ‘€Jordi

26πŸ‘

You could just make INTERNAL_IPS an object which contains everything. This is what I do:

if DEBUG:
    # `debug` is only True in templates if the vistor IP is in INTERNAL_IPS.
    INTERNAL_IPS = type(str('c'), (), {'__contains__': lambda *a: True})()

Of course you should never do this on a production host!

Explanation:

The type function (three arguments variant: https://docs.python.org/3/library/functions.html#type) creates a new class which in this case only has a __contains__ method (https://docs.python.org/3/reference/datamodel.html#object.contains) β€” contains is used to implement membership tests, meaning that this method is called when running e.g. β€œif ip in INTERNAL_IPSβ€œ. The contains method itself would probably be clearer if written as β€œdef __contains__(self):\n return Trueβ€œ. The newly created class is immediately instantiated (the final β€œ()”) and assigned to INTERNAL_IPS

14πŸ‘

An IP address that allowed me to display Django Debug Toolbar was, the Gateway IP of my docker container (container that runs Django app).

To obtain IP address of the gateway run this command.

# replace django_container_name with your container name!
docker inspect django_container_name | grep -e '"Gateway"'
# "Gateway": "172.18.0.1",

Next, add this Getway IP to settings.py -so your configuration might look like the one below.

INSTALLED_APPS = (
    ...
    'debug_toolbar',
    ...
)

MIDDLEWARE = [
    ...
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    ...
]

INTERNAL_IPS = ['172.18.0.1']

And of course add __debug__ to urls.py

import debug_toolbar
from django.conf import settings
from django.urls import include, path

urlpatterns = [
    ...
    path('__debug__/', include(debug_toolbar.urls)),
]

Just follow djdt installation guide!

3πŸ‘

Using the accepted answer at https://unix.stackexchange.com/questions/87468/is-there-an-easy-way-to-programmatically-extract-ip-address I was able to get this to work by passing the address of the host’s Docker bridge to the docker run command as an environment variable:

-e "DOCKER_HOST=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')"

With that set, the following two lines in settings.py detected it and allowed the host to see the toolbar:

if "DOCKER_HOST" in os.environ:
    INTERNAL_IPS = [os.environ["DOCKER_HOST"]]
πŸ‘€ncoghlan

2πŸ‘

Solved. Checked the value for REMOTE_ADDR in request headers and added that to INTERNAL_IPS.

πŸ‘€Joris

2πŸ‘

As people have mentioned, you can use a callback to determine if the debug toolbar should appear or not. I use this together with an environment variable passed in via docker-compose.

settings.py

def show_toolbar_callback(*args, **kwargs):
    if os.getenv("LOCAL_DEV"):
        return True
    return False


DEBUG_TOOLBAR_CONFIG = {"SHOW_TOOLBAR_CALLBACK": show_toolbar_callback}

docker-compose.yaml

services: 
  django:
    container_name: "django"
    build: "./"
    ports: 
      - "8000:8000"
    volumes:
      - ".:/opt/service"
    environment: 
      LOCAL_DEV: "true"
    depends_on: 
      - "db"
πŸ‘€rxvt

2πŸ‘

The simplest solution is to use gethostbyname_ex instead of gethostbyname

INTERNAL_IPS = ['127.0.0.1', '10.0.2.2' ]
if DEBUG:    
   import socket
   hostname, _, ips =socket.gethostbyname_ex(socket.gethostname())
   INTERNAL_IPS += [ip[:-1] + '1' for ip in ips]
πŸ‘€Mahmoud

1πŸ‘

Here’s a hacky way that doesn’t require injecting the address into the container. I’m not sure how it would work if your container is connected to multiple networks and could break if docker changed the way they assign addresses (though that doesn’t seem likely).

import subprocess

route = subprocess.Popen(('ip', 'route'), stdout=subprocess.PIPE)
network = subprocess.check_output(
    ('grep', '-Po', 'src \K[\d.]+\.'), stdin=route.stdout).decode().rstrip()
route.wait()
network_gateway = network + '1'
INTERNAL_IPS = [network_gateway]
πŸ‘€Ryne Everett

0πŸ‘

1- run this command in the directory docker-compose or Dockerfile and get NETWORK ID:

sudo docker network list

and view list all network

NETWORK ID     NAME                DRIVER    SCOPE
556e2e7123er   admin_default       bridge    local
aq3033sc09c1   bridge              bridge    local
1983cf1x2cb9   c**kroach           bridge    local
0cc1be23b543   flask               bridge    local

2- run this command:

ip addr

.
.

8: br-556e2e7123er: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether **:**:**:**:**:** brd ff:ff:ff:ff:ff:ff
    inet 162.21.0.1/16 brd 172.22.255.255 scope global br-556e2e7123er
       valid_lft forever preferred_lft forever

.
.

3- get your IP

NETWORK ID : 556e2e7123er == 8: br-556e2e7123er => ip 162.21.0.1

4- add ip to INTERNAL_IPS = […, 162.21.0.1, …]
‍‍‍‍‍‍‍‍‍‍

Leave a comment