Как автоматически запустить службу при запуске Docker-контейнера?

157

У меня есть Dockerfile для установки сервера MySQL в контейнере, который я затем запускаю так:

sudo docker run -t -i 09d18b9a12be /bin/bash

Но служба MySQL не запускается автоматически, я должен запускаться вручную (из контейнера):

service mysql start

Как автоматически запустить службу MySQL при запуске контейнера Docker?

mtmacdonald
источник
1
нет, для одной простой услуги супервизор не нужен, он усложняет стартовый пользователь
Ларри Кай,
8
Возможно, вы захотите скопировать файл Docker здесь вместо ссылки на файл, который больше не существует
neo112
Докерская статья о supervisord теперь здесь: docs.docker.com/config/containers/multi-service_container Я использовал команду && tail, чтобы заставить мой сервис работать - но мне нужно было добавить "--cap-add SYS_PTRACE" в докер Команда выполнения.
Тед Кэхолл

Ответы:

205

Во- первых, есть проблема в вашем Dockerfile:

RUN service mysql restart && /tmp/setup.sh

Образы Docker не сохраняют запущенные процессы. Следовательно, ваша RUNкоманда выполняется только во время docker buildфазы и останавливается после завершения сборки. Вместо этого вам нужно указать команду при запуске контейнера с помощью команд CMDили, ENTRYPOINTкак показано ниже:

CMD mysql start

Во-вторых, контейнеру Docker необходим процесс (последняя команда) для продолжения работы, иначе контейнер выйдет / остановится. Следовательно, обычную service mysql startкоманду нельзя использовать непосредственно в Dockerfile.

Решение

Существует три типичных способа поддержания процесса в рабочем состоянии:

  • Использование serviceкоманды и добавить не конец команды после этого, какtail -F

    CMD service mysql start && tail -F /var/log/mysql/error.log
    

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

  • Или используйте команду переднего плана, чтобы сделать это

    CMD /usr/bin/mysqld_safe
    

Это работает, только если есть сценарий, как mysqld_safe.

  • Или оберните ваши сценарии start.shи положите в конец

    CMD /start.sh
    

Это лучше всего, если команда должна выполнить серию шагов, опять же, /start.shдолжна продолжаться.

Заметка

Для начинающих использовать supervisordне рекомендуется. Честно говоря, это излишне. Гораздо лучше использовать одну команду service / single для контейнера.

Кстати: пожалуйста, проверьте https://registry.hub.docker.com для существующих изображений MySQL Docker для справки

Ларри Кай
источник
Как бы вы перезапустили службу после запуска в контейнере Docker?
К - Токсичность в СО растет.
3
@KarlMorrisondocker exec -it <CONTAINER NAME> mysql /etc/init.d/mysqld restart
кайзер
1
Я бы не рекомендовал хвостить журнал ошибок MySQL, чтобы определить, работает база данных или нет. В большинстве установок mysqld сервер будет восстанавливаться после ошибок soe, и в процессе этого журнал ошибок будет закрыт, а затем снова открыт. Я также не уверен, что ваш хвост-F сработает для вас во всех или даже в некоторых случаях.
Брайан Акер
Я не уверен, почему, но первый вариант решения прекрасно работает для служебного сценария. Когда вы не используете tail, он потерпит неудачу, даже если служба запущена (по крайней мере, для службы tomcat7). С хвостом работает. В обоих случаях вам нужно использовать переключатель cap_add (- cap-add SYS_PTRACE для запуска) как минимум с SYS_PTRACE
zhrist
1
нет, см. больше в stackoverflow.com/questions/46800594/…
Ларри Кай
73

В вашем Dockerfile, добавьте в последней строке

ENTRYPOINT service ssh restart && bash

Меня устраивает

И вот результат:

root@ubuntu:/home/vagrant/docker/add# docker run -i -t ubuntu
 * Restarting OpenBSD Secure Shell server sshd   [ OK ]                                                                      
root@dccc354e422e:~# service ssh status
 * sshd is running
Цзя
источник
2
это хорошо, но я думаю, что вы не можете иметь отдельный контейнер таким образом.
mdob
1
Это отлично сработало для меня. У меня были проблемы с автоматическим запуском Nginx 1.8. Может оказаться полезным добавить следующее: RUN echo "daemon off;" >> /etc/nginx/nginx.conf RUN ln -sf / dev / stdout /var/log/nginx/access.log RUN ln -sf / dev / stderr /var/log/nginx/error.log
Лионель Моррисон,
1
Есть ли недостатки этого решения?
srph
2
Запуск Bash, наконец, плохая идея, когда вы хотите аккуратно остановить свои службы, потому что таким образом не может быть остановлен docker contaienr docker stopили docker restartпросто изящно, просто его можно убить.
Мохаммед Нурельдин
Я работал над упаковщиком для создания образов докера, и это, кажется, исправило мою проблему с conaitner в файле упаковщика. "changes": ["Служба ENTRYPOINT запуска nginx && / bin / bash"]
karthik101
8

Просто! Добавьте в конце dockerfile:

ENTRYPOINT service mysql start && /bin/bash
Тьяго
источник
Это лучший ответ, который решает мою текущую проблему с Docker-контейнером: Docker version 18.09.7, build 2d0083dбез && /bin/bashслужбы немедленно остановится
Long
7

Есть еще один способ сделать это, который я всегда считал более читабельным.

Скажем, что вы хотите запустить rabbitmq и mongodb, когда вы запустите его, тогда ваш CMDбудет выглядеть примерно так:

CMD /etc/init.d/rabbitmq-server start && \
    /etc/init.d/mongod start

Так как вы можете иметь только один CMDза Dockerfileхитрость заключается в том, чтобы объединить все инструкции с , &&а затем использовать \для каждой команды , чтобы начать новую строку.

Если вы добавите ко многим из них, я предлагаю вам поместить все свои команды в файл сценария и запустить его так, как предложил @ larry-cai:

CMD /start.sh
Франческо Касула
источник
3

В моем случае у меня есть веб-приложение PHP, обслуживаемое Apache2 в контейнере Docker, который подключается к базе данных MYSQL. Решение Ларри Кая работало с небольшими изменениями. Я создал entrypoint.shфайл, в котором я управляю своими услугами. Я думаю, что создание entrypoint.shкогда у вас есть несколько команд для запуска при запуске вашего контейнера, это более чистый способ загрузки Docker.

#!/bin/sh

set -e

echo "Starting the mysql daemon"
service mysql start

echo "navigating to volume /var/www"
cd /var/www
echo "Creating soft link"
ln -s /opt/mysite mysite

a2enmod headers
service apache2 restart

a2ensite mysite.conf
a2dissite 000-default.conf
service apache2 reload

if [ -z "$1" ]
then
    exec "/usr/sbin/apache2 -D -foreground"
else
    exec "$1"
fi
Мистер думсбастер
источник
Просто положите его рядом с вашим Dockerfile. Затем в вашем Dockerfile должна быть инструкция, которая копирует этот файл в нужное место. Затем вы указываете ENTRYPOINT ['your location']инструкцию на файл сценария. Не забудьте установить права на выполнение в вашем скрипте. COPY entrypoint.sh /entrypoint.sh RUN chmod 755 /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"], В этом примере я скопировал свою точку входа в корневой каталог в контейнере Docker.
Мистер Doomsbuster
где находится Dockerfile?
Виктор Жорас
3

У меня та же проблема, когда я хочу автоматически запустить службу SSH. Я нашел это приложение

/etc/init.d/ssh start
в
~ / .Bashrc
может решить, но только вы откроете его с помощью bash.

Weiping.Chen
источник
1

Я добавляю следующий код в /root/.bashrc для запуска кода только один раз,

Пожалуйста, передайте этот контейнер изображению перед запуском этого скрипта, в противном случае файл 'docker_services' будет создан в изображениях, и служба не будет запущена.

if [ ! -e /var/run/docker_services ]; then
    echo "Starting services"
    service mysql start
    service ssh start
    service nginx start
    touch /var/run/docker_services
fi
user136685
источник
1

Вот как я автоматически запускаю службу MySQL всякий раз, когда запускается контейнер Docker.

В моем случае мне нужно запустить не только MySQL, но и PHP, Nginx и Memcached

У меня есть следующие строки в Dockerfile

RUN echo "daemon off;" >> /etc/nginx/nginx.conf
EXPOSE 80
EXPOSE 3306
CMD service mysql start && service php-fpm start && nginx -g 'daemon off;' && service memcached start && bash

Добавление && bash позволит поддерживать работу Nginx, MySQL, PHP и Memcached внутри контейнера.

Крис
источник
1

Это не работает CMD service mysql start && /bin/bash

Это не работает CMD service mysql start ; /bin/bash ;

- Я думаю, интерактивный режим не будет поддерживать передний план.

Это работает !! CMD service nginx start ; while true ; do sleep 100; done;

Это работает !! CMD service nginx start && tail -F /var/log/nginx/access.log

будьте осторожны, вы должны использовать docker run -p 80:80 nginx_bashбез параметра команды.

user3073309
источник
0

Следующая документация с веб-сайта Docker показывает, как реализовать службу SSH в контейнере Docker. Он должен быть легко адаптируем для вашего обслуживания:

Вариация по этому вопросу также была задана здесь:

Zammalad
источник
Инструмент nsenter - это еще один подход для входа в контейнер без установки сервера SSH: github.com/jpetazzo/nsenter . Но этот подход требует доступа к вашему хосту Docker (обычно достаточно доступа по SSH).
Фабьен Балагеас
Ссылка docs.docker.com/sorry/#/examples/running_ssh_service не работает. Можете ли вы обновить его?
Анкур
0
docker export -o <nameOfContainer>.tar <nameOfContainer>

Возможно, нужно удалить существующий контейнер, используя docker prune ...

Импорт с необходимыми изменениями:

cat <nameOfContainer>.tar | docker import -c "ENTRYPOINT service mysql start && /bin/bash" - <nameOfContainer>

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

docker run -d -t -i --restart always --name <nameOfContainer> <nameOfContainer> /bin/bash

Примечание: на мой взгляд, разумно запускать только сервис cron, оставляя контейнер максимально чистым, а затем просто изменить crontab или cron.hourly, .daily и т. Д. ... с соответствующими сценариями проверки / мониторинга. Причина в том, что вы полагаетесь только на одного демона, и в случае изменений с ansible или puppet легче перераспределить скрипты cron вместо отслеживания сервисов, которые запускаются при загрузке.

Даниил
источник