|
|||||||
Виртуализация процесса разработки, часть 1: Docker
Время создания: 02.02.2018 13:50
Автор: Андрей Двояк
Текстовые метки: docker development tutorial
Раздел: Docker
Запись: Velonski/mytetra-database/master/base/15175614486e3p3bwlnu/text.html на raw.githubusercontent.com
|
|||||||
|
|||||||
Привет, меня зовут Андрей Двояк. Я специалист по комплексной разработке веб-приложений в украинском стартапе Preply.com , это платформа для поиска репетиторов. За последний год наша команда выросла, и для облегчения процесса адаптации новых разработчиков мы решили организовать и стандартизировать наш процесс разработки. Мы посвятили много времени поиску лучших методик и обсуждению с другими командами, стремясь выяснить, какой путь наиболее эффективен для организации процесса разработки и распределения доступа, особенно когда ваш продукт разделен на несколько микросервисов. В итоге мы остановились на двух основных технологиях: Vagrant и Docker. Вы можете прочитать обо всех аспектах и особенностях у самих создателей этих сервисов на StackOverflow . В этом руководстве я покажу вам, как «докеризировать» ваше приложение, чтобы вы таким образом могли удобно и просто распространить и развернуть его на любой машине, поддерживающей Docker. Прежде, чем начать В этом руководстве мы будем работать с простым приложением Django с базой PostgerSQL и Redis в качестве брокера для выполнения задач Celery . Также мы используем Supervisor для запуска нашего сервера Gunicorn . Мы будем использовать технологию Docker Compose , чтобы организовать работу нашего мультиконтейнерного приложения. Обратите внимание, что Compose 1.5.1 требует Docker 1.8.0 или более поздние версии. Это поможет нам запустить приложение Django, PostgreSQL и Redis Server и Celery Worker в отдельных контейнерах и связать их между собой. Чтобы реализовать это все, нам нужно всего лишь создать несколько файлов в корневом каталоге вашего проекта Django рядом с файлом manage.py):
Мы используем переменную RUN_ENV для определения текущей среды. Вы набираете на клавиатуре export RUN_ENV=PROD на рабочем сервере и export RUN_ENV=DEV на виртуальной машине Vagrant. Docker Как вы, возможно, уже знаете, о Docker нужно знать две вещи: образы и контейнеры. Мы создадим образ, основанный на Ubuntu с установленными Python, PIP и другими инструментами, необходимыми для запуска вашего приложения Django. В этом образе будет предустановлено всё, что необходимо. Этот образ направим в публичное хранилище в DockerHub. Имейте ввиду, что этот образ не содержит ни одного файла вашего проекта. Мы договорились хранить наш образ на DockerHub всегда обновленным. С этого образа мы загрузим контейнер, пробрасывая специфические порты и монтируя ваш локальный каталог с проектом к какой-то папке внутри контейнера. Это означает, что файлы вашего проекта будут доступны внутри контейнера. Никакой необходимости копировать файлы! Это очень удобно для процесса разработки, потому что вы можете вносить изменения в ваши файлы, и они сразу же будут изменены в работающем контейнере Docker, но это неприемлемо в реальной рабочей среде. Как только вы запустили контейнер, мы запустим Supervisor с вашим сервером Gunicorn. Как только вы захотели сделать повторное развертывание, мы извлечем новые данные из GitHub, остановим и удалим существующий контейнер и запустим совершенно новый контейнер. Настоящее волшебство! Установка Docker и Docker-Compose Прежде чем начать, нам нужно установить Docker и Docker-Compose на наш локальный компьютер или сервер. Ниже указан скрипт, который это делает на Ubuntu 14.04: sudo -i echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections curl -sSL https://get.docker.com/ | sh curl -L https://github.com/docker/compose/releases/download/1.5.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose usermod -aG docker ubuntu sudo reboot Тут ubuntu — ваш текущий пользователь. Если ваша текущая среда разработки не Ubuntu 14.04 — тогда вам будет лучше использовать Vagrant для создания этой среды. Подробнее расскажу в следующей статье. Образ Docker Во-первых, для подготовки проекта к развертыванию докером нам нужно создать образ при помощи только Python, PIP и нескольких зависимостей, необходимых для запуска Django. Давайте создадим новый докер файл под названием Dockerfile в корневом каталоге проекта. Это будет выглядеть так: FROM ubuntu:14.04 MAINTAINER Andrii Dvoiak RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections RUN apt-get update RUN apt-get install -y python-pip python-dev python-lxml libxml2-dev libxslt1-dev libxslt-dev libpq-dev zlib1g-dev && apt-get build-dep -y python-lxml && apt-get clean # Specify your own RUN commands here (e.g. RUN apt-get install -y nano) ADD requirements.txt requirements.txt RUN pip install -r requirements.txt WORKDIR /project EXPOSE 80 Вы можете указать ваши собственные команды RUN, например, установить другие необходимые инструменты. Затем вам нужно создать образ из этого, используя команду: docker build -t username/image Тут username — ваше имя пользователя Dockerhub и image — название вашего нового образа для данного проекта. Когда вам успешно удалось создать основной образ, лучше будет вам загрузить в облако DockerHub. Это можно сделать командой docker push username/image. И не переживайте, в этом образе нет никакой информации из вашего проекта (кроме файла requiremets.txt). Если вы используете приватное хранилище DockerHub, удостоверьтесь в исполнении docker login перед загрузкой/выгрузкой образов. Организация работы контейнеров Итак, на данном этапе мы можем запустить наш контейнер с приложениям Django, но нам также нужно запустить некоторые другие контейнеры c Redis, базой данных PostgreSQL и Celery Worker. Чтобы упростить этот процесс, мы воспользуемся технологией Docker Compose , которая позволяет нам создать простой файл YML с инструкциями о том, какие контейнеры запускать и как линковать их между собой. Давайте создадим этот волшебный файл и назовем его по умолчанию docker-compose.yml: django: image: username/image:latest command: python manage.py supervisor environment: RUN_ENV: "$RUN_ENV" ports: - "80:8001" volumes: - .:/project links: - redis - postgres celery_worker: image: username/image:latest command: python manage.py celery worker -l info links: - postgres - redis postgres: image: postgres:9.1 volumes: - local_postgres:/var/lib/postgresql/data ports: - "5432:5432" environment: POSTGRES_PASSWORD: "$POSTGRES_PASSWORD" POSTGRES_USER: "$POSTGRES_USER" redis: image: redis:latest command: redis-server --appendonly yes Как вы видите, мы запустим четыре проекта под названиями django, celery_worker, postgres и redis. Эти названия важны для нас. Итак, во-первых, наш файл загрузит образ Redis из dockerhub и запустит из него контейнер. Во-вторых, он загрузит образ Postgres и запустит контейнер с закрепленными данными из радела local_postgres. О создании локальной базы данных расскажу подробней в следющей статье. Затем, этот файл запустит контейнер с нашим приложением Django, направит 8001-й порт изнутри на 80-й снаружи, свяжет ваш текущий каталог прямо с папкой /project внутри контейнера, пролинкует его с контейнерами Redis и Postgres и запустит супервайзера. И последнее, но не менее важное — наш контейнер с celery worker, который также пролинкован с Postgres и Redis. Вы можете направить любое количество портов, если необходимо — для этого просто добавьте новые записи в соответствующий раздел. Также вы можете пролинковать любое количество контейнеров, например, контейнер с вашей базой данных. Используйте тег :latest для автоматической проверки обновленного образа на DockerHub. Если вы назвали проект Redis Server именем redis в файле YML — вам нужно указать redis вместо localhost в вашем settings.py чтобы позволить вашему приложению Django подсоединиться к redis: REDIS_HOST = "redis" BROKER_URL = "redis" То же с базой данных Postgres — используйте postgres вместо localhost: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'database_name', 'USER': os.getenv('DATABASE_USER', ''), 'PASSWORD': os.getenv('DATABASE_PASSWORD', ''), 'HOST': 'postgres', 'PORT': '5432', } } Скрипт для повторного развертывания Давайте создадим скрипт для повторного развертывания в один клик (давайте назовем его redeploy.sh): #!/bin/sh if [ -z "$RUN_ENV" ]; then echo 'Please set up RUN_ENV variable' exit 1 fi if [ "$RUN_ENV" = "PROD" ]; then git pull fi docker-compose stop docker-compose rm -f docker-compose up -d Давайте проверим, что он делает: Итак, это выглядит достаточно просто: чтобы сделать повторное развертывание, вам нужно всего лишь запустить ./redeploy.sh. Не забудьте дать права на исполнение (chmod +x redeploy.sh) этому скрипту и всем другим скриптам, описанным в инструкции. Чтобы сделать быстрое повторное развертывание, используйте эту команду: docker-compose up --no-deps -d django Развертывание внутри контейнера Нам нужно всего лишь запустить супервайзера для того, чтобы собственно запустить наш сервис внутри контейнера: python manage.py supervisor. Если вы не используете супервайзер, вы можете просто запустить ваш сервер вместо супервайзера. Если же вы пользуетесь супервайзером, давайте посмотрим на файл ’supervisord.conf’: [supervisord] environment=C_FORCE_ROOT="1" [program:__defaults__] redirect_stderr=true startsecs=10 autorestart=true [program:gunicorn_server] command=gunicorn -w 4 -b 0.0.0.0:8001 YourApp.wsgi:application directory={{ PROJECT_DIR }} stdout_logfile={{ PROJECT_DIR }}/gunicorn.log Итак, супервайзер запустит ваш сервер Gunicorn с 4 работающими процессами и связанным портом 8001. Процесс разработки Чтобы зайти на ваш локальный сервер, пройдите по 127.0.0.1:8000 . Для повторного развертывания локальных изменений сделайте: Чтобы просмотреть все логи в вашем проекте, выполните: Чтобы быстро реализовать повторное развертывание изменений, используйте: Чтобы подсоединиться к Django — просто подсоединяйтесь (если ваш работающий контейнер назван CONTAINER): Чтобы создать изначального суперпользователя: Выполнить миграцию: Или вы можете подсоединиться к bash внутри контейнера: Вы можете сохранить вашу локальную базу данных в файл .json (вы можете указать таблицу для сохранения): Или вы можете загрузить данные в вашу базу данных из файла: Используйте эту команду для мониторинга статуса ваших работающих контейнеров: Используйте эту команду для удаления всех остановленных контейнеров: Вы можете играться с вашими контейнерами как вам захочется. Здесь — полезный Docker cheat sheet . GIT Когда сервер работает, он будет создавать дополнительные файлы, такие как .log, .pid и так далее. Вам не нужно их включать в репозиторий. Не забудьте создать файл .gitignore: .idea db.sqlide3 *.pyc *.ini *.log *.pid /static .vagrant/ Статические файлы У вас могут обнаружиться некоторые проблемы в работе со статическими файлами на рабочем сервере при использовании только gunicorn, поэтому не забудьте создать пустую папку /static/ в вашем корневом каталоге проекта с файлом __init__.py для обслуживания из него статики. По этой схеме ваш файл settings.py должен включать: STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static') И для обслуживания статики с помощью gunicorn на рабочем сервере добавьте это в конец файла urls.py: SERVER_ENVIRONMENT = os.getenv('RUN_ENV', '') if SERVER_ENVIRONMENT == 'PROD': urlpatterns += patterns('', (r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}), ) Или же вы можете пользоваться другими сервисами для обслуживания статических файлов, например, использовать сервер nGinx.
|
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|