Деплой проекта на php/python с помощью Docker. Часть 2.

Создание контейнера для python-приложения

В случае с python'ом всё гораздо проще - в данном случае не надо обслуживать статику, настраивать nginx, копировать файлы настроек и т.п. Dockerfile выглядит так:

    FROM python:2.7.9

    RUN mkdir -p /usr/src/app
    WORKDIR /usr/src/app

    RUN pip install \
        tornado \
        mongoalchemy \
        apscheduler \
        redis \
        boto

    EXPOSE 8080

    CMD python server.py & > /dev/null && /bin/bash

Конейнер создаём на основе официального, с уже установленным python'ом 2.7 (FROM python:2.7.9). Далее всё просто - создаём рабочую директорию, указываем, что нам надо пробросить на хост машину порт 8080, на котором будет работать наше приложение, устанавливаем необходимые библиотеки и задаём команду запуска. Думаю, тут всё предельно просто и понятно

Скрипт запуска контейнера:

    #! /bin/bash
    sudo docker build -t example/python-app .
    sudo docker stop python-app
    sudo docker rm python-app
    sudo docker run -d -i -t \
        --name python-app \
        -v $PWD:/usr/src/app \
        -h python-app \
        --link mongo:mongo \
        --link redis:redis \
        -p 8080:8080 \
        example/python-app

Всё так же, как и в скрипте запуска контейнера для php-приложения. Вместо монтирования директории проекта (-v $PWD:/usr/src/app) можно было бы скопировать всё необходимое в контейнер ("ADD . /usr/src/app" в Dockerfile), так как здесь, в отличие от php, для обновления проекта одного git pull недостаточно и надо перезапускать контейнер. Но моё приложение пишет логи в текущую директорию и мне хотелось бы просматривать их там же.

Для деплоя приложения на продакшн-сервер я использую простой скрипт:

    #! /bin/bash
    git checkout master
    git pull origin master
    sudo docker restart python-app

Установка и настройка

Итак, у нас есть всё необходимое, чтобы развернуть проект на удалённом сервере. Далее - пошаговая инструкция, нагло скопированная из внутренней wiki :)

В первую очередь, на сервере нужен git

    sudo apt-get install git

Копируем ключ

    ssh-keygen
    cat ~/.ssh/id_rsa.pub

и даём этому серверу доступ к репозиториям в bitbucket/github.

Ставим docker. Для ubuntu server это делатся скриптом

    curl -sSL https://get.docker.com/ubuntu/ | sudo sh

Клонируем репозитории:

    git clone url-репозитория app
    git clone url-репозитория python-app

Скрипт для запуска бд хранится в моём случае в репозитории с php-приложением. Запускаем его, потом - скрипты для создания контейнеров приложений.

Набираем команду

    sudo docker ps

И ожидаем увидеть примерно следующее:

    CONTAINER ID        IMAGE                       COMMAND                CREATED             STATUS              PORTS                      NAMES
5ffcaf6c186f        example/python-app:latest   "/bin/sh -c 'python    4 minutes ago       Up 4 minutes        0.0.0.0:8080->8080/tcp     python-app
d364fac3517d        example/app:latest          "/bin/sh -c 'service   13 minutes ago      Up 13 minutes       0.0.0.0:80->80/tcp         app
7682066be8c9        redis:latest                "/entrypoint.sh redi   16 minutes ago      Up 16 minutes       0.0.0.0:6379->6379/tcp     redis
0959a6da8db9        mongo:2.4                   "/entrypoint.sh mong   16 minutes ago      Up 16 minutes       0.0.0.0:27017->27017/tcp   mongo

И, наконец, устанавливаем клиенты для работы с mongodb и redis:

    sudo apt-get install mongodb-clients
    sudo apt-get install redis-tools

Так как контейнеры работают на стандартных портах, работа с ними ничем не отличается от "обычной" работы с mongo и redis с помощью утилит mongo, mongodump, redis-cli и др.

Работа с контейнерами

Список запущенных контейнеров:

    sudo docker ps

Запуск/остановка/перезапуск контейнера:

    sudo docker start/stop/restart название-контейнера

Логи контейнера:

    sudo docker logs название-контейнера

top процессов контейнера:

    sudo docker top название-контейнера

Переменные окружения

Docker позволяет задавать переменные окружения linux, но я пошёл другим, на мой взгляд, более простым путём - в корневой директории проекта создаётся файл .env с информацией о текущем окружении (конечно же, он должен быть добавлен в .gitignore), который используется при инициализации конфига приложения. То есть, чтобы указать окружение проекта, например, на продакшн сервере, я пишу в консоли:

    echo "prod" > .env

Заключение

Итак, в этой статье я показал пример "контейнеризации" веб-приложения с помощью docker'а и разворачивания его на сервере. Пример довольно простой, но вполне пригодный для дальнейшего усовершенствования.

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

На этом всё, надеюсь, информация окажется для кого-то полезной, жду советов, отзывов, вопросов в комментариях.