Запустіть службу автоматично в контейнері докерів

Я створюю просте зображення: той, який тримає Riak (база даних NoSQL). Зображення запускає службу Riak за допомогою команди riak start як CMD. Тепер, якщо я запускаю його як демон з docker run -d quintenk/riak-dev , він починає процес Riak (я бачу це в журналах). Однак він автоматично закривається через кілька секунд. Якщо я запускаю його, використовуючи команду docker run -i -t quintenk/riak-dev/bin/bash , процес riak не запускається (UPDATE: див. Відповіді на це пояснення). По суті, жоден з послуг не працює взагалі. Я можу почати його вручну за допомогою термінала, але я хотів би, щоб Riak запускався автоматично. Я вважаю, що така поведінка могла б статися і для інших служб, а Riak - це лише приклад.

Таким чином, запуск/перезапуск контейнера повинен автоматично запускати Riak. Який правильний підхід до встановлення цього?


Для довідки, це Dockerfile, з яким зображення може бути створене (UPDATE: змінено, використовуючи обрану відповідь):

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

34
До речі. Я зараз (для цілей розвитку) використовую контейнер, запустивши його, приєднавши до нього, а потім запустив командний рядок Riak.
додано Автор qkrijger, джерело

6 Відповіді

Щоб утримувати докер-контейнери, потрібно активувати процес на передньому плані.

Таким чином, ви, ймовірно, зможете замінити цей останній рядок у вашому файлі Dockerfile з

CMD /bin/riak console

Або навіть

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

Зауважте, що ви не можете мати декілька рядків операторів CMD, лише останній запускається.

41
додано
Я зараз використовую другий варіант. Спасибі за ваш відгук!
додано Автор qkrijger, джерело

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

Кращим рішенням є використання керівника . Погляньте на це підручник про роботу Riak в контейнері Докер.

31
додано
Це виглядає багатообіцяючим. Якщо у вас вже є досвід використання цього в поєднанні з докерівкою, чи ви хотіли б поділитися коротким прикладом тут?
додано Автор qkrijger, джерело

Пояснення до:

Якщо я запускаю його, використовуючи команду docker run -i -t quintenk/riak-dev/bin/bash , процес riak не запускається

є наступним. Використання CMD в Dockerfile - це насправді та сама функція, як і запуск контейнера за допомогою команди docker run {image} {command} . Як відзначив Гігабла, використовується лише останній CMD, тому в цьому випадку перезаписаний файл Dockerfile перезаписується.

By using CMD /bin/riak start && tail -f /var/log/riak/erlang.log.1 in the Buildfile, you can start the container as a background process using docker run -d {image}, which works like a charm.

4
додано
Аналогічним чином, я намагаюсь докерувати CDH. У такому випадку я запускаю службу за допомогою команди RUN. Починається і виходить після команди RUN. Що може бути причиною?
додано Автор Gops AB, джерело
@GopsAB, ймовірно, існує якась помилка, яка перешкоджає запуску основного процесу (keep). Перевірте свої журнали або спробуйте свій CMD вручну, запустивши контейнер з/bin/bash і подивіться, що станеться
додано Автор qkrijger, джерело
Якщо процес аварійно завершений, tailf продовжує працювати. Одна історія, як @damick
додано Автор Mincă Daniel Andrei, джерело

"Якщо я запускаю його за допомогою докер-запуску -i -t quintenk/riak-dev/bin/bash, процес riak не запускається"

Схоже, ви хочете, щоб ви мали змогу стежити за журналом при приєднанні до контейнера. Мій корисний випадок трохи відрізняється тим, що я хочу, щоб команди запускалися автоматично, але я хочу, щоб він міг приєднуватися до контейнера і знаходитися в оболонці bash. Я зміг вирішити обидві наші проблеми таким чином:

У зображенні/контейнері додайте команди, які ви хочете автоматично запустити до кінця файлу /etc/bash.bashrc .

In your case just add the line /bin/riak start && tail -F /var/log/riak/erlang.log.1, or put /bin/riak start and tail -F /var/log/riak/erlang.log.1 on separate lines depending on the functionality desired.

Тепер внесіть ваші зміни в свій контейнер і запустіть його знову за допомогою команди docker -i -t quintenk/riak-dev/bin/bash . Ви побачите, що команди, які ви встановили в bashrc, вже запущені, як ви прикріпляєте.

4
додано
Це насправді дуже хороше рішення :) Зауважте, що 0,6.5 додав, що параметр docker run -a для сумісності контролерів. Можливо, ви захочете, щоб це вийшло також.
додано Автор qkrijger, джерело
Не гарне рішення. Що ви будете робити, якщо процес завершиться, tailf буде продовжувати працювати, контейнер не виходить.
додано Автор Mincă Daniel Andrei, джерело
Іншим варіантом буде використання dumb-init , системи init для контейнерів, як зазначено тут engineeringblog.yelp.com/2016/01/ …
додано Автор Mincă Daniel Andrei, джерело
@ MincăDanielAndrei Ви маєте частину права. Це не готове рішення до виробництва, це не є стійким з тієї причини, про яку ви згадуєте. Найкраще, якщо взагалі можливо, що entrypoint або cmd вашого зображення буде процес, який ви хочете запустити самі. Часто це означає, що вам потрібно знайти параметр - no-daemon для зазначеного процесу, щоб контейнер не виходив із самого фону входу та виходив, а також зробив його протоколом stderr/stdout.
додано Автор damick, джерело

Оскільки я хочу чистий спосіб вийти з процесу пізніше, я виконую останню команду на виклик read оболонки, що призводить до блокування цього процесу, доки я не приєднаюсь до нього , і удар вхід

[email protected]:~/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

[email protected]:~/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

[email protected]:~/docker$ sudo docker attach 35f253bdf45a

[email protected]:~/docker$ sudo docker ps                                                                                                                                     
ID                  IMAGE               COMMAND             CREATED             STATUS              PORTS

як ви можете бачити контейнер виходить після того, як ви приєднаєте до нього і розблокувати читання. Звичайно, ви можете скористатися більш складним сценарієм, ніж read-p , якщо вам потрібно зробити іншу очистку, наприклад, зупинити послуги та зберігати журнали тощо.

3
додано

Я використовую простий трюк кожного разу, коли починаю будувати новий докер-контейнер. Щоб зберегти його живим, я використовую пінг у сценарії вхідного поля.

Отже, в 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 , оскільки я завжди використовую запускний файл.

0
додано