Дополнение C. Как применять Django, PostgreSQL и Docker

Данный раздел содержит перевод блога Вилла Винцента How to use Django, PostgreSQL, and Docker в редакции от 27 июня 2018.

{Прим. пер.: Надеемся, что материалы книги, в которую и включён данный перевод явятся хорошим дополнением для данного краткого блога. В то время как сам блог может оказаться полезным в плане расширения аудитории.}

В данном руководстве мы создадим некий новый проект Django при помощи Docker и PostgreSQL. Django снабжается со встроенной поддержкой SQLite, но даже для локальной разработки вам лучше применять "настоящую" базу данных подобную PostgreSQL, которая лучше соответствует промышленному применению.

Имеется возможность запускать PostgreSQL локально применяя некий инструмент подобный Postgres.app, но мы предпочитаем выбор множества разработчиков сегодняшнего дня и воспользуемся Docker, инструментом для создания изолированных операционных систем. Самый простой способ представлять себе его как некое крупное окружение, которое содержит всё что требуется для нашего проекта Django: зависимости, базу данных, кэшированные службы и все прочие необходимые инструменты.

Основная причина для применения Docker состоит в том, что он полностью удаляет все проблемы относительно установок локальной разработки. Вместо того чтобы заботиться относительно того какие пакеты программного обеспечения установлены или запущены в вашей локальной базе данных помимо вашего проекта, вы просто запускаете некий образ Docker для всего своего проекта целиком. Что ещё лучше, вы можете совместно использовать его в группе и это делает команду разработки намоного более простой.

Установка Docker

Самый первый шаг состоит в установке настольного приложения Docker в вашей локальной машине:

Самая первая выгрузка Docker может потребовать некоторого времени. Это большой файл. Откиньтесь на спинку кресла и передохните!

После установки Docker мы можем проверить что запускаем верную версию. Она по крайней мере должна иметь номер 18.

Неким дополнительным инструментом является Docker Compose, который автоматически содержится в выгрузке Docker для Mac и Windows, однако если вы работаете в Linux, вам понадобится добавить его вручную. Вы можете сделать это выполнив команду sudo pip install docker-compose после завершения установки своего Docker.

Проект Django

Мы будем применять Message Board app из Django for Beginners. Он предоставляет основной код для некого базового приложения панели сообщений с применением SQLite, которая может обновляться в имеющемся admin.

Создайте некий новый каталог на своём Рабочем столе и клонируйте в него соответствующий репозиторий.


$ cd ~/Desktop
$ git clone https://github.com/wsvincent/djangoforbeginners.git
$ cd djangoforbeginners
$ cd ch4-message-board-app
		

Затем установите необходимые программные пакеты определённые Pipenv и запустите новую оболочку.


$ pipenv install
$ pipenv shell
		

После этих изменений убедитесь что вы migrate свою базу данных.


(mb) $ python manage.py migrate
		

Если вы теперь воспользуетесь командой python manage.py runserver, вы сможете обнаружить некую рабочую версию своего приложения в http://localhost:8000:

 

Рисунок 1



Docker (опять)

Надеюсь, к данному моменту Docker уже установился. Для того чтобы убедиться успешности его установки выйдите из своего локального сервера при помощи Control+c, а затем наберите в своей командной строке docker run hello-world. Вы должны обнаружить отклик подобный такому:


$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
d1725b59e92d: Pull complete
Digest: sha256:0add3ace90ecb4adbf7777e9aacf18357296e799f81cabc9fde470971e499788
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image whi
ch runs the executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client,
which sent it to your terminal.

To try something more ambitious, you can run an Ubuntu container
with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
		

Образы и контейнеры

Существует два важных понятия, которые вам следует уяснить в Docker: образы и контейнеры.

  • Образы: список инструкций для всех ваших программных продуктов в вашем проекте

  • Контейнеры: экземпляр времени исполнения определённого образа

Иными словами, некий образ определяет что произойдёт, а контейнер выступает тем, что исполняется в действительности.

Для настройки образов и контейнеров Docker мы применяем два файла: Dockerfile и docker-compose.yml.

Сам Dockerfile содержит список инструкций для своего образа, то есть что в действительности происходит в самой среде нашего контейнера.

Создадим некий новый файл Dockerfile.


(mb) $ touch Dockerfile
		

Затем добавим в него в своём текстовом редакторе следующий код.


# Вытаскиваем базовый образ
FROM python:3.7-slim

# Устанавливаем переменные среды
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# Настраиваем рабочий каталог
WORKDIR /code

# Устанавливаем зависимости
RUN pip install pipenv
COPY Pipfile Pipfile.lock /code/
RUN pipenv install --system

# Копируем проект
COPY . /code/
 	   

В самой первой строке вы применяем официальный образ Docker для Python 3.7.Затем мы создаём две переменных среды, PYTHONUNBUFFERED обеспечивает то, чтобы вывод нашей консоли выглядел знакомым нам, а не буферировался Docker, чего бы мы не хотели. PYTHONDONTWRITEBYTECODE означает, что не пытается записывать файлы .pyc, что также не желательно.

Следующая строка устанавливает WORKDIR в значение /code. Это означает, что наш рабочий каталог расположен в /code, поэтому в дальнейшем для исполнения любой команды подобной manage.py мы просто можем применять WORKDIR вместо того чтобы запоминать где в точности в нашем коде Docker она в действительности расположена.

Затем мы устанавливаем свои зависимости, убедившись что мы располагаем самой последней версией pip, устанавливаем pipenv, копируем свой локальный Pipfile и Pipfile.lock в Docker и затем запускаем его для установки наших зависимостей. Команда RUN позволяет нам запускать команды в Docker, также как это мы могли бы делать в своей командной строке.

Мы не можем запустить некий контейнер Docker пока он не получит некий образ, поэтому давайте сделаем его собрав необходимый образ в самый первый раз.


$ docker build .
		

Если всё успешно, вы увидите обильный вывод!

Далее нам понадобится некий новый файл docker-compose.yml. Он сообщает Docker как запускать наш контейнер Docker.


(mb) $ touch docker-compose.yml
		

Затем наберите такой код:


version: '3.7'

services:
  db:
    image: postgres:10.1-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data/
  web:
    build: .
    command: python /code/manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - 8000:8000
    depends_on:
      - db

volumes:
  postgres_data:
 	   

В самой верхней строчке мы применяем самую последнюю версию Compose, которой является 3.7.

Под db для своей базы данных мы хотим видеть образ Docker для Postgres 10.1 и воспользоваться volumes чтобы сообщить Compose где этот контейнер должен располагаться в нашем контейнере Docker.

Для web мы определяем как должна запускаться наша служба web. Прежде всего Compose потребуется собрать некий образ из нашего текущего каталога и запустить его сервер по 0.0.0.0:8000. Мы применяем volumes чтобы сообщить Compose о необходимости сохранять код в нашем контейнере в /code/. Значение настроек ports позволяет установить соответствие нашего порта 8000 на порт 8000 в самом контейнере Docker. Именно он является портом по умолчанию в Django. И, наконец, depends_on сообщает что нам следует запустить db перед исполнением наших служб web.

Самый последний раздел volumes присутствует по причине того, что Compose имеет некое правило, согласно которому вы должны перечислять названия томов в ключе volumes некого верхнего уровня.

Docker полностью настроен!

Обновление на PostgreSQL

Нам требуется обновить своё Message Board app для применения PostgreSQL вместо SQLite. Прежде всего установите psycopg2 ждя привязки нашей базы данных к PostgreSQL.


(mb) $ pipenv install psycopg2-binary
		

Затем обновите свой файл settings.py чтобы определить что мы применяем PostgreSQL, а не SQLite.


# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'postgres',
        'USER': 'postgres',
        'HOST': 'db', # set in docker-compose.yml
        'PORT': 5432 # default postgres port
    }
}
		

Сейчас нам требуется migrate свою базу данных в Docker.


(mb) $ docker-compose run web python /code/manage.py migrate --noinput
		

К тому же, поскольку Message Board app требуется применять admin, создайте в Docker суперпользователя. Заполните приглашение, получаемое после исполнения следующей команды:


(mb) $ docker-compose run web python /code/manage.py createsuperuser
		

Запуск Docker

Мы готовы запустить сам Docker! В самый первый раз когда вы исполните свою команду, вам придётся подождать пока Docker выгрузит всё требуемое содержимое. Но всё это будет кэшировано чтобы в последующем раскручивать намного бустрее.

Наберите следующую команду:


(mb) $ docker-compose up -d --build
		

Мы можем убедиться что всё работает перейдя к http://127.0.0.1:8000/, где вы обнаружите ту же самую домашнюю страницу, которую вы уже видели ранее:

 

Рисунок 1



Теперь перейдите к http://127.0.0.1:8000/admin и зарегистрируйтесь. Вы теперь имеете возможность добавлять посты и затем наблюдать их в своей домашней странице, в точности как это описывается в Django for Beginners.

После завершения не забудьте закрыть свой контейнер Docker.


(mb) $ docker-compose down
		

Беглый обзор

Вот сокращённая версия основных терминов и понятий, которые мы рассмотрели в данном посте:

  • Образ: "определение" вашего проекта

  • Контейнер: то что на самом деле исполняет ваш проект (некий экземпляр имеющегося образа)

  • Dockerfile: определяет как будет выглядеть ваш образ

  • docker-compose.yml: некий файл YAML, который берёт содержимое Dockerfile и добавляет дополнительные инструкции для того как себя следует вести нашему контейнеру Docker в промышленном применении.

Мы применяем Dockerfile чтобы сообщать Docker как тому собирать наш образ. Файл же docker-compose.yml предоставляет дополнительную информацию о том как наш контейнер Docker должен вести себя в промышленной среде.

Рекомендуемые ресурсы

Для дополнительного объяснения самого Docker я написал отдельный пост Beginner’s Guide to Docker. А если вы желаете погрузиться глубже тот фантастический ресурс Docker, который я применяю и сам, а теперь рекомендую всем, вот видеокурс: Dive into Docker.