Настройка docker для django на mysql

В интернете много неактуальных статей, поэтому я подготовил эту публикацию. В основном при написании статьи опирался на пример настройки докера для джанго в документации докера.


Здесь будет описываться настройка докера для фреймворка django и базы данных mysql, которая будет храниться вне контейнера, благодаря чему можно будет не беспокоиться, что с нашим контейнером что-то случится.


При написании данного руководства использовалось:


  • ubuntu 20.04
  • docker 19.03.12
  • docker-compose 1.26.2
  • python 3.8
  • mysql 5.7
  • django 3.1.1
  • mysqlclient 2.0.1
  • django-mysql 3.8.1

Настройка рабочего пространства


Перед началом настройки необходимо подготовить рабочее пространство:


  1. Установить docker и docker-compose. Процесс установки подробно описан в документации докера.
  2. Создать директорию, в котором будет размещаться наш проект (в данном примере project). В этой директории создать еще одну, в которой будет храниться конфигурация для запуска образа python (в данном примере web).

./project
      /web

На этом подготовка закончена и можно приступать к настройке нашего небольшого проекта.


requirements.txt


В директории web создаем файл под названием requirements.txt.
В данном файле объявляем пакеты для работы нашего django приложения.


/project/web/requirements.txt


Django==3.1.1
mysqlclient==2.0.1
django-mysql==3.8.1

Как видите, тут прописан сам джанго, а также пакеты для связи с базой данных mysql.


Далее мы его будем использовать данный файл для настройки содержимого образа.


Dockerfile


В директории web создаем файл под названием Dockerfile.
Файл Dockerfile настраивает содержимое образа приложения с помощью одной или нескольких команд. После сборки запустим контейнер из настроенного образа.


Добавьте следующее содержимое в этот файл:


/project/web/Dockerfile


FROM python:3.8
ENV PYTHONUNBUFFERED 1
RUN mkdir /web_django
WORKDIR /web_django
COPY requirements.txt /web_django/
RUN pip install --upgrade pip && pip install -r requirements.txt
ADD . /web_django/ 

Данная настройка создает в образе python директорию с нашим проектом, копирует туда список пакетов, которые нужно установить и устанавливает их. Также папка с кодом из образа привязывается к директории web_django в корне проекта.
Перед установкой пакетов обновляется менеджер пакетов pip во избежании проблем с версией(--upgrade pip), т.к. изначально в моем случае он был устаревшим, и вылезала ошибка.


docker-compose.yml


В корне проекта создаем файл docker-compose.yml.


Данный файл содержит настройки сервисов используемые приложением. В данном примере этими сервисами являются веб-сервер и база данных. Файл compose также описывает, какие образы Docker используют эти сервисы, как они связываются друг с другом, какие тома им нужны внутри контейнеров. Также устанавливаются порты, используемые этими сервисами.


Добавьте следующее содержимое в этот файл.


/project/docker-compose.yml


version: '3'

services:
  web:
    build: ./web
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/web_django
    ports:
      - '8000:8000'
    depends_on:
      - db
  db:
    image: mysql:5.7
    ports:
      - '3306:3306'
    environment:
      MYSQL_DATABASE: 'db_django'
      MYSQL_USER: 'root'
      MYSQL_PASSWORD: 'password'
      MYSQL_ROOT_PASSWORD: 'password'
    restart: always
    volumes:
      - ./db_django:/var/lib/mysql

В первой части собирается образ согласно нашей инструкции в файле web/Dockerfile и запускается контейнер. Далее запускается сервер django на 8000 порту. Настраивается том нашего джанго проекта и присваивается в зависимость сервис с образом mysql.


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


Настройку докера закончили. Теперь приступим к запуску контейнера и создания django проекта.


Создание проект django


Перейдите в корень проекта (project/) и выполните команду. Данная команда создает django проект с названием web_django.


sudo docker-compose run web django-admin startproject web_django .

После этой команды получится следующая структура:


drwxr-xr-x   6 root  root   4,0K  сен 16 21:49 db_django
-rw-rw-r--   1 kafka kafka  466   сен 16 21:31 docker-compose.yml
-rwxr-xr-x   1 root  root   666   сен 16 21:34 manage.py
drwxrwxr-x   2 kafka kafka  4,0K  сен 16 21:31 web
drwxr-xr-x   3 root  root   4,0K  сен 16 21:34 web_django

Далее необходимо изменить владельца папки, т.к. контейнер запускается как root пользователь.


sudo chown -R $USER:$USER web_django

Настройка базы данных проекта


Откройте файл настроек django проекта по пути web_django/settings.py
В этом файле заменим настройки подключения к бд, которые мы указывали в docker-compose.yml.


/project/web_django/settings.py


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db_django',
        'USER': 'root',
        'PASSWORD': 'password',
        'HOST': 'db',
        'PORT': '3306',
    }
}

Теперь все готово и можно запускать docker-compose.


Запуск проекта


Для запуска контейнеров достаточно выполнить данную команду


docker-compose up

Чтобы запустить контейнеры в фоновом режиме необходимо указать дополнительный аргумент


docker-compose up -d

Для того чтоб пересобрать образы можно выполнить команду


docker-compose build

Миграция базы данных


Для того, чтобы выполнить миграцию бд, выполните команды:


docker-compose run web python manage.py makemigrations

docker-compose run web python manage.py migrate
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 14

    0
    докер в 2020 научился работать в режиме сетевой мост как у vmware? чтобы выделялся IP от роутера как отдельное устройство?
      +1

      Умеет давно, нужно использовать сетевой драйвер macvlan.

    0

    Чтобы не забивать каталог проекта мусорными файлами, от которых нет никакого толка, лучше использовать анонимный том:


        volumes:
          - mysql-django:/var/lib/mysql

    (его также надо объявить в секции volumes docker-compose)


    Использовать pip с requirements.txt — это уже устаревшая неудобная практика. Лучше сразу начинать использовать poetry.


    В качестве БД с Django лучше использовать Postgres. Во-первых, он сам значительно опережает по возможностям и удобству MySQL, во-вторых, интеграция Django с Postgres намного более плотная, чем с MySQL.

      0
      Спасибо за совет
        0

        Замечание:


        • mysql-django:/var/lib/mysql

        Это не анонимный, а вполне именованный том


        Использовать pip с requirements.txt — это уже устаревшая неудобная практика. Лучше сразу начинать использовать poetry.

        Мы недостатки pip преодолевали при помощи pip-compile и соответствующего инструментария. Но pip сейчас активно дорабатывают, глядишь, он и научится в зависимости нормально, а не как сейчас.
        Да и за poetry от меня плюсик


        В качестве БД с Django лучше использовать Postgres. Во-первых, он сам значительно опережает по возможностям и удобству MySQL, во-вторых, интеграция Django с Postgres намного более плотная, чем с MySQL

        Мне самому пг нравится больше, но это очень холиварный вопрос. По возможностям мускуль уже сильно продвинулся вперёд. В частности, Мария и галера. Когда там в постгрес мастер-мастер завезут? Ну, и новичкам проще освоиться с мускулем будет. 100%. Единственное, что, кажется, что докер образ постгрес проще, чем мускуль, но это вопрос упаковки, а не самой бд

          +1
          Это не анонимный, а вполне именованный том

          Действительно. Оказывается, в докере есть настоящие анонимные тома, только после вашего ответа погуглил и нашёл.


          Здесь можно использовать именованный или анонимный том. Но я настоящие анонимные тома, получается, явно еще не использовал, не знаю какие могут быть подводные камни.


          По возможностям мускуль уже сильно продвинулся вперёд. В частности, Мария и галера.

          Возможно, и так. Но вторая часть может перевешивать: аналога django.contrib.postgres для MySQL нет. Для небольшого проекта удобства, предоставляемые Postgres, очевидны. Для большого надо взвешивать, не все проекты используют мастер-мастер и не всем он нужен.

        +2
        А чем неактуально «множество неактуальных статей»? Номерами версий?
          0
          Во первых да, но также мало статей нашел настройки для mysql. Но сейчас понял что зря искал именно для этой бд) Еще в некоторых статьях были нерабочие примеры, по крайней мере у меня они не хотели работать)
            0
            facepalm.jpg
          +1
          Лучше сделать так:

          docker-compose.yml
          ...
            db:
              image: mysql:5.7
              ports:
                - '3306:3306'
              env_file: .env
          ...


          .env
          MYSQL_DATABASE=db_django
          MYSQL_USER=root
          MYSQL_PASSWORD=password
          MYSQL_ROOT_PASSWORD=password
          

          И тогда settings.py что-то вроде:
          DATABASES = {
              'default': {
                  'ENGINE': 'django.db.backends.mysql',
                  'NAME': os.environ.get('MYSQL_DATABASE'),
                  'USER': os.environ.get('MYSQL_USER'),
                  'PASSWORD': os.environ.get('MYSQL_PASSWORD'),
                  'HOST': os.environ.get('MYSQL_HOST', 'db'),
                  'PORT': '3306',
              }
          }


          И .env добавить в .gitignore не хранить данные продовой базы в репозитории
            0

            Лучше не путать .env и env_file. Я не знаю, кто тот гениальный человек, который первый это порекомендовал, но есть разница.
            Кратко в том, что .env считывается докер компостом и позволяет делать variable interpolation (почитайте в оф доке, что это такое).
            А вот env_file подцепляет env_file и прокидывают ВНУТРЬ контейнера как переменные.
            И иногда это дает СТРАННЫЕ эффекты.

              0

              Еще лучше подключить django-environ, чтобы не писать руками все эти os.environ.get и получить некоторые дополнительные удобства в комплекте.

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

            Самое читаемое