Автоматический запуск службы в контейнере 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
, поскольку я всегда использую загрузочный файл.