Автоматический запуск службы в контейнере docker

я настраиваю простой образ: тот, который содержит Riak (база данных NoSQL). Изображение запускает службу Riak с помощью riak start как CMD. Теперь, если я запущу его как демон с docker run -d quintenk/riak-dev, он запускает процесс Riak (я вижу это в журналах). Однако через несколько секунд она автоматически закрывается. Если я запускаю его с помощью docker run -i -t quintenk/riak-dev /bin/bash процесс riak не запущен (обновление: см. ответы для объяснения этого). Фактически, никакие службы не работают вообще. Я могу запустить его вручную с помощью терминала, но Я бы хотел, чтобы РИАК начал автоматически. Я полагаю, что такое поведение будет происходить и для других служб, Riak-просто пример.

Итак, запуск / перезапуск контейнера должен автоматически запустить Riak. Каков правильный подход к этому?


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

FROM ubuntu:12.04
RUN apt-get update
RUN apt-get install -y openssh-server curl 
RUN curl http://apt.basho.com/gpg/basho.apt.key | apt-key add -
RUN bash -c "echo deb http://apt.basho.com precise main > /etc/apt/sources.list.d/basho.list"
RUN apt-get update
RUN apt-get -y install riak
RUN perl -p -i -e 's/(?<={http,s[s{")127.0.0.1/0.0.0.0/g' /etc/riak/app.config
EXPOSE 8098 
CMD /bin/riak start && tail -F /var/log/riak/erlang.log.1

EDIT: - F изменен на-F в CMD в соответствии с sesm его замечание


МОЙ СОБСТВЕННЫЙ ОТВЕТ

после работы с докером в течение некоторого времени я взял привычку использовать supervisord для настройки моих процессов. Если вы хотите пример кода для этого, проверьтеhttps://github.com/Krijger/docker-cookbooks. Я использую свой образ супервизора в качестве основы для всех моих других изображений. Я написал в блоге об использовании supervisor здесь.

6 ответов


чтобы контейнеры docker продолжали работать, необходимо поддерживать активный процесс на переднем плане.

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

CMD /bin/riak console

или даже

CMD /bin/riak start && tail -F /var/log/riak/erlang.log.1

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


использование хвоста для поддержания контейнера в живых-это хак. Также обратите внимание, что с -f контейнер опций завершится, когда произойдет вращение журнала (этого можно избежать, используя -F вместо).

лучшее решение-использовать руководитель. Взгляните на это учебник о запуске Riak в контейнере Docker.


объяснение:

если я запускаю его с помощью docker run -i -t quintenk/riak-dev /bin/bash процесс riak не запущен

выглядит следующим образом. Использование CMD в Dockerfile фактически является той же функциональностью, что и запуск контейнера с помощью docker run {image} {command}. Как заметил Гигаблах, используется только последний CMD, поэтому в этом случае перезаписывается написанный в Dockerfile.

С помощью CMD /bin/riak start && tail -f /var/log/riak/erlang.log.1 в Buildfile, вы можете запустить контейнер в качестве фонового процесса с использованием docker run -d {image}, который работает как шарм.


"если я запускаю его с помощью docker run-i-t quintenk/riak-dev /bin/bash, процесс riak не запускается"

похоже, вы хотите только иметь возможность контролировать журнал при подключении к контейнеру. Мой вариант использования немного отличается тем, что я хочу, чтобы команды запускались автоматически, но я хочу иметь возможность прикрепляться к контейнеру и быть в оболочке bash. Я смог решить обе наши проблемы следующим образом:--7-->

в образе/контейнере добавьте команды, которые вы хотите автоматически запускаются до конца .

в вашем случае просто добавьте строку /bin/riak start && tail -F /var/log/riak/erlang.log.1, или put /bin/riak start и tail -F /var/log/riak/erlang.log.1 на отдельной линии в зависимости от требуемой функциональности.

теперь зафиксируйте изменения в контейнере и запустите его снова с помощью: docker run -i -t quintenk/riak-dev /bin/bash. Вы найдете команды, которые вы помещаете в bashrc, уже запущены по мере присоединения.


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

arthur@macro:~/docker$ sudo docker run -d -t -i -v /raid:/raid -p 4040:4040 subsonic /bin/bash -c 'service subsonic start && read -p "waiting"'
WARNING: Docker detected local DNS server on resolv.conf. Using default external servers: [8.8.8.8 8.8.4.4]
f27229a260c9

arthur@macro:~/docker$ sudo docker ps                                                                                                                                     
[sudo] password for arthur: 
ID                  IMAGE               COMMAND                CREATED              STATUS              PORTS
35f253bdf45a        subsonic:latest     /bin/bash -c service   2 days ago          Up 2 days           4040->4040

arthur@macro:~/docker$ sudo docker attach 35f253bdf45a

arthur@macro:~/docker$ sudo docker ps                                                                                                                                     
ID                  IMAGE               COMMAND             CREATED             STATUS              PORTS

как вы можете видеть выходы контейнера после присоединения к нему и разблокирования чтения. Конечно, вы можете использовать более сложный скрипт, чем read -p Если вам нужно сделать другую очистку, например, остановить службы и сохранить журналы и т. д.


Я использую простой трюк, когда я начинаю строить новый контейнер docker. Чтобы сохранить его, я использую ping в скрипте entrypoint.

поэтому в Dockerfile, например, при использовании debian, я удостоверяюсь, что могу пинговать. Это кстати, всегда приятно, чтобы проверить, что доступно из контейнера.

...
RUN DEBIAN_FRONTEND=noninteractive apt-get update \
 && apt-get install -y iputils-ping 
...
ENTRYPOINT ["entrypoint.sh"]

и в entrypoint.sh файл

#!/bin/bash
...
ping 10.10.0.1 >/dev/null 2>/dev/null

Я использую это вместо CMD bash, поскольку я всегда использую загрузочный файл.