django_debug_toolbar и Docker

Так что я заставил Docker и Django работать локально, сначала создав изображение из Dockerfile, затем используя Fig, чтобы получить изображение Postgres, связав его с базовым образом, и запустив локальный сервер. Все работает отлично, за исключением django_debug_toolbar. По какой-то причине это просто не появится. Имейте ip dockerhost также во internal_ips. Кто-нибудь может мне помочь с этим? Docker работает на Mac через boot2docker.

Спасибо!

Мои настройки:

init.py

import os

if 'DEBUG' not in os.environ or not os.environ['DEBUG']:
    from .local import *
else:
    pass

base.py

""" common and global settings """

from sys import path
from os import environ
from os.path import abspath, basename, dirname, join, normpath
from django.core.exceptions import ImproperlyConfigured
import dj_database_url


def get_env_variable(var_name):
    try:
        return environ[var_name]
    except KeyError:
        error_msg = "Set the environment variable" % var_name
        raise ImproperlyConfigured(error_msg)

# Paths
DJANGO_ROOT = dirname(dirname(abspath(__file__)))
SITE_ROOT = dirname(DJANGO_ROOT)
SITE_NAME = basename(DJANGO_ROOT)
# End Paths


# URLs
MEDIA_ROOT = normpath(join(SITE_ROOT, 'media'))
MEDIA_URL = "/media/"

STATIC_ROOT = normpath(join(SITE_ROOT, 'assets'))
STATIC_URL = "/static/"

STATICFILES_DIRS = (
    normpath(join(SITE_ROOT, 'static')),
)

STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)

ROOT_URLCONF = '%s.urls' % SITE_NAME

path.insert(0, join(DJANGO_ROOT, 'apps'))  # add apps folder to system path
# End URLs


# Database
# example:  postgres://joris:luna@localhost/bitbybit
DATABASES = {'default': dj_database_url.config(
   default='postgres://postgres@db:5432/postgres')}
# End Database

# Templates
TEMPLATE_CONTEXT_PROCESSORS = (
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
    'django.core.context_processors.static',
    'django.core.context_processors.tz',
    'django.contrib.messages.context_processors.messages',
    'django.core.context_processors.request',
)

TEMPLATE_LOADERS = (
   'django.template.loaders.filesystem.Loader',
   'django.template.loaders.app_directories.Loader',
)

TEMPLATE_DIRS = (
    normpath(join(SITE_ROOT, 'templates')),
)
# End Templates


# SECURITY WARNING: keep the secret key used in production secret!
# make it unique and store it as an environment variable
SECRET_KEY = r"d%g7_h6cz=xbhs*5-i+e$c7mns*s)^_+#^8n@^-2dno@uie-z9"


# Application
DJANGO_APPS = (
   'django.contrib.admin',
   'django.contrib.auth',
   'django.contrib.contenttypes',
   'django.contrib.sessions',
   'django.contrib.messages',
   'django.contrib.staticfiles',
)

LOCAL_APPS = (
   'home',
)

INSTALLED_APPS = DJANGO_APPS + LOCAL_APPS

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'debug_toolbar.middleware.DebugToolbarMiddleware',
)

WSGI_APPLICATION = '%s.wsgi.application' % SITE_NAME
# End Application


# Internationalization
LANGAUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True
# End Internationalization

Local.py

from .base import *

# Debug config
DEBUG = True
TEMPLATE_DEBUG = DEBUG
# End Debug config

# Hosts
ALLOWED_HOSTS = ['127.0.0.1', 'localhost']
# End Hosts


# Django Debug Toolbar config
INSTALLED_APPS += (
    'debug_toolbar', )

INTERNAL_IPS = ('127.0.0.1', 'localhost')
# End Django Debug Toolbar config

10 ответов

Используя конфигурацию SHOW_TOOLBAR_CALLBACK разбудил для меня

def show_toolbar(request):
        return True

DEBUG_TOOLBAR_CONFIG = {
    'SHOW_TOOLBAR_CALLBACK': show_toolbar,
}

Я надеюсь, что это помогло:)

Если вы хотите сделать это программно, а не копировать / вставлять ваш IP-адрес контейнера, я бы посоветовал вам делать то же, что и люди django-cookiecutter. В вашем локальном файле настроек:

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

Для справки, это ссылка на файл настроек django-cookiecutter local.py.

Вы могли бы просто сделать INTERNAL_IPS объект, который содержит все. Вот что я делаю:

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})()

Конечно, вы никогда не должны делать это на производственном хосте!

Объяснение:

Функция типа (вариант с тремя аргументами: https://docs.python.org/3/library/functions.html) создает новый класс, который в этом случае имеет только __contains__ метод ( https://docs.python.org/3/reference/datamodel.html) - содержит используется для реализации тестов членства, что означает, что этот метод вызывается при выполнении, например, "if ip in INTERNAL_IPSMsgstr "Сам метод метода, вероятно, будет более понятным, если будет записан какdef __contains__(self):\n return TrueMsgstr "Вновь созданный класс сразу создается (последний"()") и присваивается INTERNAL_IPS

IP-адрес, который позволял мне отображать панель инструментов django, был IP-адресом getway, связанным с моим док-контейнером. Для получения IP прохода я запускаю эту команду

docker inspect my_container_name | grep -e '"Gateway"'
# "Gateway": "172.18.0.1",

Все мои настройки выглядят так

INSTALLED_APPS = (
    'debug_toolbar',
)
INTERNAL_IPS = ['172.18.0.1']

Используя принятый ответ на https://unix.stackexchange.com/questions/87468/is-there-an-easy-way-to-programmatically-extract-ip-address я смог заставить это работать, передав адрес Docker моста хозяина к docker run команда как переменная среды:

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

С этим набором следующие две строки settings.py обнаружил его и позволил хосту увидеть панель инструментов:

if "DOCKER_HOST" in os.environ:
    INTERNAL_IPS = [os.environ["DOCKER_HOST"]]

Решаемые. Проверил значение REMOTE_ADDR в заголовках запроса и добавил его к INTERNAL_IPS.

Хитрость заключается в использовании метода gethostbyname_ex вместо метода gethostbyname .

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

Как уже упоминалось, вы можете использовать обратный вызов, чтобы определить, должна ли отображаться панель инструментов отладки или нет. Я использую это вместе с переменной окружения, переданной через 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"

Вот хакерский способ, который не требует внедрения адреса в контейнер. Я не уверен, как это будет работать, если ваш контейнер подключен к нескольким сетям и может сломаться, если docker изменил способ назначения адресов (хотя это маловероятно).

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]

1- запустите эту команду в каталоге docker-compose или Dockerfile и получите NETWORK ID:

sudo docker network list

и просмотреть список всех сетей

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

2- запустите эту команду:

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- получить свой IP

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

4- добавить ip в INTERNAL_IPS = [..., 162.21.0.1, ...] ‍‍‍‍‍‍‍‍‍‍

Другие вопросы по тегам