Як автоматично запустити послугу під час запуску контейнера докера?


157

У мене є Dockerfile для встановлення MySQL-сервера в контейнер, який я починаю так:

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

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

service mysql start

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


1
ні, для однієї простої послуги супервізор не потрібен, це ускладнює початкового користувача
Ларрі Кай

8
ви можете скопіювати сюди dockerfile замість посилання на файл, який більше не існує
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

По-друге, контейнеру докер потрібен процес (остання команда), щоб продовжувати працювати, інакше контейнер вийде / зупиниться. Тому звичайну 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не рекомендується. Чесно кажучи, це надмірно. Набагато краще використовувати одну службу / одну команду для контейнера.

BTW: перевірте https://registry.hub.docker.com щодо наявних зображень докера mysql для ознайомлення


Як би ви перезапустили службу після запуску в контейнері докера?
K - Токсичність в SO зростає.

3
@KarlMorrisondocker exec -it <CONTAINER NAME> mysql /etc/init.d/mysqld restart
кайзер

1
Я б не рекомендував журнал помилок MySQL, щоб визначити, працює чи ні база даних. У більшості налаштувань mysqld сервер відновиться після помилок Soe, і в процесі цього журнал помилок буде закритий, а потім знову відкритий. Я також не впевнений, що ваш хвіст -F підійде для вас у всіх або навіть деяких випадках.
Брайан Акер

Я не впевнений, чому, але перший варіант рішення прекрасно працює для сервісного сценарію. Якщо ви не використовуєте хвіст, він вийде з ладу, навіть незважаючи на те, що служба запускається (принаймні, для служби tomcat7). З хвостом це працює. В обох випадках вам потрібно використовувати перемикач cap_add (- cap-додати SYS_PTRACE для запуску) принаймні SYS_PTRACE
zhrist

1
ні, більше дивіться у stackoverflow.com/questions/46800594/…
Larry Cai

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 "демон демон;" >> /etc/nginx/nginx.conf RUN ln -sf / dev / stdout /var/log/nginx/access.log RUN ln -sf / dev / stderr /var/log/nginx/error.log
Lionel Morrison

1
Чи є недоліки цього рішення?
srph

2
Запустити Bash нарешті - це погана ідея, коли ви хочете граціозно зупинити свої послуги, оскільки таким чином докер-контактор не може бути зупинений docker stopабо docker restartвитончено, просто його можна вбити.
Мохаммед Нурелдін

Я працював над пакувальником, щоб створити зображення докера, і це, здається, вирішило мою проблему з конайтнером у файлі пакета. "changes": ["ENTRYPOINT service nginx start && / bin / bash"]
karthik101

8

Просто! Додати в кінці dockerfile:

ENTRYPOINT service mysql start && /bin/bash

Це найкраща відповідь, яка вирішує мою актуальну проблему з контейнером Docker: Docker version 18.09.7, build 2d0083dбез && /bin/bashсервісу негайно зупиниться
Довгий

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коли у вас є кілька команд, які потрібно виконати, коли ваш контейнер запускається, - це більш чистий спосіб завантажувати докер.

#!/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"]. У цьому прикладі я скопіював свою вхідну точку до кореневого каталогу в контейнер докера.
Містер Думсбустер

де Dockerfile?
Віктор Джорас

3

У мене така ж проблема, коли я хочу автоматично запустити службу ssh. Я знайшов це додаток

/etc/init.d/ssh start
до
~ / .bashrc
Ви можете вирішити це, але тільки ви відкриєте його з bash.


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

1

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

У моєму випадку мені потрібно запустити не тільки 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без командного параметра.


0

Наступна документація на веб-сайті Docker показує, як реалізувати службу SSH в контейнері docker. Він повинен легко адаптуватися до вашої послуги:

Варіант цього питання також був заданий тут:


Інструмент nsenter - це ще один підхід для введення в контейнер, не вимагаючи встановлення SSH-сервера: github.com/jpetazzo/nsenter . Але такий підхід вимагає доступу до вашого хокера Docker (зазвичай SSH доступу достатньо).
Фабієн Балагеас

Посилання docs.docker.com/sorry/#/examples/running_ssh_service не працює. Чи можете ви оновити його?
Анкур

0
docker export -o <nameOfContainer>.tar <nameOfContainer>

Можливо, потрібно обрізати існуючий контейнер, використовуючи докер чорнослив ...

Імпорт із необхідними модифікаціями:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.