Как интегрировать Capistrano с Docker для развертывания?

Я не уверен, что мой вопрос актуален, поскольку я могу попытаться смешать инструменты (Capistrano и Docker), которые не должны быть смешаны.

недавно я dockerized приложение, которое развертывается с Capistrano. Docker compose используется как для разработки, так и для промежуточных сред.

вот как выглядит мой проект (файлы приложений не отображаются):

Capfile
docker-compose.yml
docker-compose.staging.yml
config/
    deploy.rb
    deploy
        staging.rb

Docker Compose files создает все необходимые контейнеры (Nginx, PHP, MongoDB, Elasticsearch, etc.) для запуска приложения в среде разработки или промежуточной среды (следовательно, некоторые конкретные параметры, определенные в docker-compose.staging.yml).

приложение развертывается в промежуточной среде с помощью этой команды:

cap staging deploy

архитектура папок на сервере-это архитектура Capistrano:

current
releases
    20160912150720
    20160912151003
    20160912153905
shared

следующая команда была запущена в current каталог промежуточного сервера для создания экземпляра всех необходимых контейнеров для запуска app:

docker-compose -f docker-compose.yml -f docker-compose.staging.yml up -d

пока все хорошо. Все усложняется при следующем развертывании:current символическая ссылка будет указывать на новый каталог :

  • если deploy.rb определяет команды, которые должны выполняться внутри контейнеров (например,docker-compose exec php composer install для PHP), Docker сообщает, что контейнеры еще не существуют (потому что существующие были созданы в предыдущей папке выпуска).
  • если docker-compose up -d команда выполняется в Capistrano в процессе развертывания я получаю некоторые ошибки из-за конфликтов портов (предыдущие контейнеры все еще существуют).

у вас есть идея, как решить эту проблему? Должен ли я отойти от Капистрано и сделать что-то другое?

идея заключалась бы в том, чтобы сохранить (почти) развертывание с нулевым временем простоя, которое Capistrano предлагает с гибкостью контейнеров Docker (например, предоставляя несколько версий PHP для различных приложений на одном сервере).

2 ответов


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

в то время как вы делаете это в основном, при запуске cap deploy

  • создайте приложение (на основе текущей базы, которую вы вытащили на хосте ) - возможно, даже включает в себя gulp/grunt/build tasks
  • затем вы "упаковываете" его в свой контейнеры с использованием "Volume mounts"
  • во время этого вы запускаете / заменяете контейнеры

вы делаете это, чтобы получить "почти" нулевое развертывание простоя.

если вы действительно заботитесь о времени простоя и о формализации процесса развертывания, вы должны сделать это правильно, используя правильную реализацию конвейера для

  • упаковка / ci
  • развертывание / распределение

Я не думаю capistrano может / должен быть одним из инструментов, которые вы можете использовать во время этой стратегии. Capistrano предназначен для развертывания приложения непосредственно на сервере с использованием ssh и git в качестве транспорта. Использование cap для создания целых изображений на целевом сервере, чтобы затем запустить их как контейнеры, действительно сверху, IMHO.

упаковка / здания

либо используйте CI / CD-сервер, такой как jenkins/bamboo/gocd, чтобы создать для вас приложение release-image. Предполагая, что только приложение настроено в условия "выпуска", скажем, у вас есть БД и приложение в качестве контейнеров/сервисов, приложение будет включать ваш исходный код и будет регулярно меняться во время выпусков..

таким образом, его процесс CD/CI для создания нового app-image (release) offsite на вашем сервере CI. Вытягивание исходного кода вашего приложения и упаковка его в изображение с помощью COPY а потом любой RUN оператор для компиляции ваших активов (npm / gulp / grunt whatever ). Все это происходит не на производственном сервере, а на CI / CD агент.

затем вы нажимаете этот релиз-образ, давайте назовем это изображение yourregistry.com/yourapp в своем частный реестр как новая "версия" для развертывания.

развертывание

с простоем (легко)

для развертывания на вашем производственном или промежуточном сервере с простоем вы просто сделаете docker-composer stop && docker-composer up - это автоматически вытащит новое изображение, а затем запустите его в своем стеке-ваше приложение обновлено

сервер должен конечно можно извлечь из личного хранилища.

без простоя (больше усилий)

достижение развертывания с нулевым временем простоя вы должны использовать сине-зеленая концепция развертывания. Таким образом, вы добавляете прокси-сервер в свою установку и больше не предоставляете публичный порт из приложения, а используете этот публичный порт прокси-сервера. Ваша текущая живая система может работать на случайном порту 21231, прокси-сервер перенаправляет с 443 на 21231.

мы используем случайные порты чтобы избежать конфликта при развертывании "второй" системы, охватывающей одну из упомянутых вами проблем.

при повторном развертывании вы будете запускать только "новый" контейнер на основе нового app - image В дополнение (к старому), он получает новый случайный порт 12312-если хотите, запустите интеграционные тесты agains 12312 напрямую ( не используйте прокси ). Если вы закончили и счастливы, перенастроите прокси-сервер теперь вперед на 12312-затем удалите старый контейнер (21231).

если вы хотите автоматизируйте прокси-реконфигурацию, которая подробно выходит за рамки этого вопроса, Вы можете использовать service-discovery и регистратор, который делает случайные порты гораздо более практичными и упрощает перенастройку прокси-сервера, пусть это будет nginx/haproxy во время их работы. Инструменты были бы, например.


Я не думаю, что Капистрано является правильным инструментом для работы. Это недавно обсуждалось в PR для SSHKit, который лежит в основе Capistrano.

https://github.com/capistrano/sshkit/pull/368

@EugenMayer лучше объясняет "нормальный" способ использования Docker.