Разработка такого проекта как кешбек-сервис подразумевает использование различных сервисов, нетипичных для обычного ноутбука, даже если это ноутбук разработчика. Postgresql, Redis, Celery и так далее. Желание создать комфортную среду разработки и тестирования привело нас к необходимости использование какой-то системы виртуализации/изоляции. Как вариант — некоторое время использовался Vagrant, но это всё-таки ovrerhead и наши поиски оптимального способа привели, на данный момент, к Docker.
Docker — платформа для запуска приложений в изолированных контейнерах. Использование контейнеров в Linux позволяет программному обеспечение быть изолированным от базовой системы. В отличии от Virtualbox, исключаются системные издержки (overhead), необходимые для виртуализации оборудования. Docker может помочь в разработке и развертывании веб-приложений и сервисов. Давайте посмотрим, как это происходит.
Зачем мне нужен Docker?
Docker может быть использован различными способами. Он может обеспечивать работу сервисов в фоновом режиме, например, PostgreSQL заданной версии. В docker может быть помещено наше приложение (dockerizing application) и таким образом мы мы можем использовать образы подобных контейнеров для развертывания нашего приложения на продакшене.
Для python-разработчиков Docker может быть описан как virtualenv для любого приложения. Это может быть как Python-интерпретатор так и какой-нибудь сервер. Это очень удобно, когда вы хотите протестировать новые версии или хотите запустить устаревшие приложения на вашем сервере.
Установка Docker
Docker доступен в репозиториях в различных Linux дистибутивах. OSX и MS Windows пользователи могут использовать VirtualBox, на котором установлена Linux система для того, чтобы запустить Docker.
Для установки последней версии я использую PPA для Ubuntu. Когда Docker установлен, вы можете добавить себя в группу “docker” для того, чтобы в дальнейшем не требовлось использовать sudo.
Первые контейнеры
Когда Docker готов, мы можем запустить множество контейнеров из registry.hub.docker.com, например Python. Для запуска этого контейнера, просто выполните:
docker run -it --rm python:3.4
Для начала запущенный Docker скачает несколько файлов. Когда процесс завершится, мы получим дефолтную консоль Python-интерпретатора. Команда -it запускает контейнер в интерактивном режиме и привязывает ее к консоли для взаимодействия. --rm удалит текущий контейнер после выхода. “Python” — это название исходника для контейнера. После “:” мы видим тег, который обычно показывает версию — в этом случае версия Python в контейнере.
Мы также можем поменять стандартное поведение контейнера, например запустить собственный скрипт. Для использования команды из командной строки просто добавьте следующее:
docker run -it --rm python:3.4 ls
Когда наш контейнер будет запущен, внутри него запустится команда “ls”, которая покажет все файлы и фильтры в главной директории.
Dockerfile
Файл Dockerfile содержит “рецепт приготовления” нашего контейнера. Если мы хотим запустить скрипт на Python, вот что мы должны написать:
FROM python:3.4
ADD ./test.py /
RUN ls -al
CMD python test.py
FROM указывает на базовый контейнер, в данном случае — образ Python 3.4. Дальше мы можем использовать ADD, RUN, ENV команды для конфигурации контейнера. RUN команда будет выполнять задачи, когда контейнер построен. Команда CMD выполнится в начале запуска контейнера. Операции построения образов кэшируются и пропускает следующие версии (RUN команда из примера запустит построения первого билда, но не второго).
В терминале мы можем написать следующее:
docker build --tag=foo .
docker run -it --rm foo
Dockerfile на Django
django-ckeditor содержит демонстрационное приложение, которое может быть запущено через manage.py и runserver. Попробуем сделать Dockfile, который создаст образ этого приложения:
FROM python:3.4
MAINTAINER Piotr Maliński <riklaunim@gmail.com>
ADD . /ckeditor
ENV DJANGO_SETTINGS_MODULE ckeditor_demo.settings
RUN pip install -r /ckeditor/ckeditor_demo_requirements.txt
RUN pip install /ckeditor
RUN python /ckeditor/manage.py validate
RUN python /ckeditor/manage.py collectstatic --noinput
CMD python /ckeditor/manage.py runserver 0.0.0.0:8080
Я использую здесь Python 3.4. Весь код из репозитория будет добавлен в папку “ckeditor” контейнера. Я также устанавливаю DJANGO_SETTINGS_MODULE переменную окружения, добавляю зависимости и собственно редактор. Дальше валидация, сбор статики и в конце CMD для запуска сервера. Также удобно сделать сервер доступным снаружи контейнера, для этого мы запускаем его на 0.0.0.0 IP
dockebuild --tag=django-ckeditor .
dockerun -it --rm --publish=192.168.0.110:8080:8080 django-ckeditor
Опция --publish позволяет сопоставить (mapping) публичный IP/Port адреса из запущенного локального контейнера с локальным. В этом примере 192.168.0.110 это порт хоста. Публичный порт может быть доступен через 8080 из моего localhost. Без опции publish сервер будет доступен только из запущенно IP адреса контейнера.
Конфигурация Dockerfile, которую я показал не идеальна и будет работать только с SQLite базой данны. Docker позволяет запускать разные сервисы в разных контейнерах. Например, давайте попробуем, использовать PostgreSQL базу данных во втором контейнере.
Так давайте запустим экземпляр PostgreSQL:
docker run -d postgres:9.4
Конетйнер запустится в фоновом режиме и мы можем проверить его статус и название командой docker ps. Названия по умолчанию задаются случайные, например “clever_ptolemy”. Сейчас мы создали базу данных на этом сервере, но сначала нам нужен IP-адрес. Мы можем получить его из docker inspect INSTANCE_NAME, которая покажет список переменных в контейнере, включая IP-адрес. Дальше мы можем создать базу данных:
createdb -h IP_ADDRESS DATABASE_NAME -U postgres
База данных создана и сейчас мы можем настроить ее в контейнере приложения. Докер позволяет сделать это используя переменные окружения. Для Django можно использовать dj_database_url:
from os import environ
import dj_database_url
DATABASES = {'default': dj_database_url.parse(environ.get('DATABASE', 'postgres:///'))}
Теперь мы должны передать env переменную с именем базы данных в контейнер чтобы заставить его работать. Это может быть сделать так:
docker run -it --rm --link=POSTGRES_INSTANCE_NAME:OUR_NAME -e DATABASE=postgres://postgres@OUR_NAME/DATABASE_NAME --publish=192.168.0.110:8080:8080 django-ckeditor
Имя экземпляра базы данных мы можем получить выполнив команду “docker ps” в консоли. “OUR_NAME” это ярлык, который мы можем использовать позже в -e значении. В моем случае это выглядело так:
docker run -it --rm --link=clever_ptolemy:db -e DATABASE=postgres://postgres@db/ckeditor --publish=192.168.0.110:8080:8080 django-ckeditor python /ckeditor/manage.py syncdb
docker run -it --rm --link=clever_ptolemy:db -e DATABASE=postgres://postgres@db/ckeditor --publish=192.168.0.110:8080:8080 django-ckeditor
Первой выполняется команда syncdb, она создаст таблицы в базе данных. Далее запускается development сервер.
Инструмент Fig
Вышеописанный простой пример требует множество названий и линков. Для того, чтобы сделать процесс проще, есть несколько инструментов типа fig. В YAML(fig.yml) файле мы можем указать все шаги и линки, которые нужны:
ckeditor:
build: .
command: python /ckeditor/manage.py runserver 0.0.0.0:8080
links:
- db
ports:
- "8080:8080"
db:
image: postgres:9.4
Далее мы можем собрать командой fig build и запустить c fig up, которая покажет работу приложения. У нас есть несколько табличек и мы можем запустить syncdb и для помощи использовать fig run NAME COMMAND, где Имя это имя экземпляра fig.yml. Когда fig запустился, то вы можете проверить список контейнеров командой “docker ps”
Вы можете прочитать больше о fig.yml syntax на странице приложения. Также есть Django-учебник, в котором предоставлен другой способ настройки Postgres.