Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Докеризация приложений на Python

Докеризация приложений на Python

Антон Егоров @ MoscowPython 35

Moscow Python Meetup

May 23, 2016
Tweet

More Decks by Moscow Python Meetup

Other Decks in Technology

Transcript

  1. Кто я такой? Не твое дело! • Ведущий разработчик и

    DevOps инженер в компании Островок.ру • 10 лет в индустрии веб-разработки из них 5 лет в Островке • Основной язык разработки – Python • Опыт работы с Докером – 2 года • Докеризировал около 50 прод-приложений, из них 80% были на Python • В Островке ответственный за кучу терабайт фоток и географию, а также за докеризацию приложений и подготовку их к выкладке в продакшен 2
  2. План • В общем о технологии Docker • Сборка образа

    для своего приложения • Немного про деплой в продакшен 3
  3. Я надеюсь, что вы... • слышали о Docker • конечно

    же, писали веб-приложения на Python • хотябы немного знаете Linux • представляете, как должен работать ваш код в продакшене 4
  4. Установка софта • Docker Engine ◦ Сам Docker, хост для

    сборки/запуска контейнеров ◦ Актуальные инструкции для всех ОС https://docs.docker.com/engine/installation/ ◦ Ванлайнер для любого Линукса curl -sSL https://get.docker.com/ | sh • Docker Compose ◦ Инструмент для запуска многоконтейнерных приложений с удобным конфигом в формате yaml. Можно трактовать как обертку вокруг docker cli ◦ Актуальные инструкции для всех ОС https://docs.docker.com/compose/install/ ◦ Всегда можно поставить как pip install docker-compose • Docker Machine ◦ Утилита для провиженинга удаленных докер-хостов, также удобна для создания локального докер-хоста для Mac OS X и Windows, используя virtualbox driver ◦ Актуальные инструкции для всех ОС https://docs.docker.com/machine/ 5
  5. Что это за покемон? • Docker – это ПО для

    автоматизации деплоя приложения в среде виртуализации на уровне ОС (в виде контейнеров) • Docker-контейнеры содержат внутри себя все, что нужно для запуска приложения: библиотеки, системные утилиты и, конечно, ваш код • Доставляя свое приложекие в контейнерах вы гарантируете окружение, в котором оно будет запущено, и имеете возможность отлаживать его у себя локально в том же виде, как оно работает в продакшене • Важно понимать, что Docker – это НЕ замена LXC или Hypervisor, это инструмент для доставки вашего приложения 7
  6. Образы и контейнеры • Мы создаем Docker-образ для нашего приложения,

    прописывая инструкции в Dockerfile (ставим нужный софт, копируем файлы) • Docker использует файловую систему, которая позволяют писать образ слоями (напрмер AUFS) и позволяет ускорять сборку образов и запуск контейнеров • Каждая инструкция в Dockerfile – это отдельный слой. Есть правила кэширования этих слоев (это ускоряет сборку) 8
  7. Слои контейнера FROM ubuntu:16.04 Base Image RUN apt-get install -y

    python3 Image COPY demo/ /opt/demo/app/ Image writable Container 9
  8. Workflow 1. Пишем Dockerfile для приложения (один раз) 2. Готовим

    релиз a. Собираем образ (локально или на CI) b. Пушим образ в репозиторий с указанием тэга (версии) 3. Доставляем a. Пулим образ нужной версии на прод-хосте b. Останавливаем и удаляем старый контейнер c. Запускаем контейнер из нового образа 4. Если что-то пошло не так a. Останавливаем и удаляем текущий контейнер b. Запускаем контейнер для той версии образа, на которой все работало 10
  9. Чего делать НЕ надо • Не пытайтесь хранить в контейнерах

    данные, используйте volumes или внешние хранилища, например S3 (в зависимости от задачи) • В примерах в документации вы встретите команду docker commit, она не нужна, все что нужно прописывайте в Dockerfile 11
  10. Приложение • Наш подопытный app сделан на Django и называется

    demo • Мы пишем на Python 3 • Статику (css, js, img) раздаем из того же контейнера • Мы не думаем о HTTPS, так как за нас это делает абстрактный фронтэнд (например: nginx, haproxy, hipache или AWS ELB) • Мы пока не думаем о логах и мониторинге, это отдельная тема 13
  11. cd ~/devel/demo && ls -la • Dockerfile – инструкции для

    сборки образа • .dockerignore – что не надо прокидывать в контекст • requirements.txt – зависимости нашего приложения • demo – исходники приложения ◦ manage.py ◦ demo/settings.py ◦ demo/wsgi.py ◦ demo/gunicorn.py • etc – конфигурационные файлы ◦ nginx ◦ circus 14
  12. Dockerfile, основа FROM ubuntu:16.04 RUN export DEBIAN_FRONTEND=noninteractive \ && apt-get

    update -y && apt-get upgrade -y \ && apt-get install -y nginx-light python3 python3-pip python3-psycopg2 \ && BUILD_DEPS='build-essential python3-dev' \ && apt-get install -y ${BUILD_DEPS} \ && pip3 install --no-cache-dir circus==0.13.0 gunicorn==19.5.0 \ && apt-get autoremove -y ${BUILD_DEPS} \ && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 15
  13. Dockerfile, примечания • По возможности склеивайте RUN инструкции, это уменьшит

    количество слоев и ускорит push/pull образа • Удаляйте все что не нужно было только для билда сразу в том же шаге, это уменьшит размер образа • Мы устанавливаем и в этом же слое удаляем пакеты build-essential и python3-dev для уменьшения размера образа. Если вам надо будет поставить питонячий пакет требующий сборки, сделайте это либо там же где я ставлю circus, либо не удаляйте билдовые зависимости. • Установку системный зависимостей делаем отдельным шагом, чтобы он закэшировался и последуящая сборка проходила на много быстрее 16
  14. Dockerfile, зависимости Контейнер сам по себе является изолированным окружением, поэтому

    нет необходимости создавать virtualenv для своих зависимостей, можно делать установку прямо в системный python COPY requirements.txt /opt/demo/app/ RUN pip3 install --no-cache-dir -r /opt/demo/app/requirements.txt Шаг с установкой зависимостей мы также сделали отдельным слоем, чтобы он закэшировался, так же как и шаг с системными зависимостями. При таком подходе время сборки контейнера будет занимать только копирование исходников и сборка статики. 17
  15. Dockerfile, наше приложение COPY etc/ /etc/ COPY demo/ /opt/demo/app/ WORKDIR

    /opt/demo/app ENV STATIC_ROOT=/opt/demo/static RUN nginx -t \ && python3 -c 'import compileall, os; compileall.compile_dir(os.curdir, force=1)' > /dev/null \ && ./manage.py collectstatic --settings=demo.settings --no-input -v0 CMD ["circusd", "/etc/circus/web.ini"] 18
  16. [watcher:nginx] cmd = /usr/sbin/nginx stop_signal = QUIT user = root

    [watcher:web] cmd=/usr/local/bin/gunicorn demo.wsgi:application -c gunicorn.py working_dir = /opt/demo/app copy_env = True user = www-data etc/circus/web.ini 20
  17. etc/nginx/sites-available/default server { listen 80; location / { include proxy_params;

    proxy_pass http://127.0.0.1:8000; } location /static/ { root /opt/demo/; access_log off; } } 21
  18. demo/gunicorn.py import multiprocessing import os bind = '127.0.0.1:8000' default_workers =

    multiprocessing.cpu_count() * 2 + 1 workers = os.environ.get('WEB_CONCURRENCY', default_workers) worker_class = 'sync' max_requests = 300 max_requests_jitter = 300 errorlog = '-' 22
  19. demo/settings.py Конекшен к базе удобно передавать через ENV переменную, распарсить

    DSN можно с помощью библиотеки dj_database_url DATABASES = { 'default': dj_database_url.config( env='DATABASE_URL', default='postgres://localhost/demo')} Тоже самое с каталогом, куда будет писать manage.py collectstatic STATIC_ROOT = os.getenv('STATIC_ROOT') 23
  20. Сборка образа Запускаем команду build с указанием локального имени для

    образа. По- умолчанию build ищет Dockerfile в текущей директории, но можно указать и полный путь. Контекстом для сборки является указанная директория, ссылка или поток docker build -t demo . Подробнее про сборку читайте в документации https://docs.docker.com/engine/reference/builder/ https://docs.docker.com/engine/reference/commandline/build/ 25
  21. Пуш в репозиторий Мы собрари образ. Этого достаточно для того

    чтобы запустить контейнер локально, но для того чтобы запустить его на другои хосте, надо запушить его в репозиторий. Сначала надо проставить образу правильное имя с которым мы будет записывать его в репозиторий docker tag demo myrepo/demo:0.1.2 Затем надо залогиниться (еще это еще ни разу не делали) и пушить docker login --username=myuser [email protected] docker push myrepo/demo:0.1.2 26
  22. Запуск контейнера Собраный образ можно запустить с помощью команды run.

    Если мы это делаем не там, где собирали, то предварительно образ надо спулить docker pull myrepo/demo:0.1.2 docker run --name=web -p 80:80 -d myrepo/demo:0.1.2 В итоге, на хосте будет образ с именем myrepo/demo:0.1.2 и запущенный контейнер с именем web и опубликованым 80 портом. В запущенном контейнере можно исполнять команды с момощью exec docker exec web ps auxwf docker exec -it web bash 27
  23. docker-compose.yml web: build: . container_name: web environment: DJANGO_SETTINGS_MODULE: demo.settings_prod DATABASE_URL:

    postgres://postgres:secret@db/demo ALLOWED_HOSTS: "*" ports: - "80:80" db: image: postgres:9.5 environment: POSTGRES_PASSWORD: "secret" POSTGRES_DB: "demo" volumes: - /var/lib/postgresql/data 29
  24. Собираем и запускаем Запускаем сборку нашего образа docker-compose build Создаем

    и стартуем контейнеры, описанные в docker-compose.yml docker-compose up -d База свежая, на нее надо накатить все миграции docker exec -it web /opt/demo/app/manage.py migrate 30
  25. Куда пушить свои образы • Есть официальный и тормозной Docker

    Hub https://hub.docker.com/ • Amazon предоставляет свой Registry (но он доступен не во всех регионах) https://aws.amazon.com/ecr/ • Google не отстает https://cloud.google.com/container-registry/ • А вообще довольно просто поднять свой Docker Registry https://cloud. google.com/container-registry/ ◦ Не забывайте про TLS ◦ Храните данные на Amazon S3, а не локально 32
  26. Как запустить в продакшене • Если приложение простое, то можно

    воспользоваться тем же docker- compose (больше профита в комбинации с Docker Machine) • Если требуется релизить более, чем на один хост, пишите скрипт для автоматизации (например на Ansible) • Есть официальные решения для релиза большого кластера контейнеров ◦ Docker Swarm https://docs.docker.com/swarm/ ◦ Docker Universal Control Plane https://docs.docker.com/ucp/ • Есть также популярные большие софтины ◦ Google Kubernetes http://kubernetes.io/ ◦ Apache Mesos http://mesos.apache.org/ 33
  27. Ссылки • Docker Docs https://docs.docker.com/ • Dockerfile best practices (official

    guide) https://docs.docker. com/engine/articles/dockerfile_best-practices/ • Circus https://circus.readthedocs.io/en/latest/for-ops/configuration/ • Gunicorn http://docs.gunicorn.org/en/stable/settings.html • Demo App https://github.com/satyrius/paid 34
  28. Ostrovok.ru is hiring • Python Developers for Content, Extranet, Finance,

    SEM teams • Go Developers for Backend and APIs teams • Analyst Developer (Graph Theory) • Android and iOS Developer 35 • More positions at https://jobs. lever.co/ostrovok.ru • Email your resume hr@ostrovok. ru