Как заставить systemd запускать контейнеры через docker-compose?

Дано:
СoreOS Linux 4.7.0 v1122.2.0 Stable
Docker version 1.10.3, build 1f8f545
docker-compose version 1.7.1, build 0a9ab35

Суть проблемы:
Есть несколько групп контейнеров, назовем из PR1 и PR2 есть ststemd сервис который запускает bash в котором прописаны команды docker-compose. Если в проекте нет data volume контейнеров PR1 сервис работает и все хорошо, я могу запускать или останавливать сервис. Но как только добавляется второй проект PR2 в котором есть контейнер с данными получаю на выходе exit-code после чего все контейнеры тушатся, хотя Exit 0 не значит что данные не замапились, контейнер работает.

Читал в документации CoreOS что контейнеры запускают командой docker run ... но такой способ запуска не подходит, контейнеров много, и каждый запихивать в сервис желания нет. В docker-compose прописаны все параметры работы контейнеров, сети ну и пр.
Вообще задача стояла что бы при перезапуске машины контейнеры сами стартовали, но т.к в CoreOS все вырезано в том числе и cron я не придумал как это сделать кроме написания systemd сервиса.

● docker-project.service - Docker containers start
   Loaded: loaded (/etc/systemd/system/docker-project.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Thu 2016-10-20 14:02:18 UTC; 5min ago
   Process: 4941 ExecStop=/home/coreos/docker-stop.sh (code=exited, status=0/SUCCESS)
   Process: 805 ExecStart=/home/coreos/docker-up.sh (code=exited, status=1/FAILURE)
   Main PID: 805 (code=exited, status=1/FAILURE)

Все листинги находятся ниже:
PR1
Name  Command  State       Ports
-------------------------------------------------------
rp_nginx_web_1  nginx -g daemon off;  Up  443/tcp, 80/tcp
rp_php_1        php-fpm               Up  9000/tcp

PR2
Name  Command  State       Ports
-------------------------------------------------------
rps_app_1           sh        Up          9000/tcp
rps_code_source_1   true     Exit 0


Systemd config
[Unit]
Description=Docker containers start
Requires=docker-project.service
After=docker-project.service

[Service]
ExecStart=/home/coreos/docker-up.sh
ExecStop=/home/coreos/docker-stop.sh

[Install]
WantedBy=multi-user.target

Содержимое скрипта docker-up.sh
#!/bin/bash
/opt/bin/docker-compose -f /home/coreos/PR1/docker-compose.yml up --no-recreate --no-build
/opt/bin/docker-compose -f /home/coreos/PR2/docker-compose.yml up --no-recreate --no-build


Всем спасибо кто примет участие в решении проблемы.
  • Вопрос задан
  • 2617 просмотров
Решения вопроса 1
Tyranron
@Tyranron
1. Чтобы при перезапуске машины контейнеры сами стартовали, нужно всего лишь соответствующий systemd service сделать enabled. Cron здесь не нужен.
sudo systemctl enable docker-project.service

2. Любой systemd service - это всего лишь абстракция. А что именно он выполняет - решать именно Вам. Что у Вас ExecStart'ом будет стартовать один контейнер через docker run, что связка контейнеров через docker-compose up, для systemd и CoreOS принципиальной разницы нет.

3. В приведенной Вами декларации systemd service'а в секции [Unit] есть следующие строки:
Requires=docker-project.service
After=docker-project.service

Они означают, что декларируемый Вами service должен быть запущен только после того, как был запущен docker-project.service. Но, насколько я понимаю из Вашего описания, это и есть декларация docker-project.service. То есть Вы говорите systemd что сервис должен быть запущен после запуска самого себя. Это не есть гуд. Эти строки, судя по всему, должны быть такими:
Requires=docker.service
After=docker.service

Дабы systemd пытался запустить этот сервис только после того, как будет запущен Docker daemon.

4. В файлике docker-up.sh у Вас docker-compose up запускается в foreground'е. Первая связка контейнеров то запустится, а что со второй - не понятно. Наверное, все же стоило их запускать с -d ключиком, а в systemd декларации в секции [Service] указать Type=forking, если прям так нужно обе связки контейнеров запускать одним systemd service. Но вообще, имхо, на каждый docker-compose.yml должен быть свой отдельный systemd service, и никаких forking.
Также, заворачивать docker-compose команды внутрь docker-up.sh было не самой хорошей идеей. Вам ничего не мешало написать несколько ExecStart'ов подряд, тем самым не размазывая декларацию по нескольким файлам, и было бы видно на каком именно шаге оно отваливается при systemctl start docker-project.service.

5. Логи наше все. Используйте journalctl --unit=docker-project.service дабы глянуть что там вообще произошло, и кто на кого ругается.

В заключение:
Вообще, честно говоря, видно полное профанство с Вашей стороны по данному вопросу. Это нормально, ведь невозможно знать все технологии и инструменты, и постоянно приходится что-то изучать. Не нормально то, что ничего не мешает заглянуть в официальную документацию по тому же systemd. 20-30 минут чтения хотя бы этой страницы, и подобного непонимания бы просто не было.
Пожалуйста, не поленитесь, потратьте немного времени и почитайте доки. Systemd умеет ещё много чего, что сможет Вам помочь в решении Ваших задач, и даст понимание что, куда, и как.

К размышлению:
Раз уж Вы используете CoreOS, посмотрите в сторону Kubernetes для запуска сервисов/контейнеров. Ставится на CoreOS он в пол-оборота, а возможностей, гибкости и вкусных абстракций уж гораздо поболее, нежели у systemd/fleet.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@om1058
Но ведь докер сам умеет перезапускать контейнеры. В docker-compose.yml просто добавляется restart: always для каждого сервиса. Ключевые слова для поиска "docker restart policy"
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы