Разработка стартапов с опытом Кремниевой Долины
0,0
рейтинг
12 января 2015 в 09:55

Разработка → Быстрое знакомство с Docker-контейнерами для Django-разработчика перевод



Разработка такого проекта как kubish.ru подразумевает использование различных сервисов, нетипичных для обычного ноутбука, даже если это ноутбук разработчика. 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.
Перевод: Piotr Maliński
zavode.ru @CloverR
карма
6,0
рейтинг 0,0
Разработка стартапов с опытом Кремниевой Долины
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (19)

  • 0
    Название звучит как «Знакомство в Docker для самых маленьких»
  • +1
    Также удобно сделать сервер доступным снаружи контейнера, для этого мы запускаем его на 0.0.0.0 IP

    0.0.0.0 указывает на то, что созданный сервер будет доступен на всех интерфейсах контейнера
  • +4
    Как вариант — некоторое время использовался Vagrant, но это всё-таки ovrerhead и наши поиски оптимального способа привели, на данный момент, к Docker.

    OSX и MS Windows пользователи могут использовать VirtualBox, на котором установлена Linux система для того, чтобы запустить Docker.


    То есть просто Virtualbox это overhead, а Docker из под VirtualBox это норм. О-ок.
  • +5
    Уже который месяц присматриваюсь к докеру, читаю статьи и хаутушки и все они почему-то оказываются очень поверхностными:( В итоге тратишь время на статью, а потом все равно идешь копать доки и разбираться самостоятельно. В данной статье грубо говоря вообще ничего нет, ни толком плюсы/минусы не описаны, не описано хранение файлов проекта и базы при перезапуске образов, как и сохранение изменений в самом образе(обновления/добавление софта). Плюс везде предлагается вынесение каждого сервиса в отдельный контейнер(вебсервер отдельно, база отдельно, приложение отдельно), но это ведь бесполезное усложнение на этапе разработки, хотя и деплой тоже усложняется. Для мелких проектов это бессмысленно, а для крупных в чем смысл использования именно докера, почему не использовать сразу отдельные впски/сервера под базу/сервер/приложение?
    • +2
      Я тоже попробовал, и без понимания того, что Вы описали — не совсем понятно, что это и чем оно лучше openvz/lxc контейнера, вот если бы кто эту часть нормально обьяснил…
      • 0
        Docker — это обёртка над lxc.

        Есть и ещё одна функция, слои. Слой — это как commit в git.
        Т.е. пишите вы свой Dockerfile

        FROM nginx
        COPY nginx.conf /etc/nginx/nginx.conf

        И при каждом изменении nginx.conf будет создаваться новый коммит.
        Хранить эту историю изменений можно публично hub.docker.com/, либо приватно github.com/docker/docker-registry.
        Удобно, если новая версия перестала работать, можно откатить до работающей.

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

        Вроде, всё
        • +1
          немного уточню
          Да, слои — это подобие коммитов в `git`, но только вот слой создается не при каждом изменении nginx.conf, а в двух случаях:
          1. вы пишете свой Dockerfile, по которому билдите свой образ и при этом каждая запись в `Dockerfile` (`ADD`, `COPY`, `RUN`) будет генерировать новый слой. имейте в виду, что если вы пишете

          RUN echo "Hello"
          RUN echo "World"
          RUN echo "My name is Vasya!"
          RUN echo "Bye!"
          

          то будет сгенерировано 4 слоя — каждый слой увеличивает размер результируючего образа в результате записи новых мета-данных. я специально привел в пример команды, которые в принципе (за исключением записи в `~/.bash_history`, но я не уверен, что он пишется во время билда образа) не должны ничего писать в файловую систему. потому все, что Вы будете делать через команду RUN лучше записывать в виде одной большой команды:

          RUN apt-get update && apt-get install nginx -y && apt-get clean
          

          этом случае будет создано один слой
          2. если Вы идете другим путем: можно запустить контейнер с интерактивной консолью `docker run -it imagename /bin/bash` (по сути Вы будете находиться в комендной оболочке контейнера), что-то там устанавливать, настраивать и писать. когда вы произведете некоторые нужные Вам действия (установите тот же `nginx` и настроите его), то Вы можете сделать коммит этих изменений в следуюющий слой (аналог коммита в `git`). при этом у Вас в дереве слоев образа добавится новый слой с изменениями. каждый слой можно тегировать — это и есть названия образов. можно смотрить изменения, которые были произведены (`diff`).
          но я не советую использовать второй вариант поскольку если нужно будет поделиться этим образои или перенести или забекапить, то вам придется передавать его полностью. в случае же когда Вы пишете `Dockerfile`, вы все Ваши дейсвтия, производимые непосредственно в консоли, записываете командой `RUN` и дополнительно, если требуется, добавление файлов (готовых конфигов, к примеру). потом по этму файлу (наборов файлов если требуется `Dockerfile` + файлы конфигов, которые вы прописали в `Dockerfile` с помощью команд `ADD`, `COPY`) можно сбилдить образ, этими файлами проще поделиться — они намного меньше, чем результируючий образ — и другой человек тоже сбилдит образ на основе этих файлов
          • 0
            Именно так, просто не хотел писать коммент-статью про это ) Спасибо!
        • 0
          Ну вот я и хотел сказать что это должно быть также описано в статье, а мой вопрос был о другом. Что такое докер и какие у него возможности я давно уже изучил, но до сих пор я не вижу «места» где действительно есть смысл его использовать, вместо тех же контейнеров/виртуальных машин/отдельных серверов. При первом знакомстве с докером я подумал вот оно счастье: упакую сейчас каждый сайт в свой контейнер со своим софтом/базой и буду запросто переносить его куда мне нужно и просто бекапить — красота. Но разбираясь дальше я пришел к выводу что цели у докера другие и использовать его так как я хочу хоть и можно, но не так уж удобно. С тех пор пытаюсь понять где же его ниша и в какой ситуации он будет полезен.
          • 0
            докер — это инструмент, который работает с lxc-контейнерами и предоставляет расширенній API для работы. на сколько мне известно, то lxc зависим от конфигурации системы и его не так уж просто перенести на другой хост. докер же делает возможным в несколько команд развернуть контейнер, который крутился на одном хосте, развернуть на другом. идея докера состоит в том, чтобы именно упаковать некое приложение или приложения и запустить его в изолированном контейнере.
            для примера, можно без особых проблем на одном хосте в контейнерах запустить несколько версий серверов БД и иметь доступ к ним через разные порты
            лично для себя докер мне удобен тем, что я могу экспериментировать с софтом, вести веб-разработку и при этом держать хост-машину в чистоте
    • +1
      для начала посоветую познакомиться с коротким русскоязычным гайдом
  • 0
    Как вариант — некоторое время использовался Vagrant, но это всё-таки ovrerhead и наши поиски оптимального способа привели, на данный момент, к Docker.

    Vagrant не исключает Docker, более того, Vagrant поддерживает его уже не первый день.
  • 0
    > Когда наш контейнер будет запущен, внутри него запустится команда “ls”, которая покажет все файлы и фильтры в главной директории.

    О чем речь, что за фильтры?
  • 0
    Мне кажется, что всю статью надо было свести к последнему абзацу и ссылкой на fig.sh. На мойвзгляд fig может смело покрыть все нужды как локальной разработки, так и тестирования на удаленном сервере.
    • 0
      вот вы вспомнили о тестировании на удаленном сервере. сейчас я придумываю как сделать приемочное тестирование на хост-машине из-под контейнера. но пока ничего толкового не приходит в голову ибо, скорее всего, это невозможно. тоесть, невозможно из-под докера запустить firefox на хост-машине. а поднимать в докере xserver как-не нерезонно
      а что Вы скажете о приемочном тестировании в докере? понимаю, что юнит-тесты раскрутить не проблема и можно проводить приемочные тесты в фантоме, но вопрос именно о firefox
      • 0
        К сожалению, я вам тут помочь не смогу, т.к. подобным тестированем не занимался.
      • 0
        Вам поможет xvfb. Плюс, например, selenium.
      • 0
        phantom.js не рассматривали?
        • 0
          хотелось бы наблюдать за тем, что происходит

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