Jak automatycznie uruchomić usługę podczas uruchamiania kontenera Dockera?

157

Mam plik Dockerfile do zainstalowania serwera MySQL w kontenerze, który następnie zaczynam w ten sposób:

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

Ale usługa MySQL nie uruchamia się automatycznie, muszę ręcznie uruchomić (z poziomu kontenera):

service mysql start

Jak automatycznie uruchomić usługę MySQL po uruchomieniu kontenera Dockera?

mtmacdonald
źródło
1
nie, do jednej prostej usługi nadzorca nie jest potrzebny, to komplikuje początkującego użytkownika
Larry Cai
8
możesz skopiować plik dockerfile tutaj zamiast tworzyć link do pliku, który już nie istnieje
neo112 Kwietnia
Artykuł dockera na temat supervisord jest teraz tutaj: docs.docker.com/config/containers/multi-service_container Użyłem polecenia && tail, aby uruchomić moją usługę - ale musiałem dodać „--cap-add SYS_PTRACE” do dockera Uruchom polecenie.
Ted Cahall,

Odpowiedzi:

205

Po pierwsze, występuje problem w Twoim Dockerfile:

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

Obrazy platformy Docker nie zapisują uruchomionych procesów. Dlatego twoje RUNpolecenie jest wykonywane tylko w docker buildfazie i zatrzymuje się po zakończeniu kompilacji. Zamiast tego musisz określić polecenie podczas uruchamiania kontenera za pomocą poleceń CMDlub ENTRYPOINT, takich jak poniżej:

CMD mysql start

Po drugie, kontener docker wymaga procesu (ostatniego polecenia), aby kontynuować działanie, w przeciwnym razie kontener zostanie zamknięty / zatrzymany. Dlatego zwykłego service mysql startpolecenia nie można używać bezpośrednio w pliku Dockerfile.

Rozwiązanie

Istnieją trzy typowe sposoby utrzymania procesu:

  • Używanie servicepolecenia i dołączanie polecenia non-end po tym, jaktail -F

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

Jest to często preferowane, gdy masz uruchomioną jedną usługę, ponieważ umożliwia ona dostęp do dziennika wyjściowego dla platformy Docker.

  • Lub użyj polecenia pierwszego planu, aby to zrobić

    CMD /usr/bin/mysqld_safe
    

Działa to tylko wtedy, gdy istnieje skrypt, taki jak mysqld_safe.

  • Lub zapakuj swoje skrypty start.shi zakończ to

    CMD /start.sh
    

Najlepiej, jeśli polecenie musi wykonać serię kroków, ponownie /start.sh powinno pozostać uruchomione.

Uwaga

Dla początkujących supervisord nie zaleca się stosowania. Szczerze mówiąc, to przesada. Znacznie lepiej jest użyć pojedynczej usługi / pojedynczego polecenia dla kontenera.

BTW: sprawdź https://registry.hub.docker.com pod kątem istniejących obrazów dockera mysql w celach informacyjnych

Larry Cai
źródło
Jak zrestartowałbyś usługę po uruchomieniu w kontenerze Dockera?
K - Toksyczność SO rośnie.
3
@KarlMorrisondocker exec -it <CONTAINER NAME> mysql /etc/init.d/mysqld restart
kaiser
1
Nie polecałbym dostosowywania dziennika błędów MySQL w celu określenia, czy baza danych działa, czy nie. W większości konfiguracji mysqld serwer będzie działał poprawnie po błędach soe, a podczas wykonywania tej czynności dziennik błędów zostanie zamknięty, a następnie ponownie otwarty. Nie jestem również pewien, czy twój ogon -F zadziała we wszystkich, a nawet w niektórych przypadkach.
Brian Aker
Nie jestem pewien dlaczego, ale pierwsza opcja rozwiązania działa dobrze w przypadku skryptu serwisowego. Jeśli nie używasz taila, to się nie powiedzie, mimo że usługa jest uruchomiona (przynajmniej dla usługi tomcat7). Z ogonem to działa. W obu przypadkach musisz użyć przełącznika cap_add (- cap-add SYS_PTRACE do uruchomienia) z co najmniej SYS_PTRACE
zhrist
1
nie, zobacz więcej na stackoverflow.com/questions/46800594/…
Larry Cai
73

W swoim Dockerfiledodaj w ostatnim wierszu

ENTRYPOINT service ssh restart && bash

Mi to pasuje

A oto wynik:

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
Jia
źródło
2
to jest miłe, ale myślę, że w ten sposób nie można mieć odłączonego pojemnika.
mdob
1
To działało świetnie dla mnie. Miałem problem z automatycznym uruchomieniem Nginx 1.8. Pomocne może się okazać dodanie następujących informacji: 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
Lionel Morrison
1
Czy są jakieś wady tego rozwiązania?
srph
2
Uruchamianie Bash w końcu jest złym pomysłem, gdy chcesz z wdziękiem zatrzymać swoje usługi, ponieważ w ten sposób kontener dockera nie może zostać zatrzymany docker stopani docker restartwdzięczny, po prostu można go zabić.
Mohammed Noureldin
Pracowałem nad pakerem, aby utworzyć obrazy dockera i wydaje się, że rozwiązuje to mój problem z conaitnerem w pliku pakera. "changes": ["Usługa ENTRYPOINT nginx start && / bin / bash"]
karthik101
8

Prosty! Dodaj na końcu pliku dockerfile:

ENTRYPOINT service mysql start && /bin/bash
Thiago
źródło
To najlepsza odpowiedź, która rozwiązuje mój obecny problem z kontenerem Docker: Docker version 18.09.7, build 2d0083dbez && /bin/bashusługi zostanie natychmiast zatrzymana
Długo
7

Jest na to inny sposób, który zawsze uważałem za bardziej czytelny.

Powiedz, że chcesz uruchomić rabbitmq i mongodb po uruchomieniu, wtedy CMDwyglądałoby to mniej więcej tak:

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

Ponieważ możesz mieć tylko jedną CMDna każdą Dockerfilesztuczkę, musisz połączyć wszystkie instrukcje z, &&a następnie użyć\ dla każdego polecenia, aby rozpocząć nowy wiersz.

Jeśli w końcu dodasz do wielu z nich, sugeruję umieszczenie wszystkich poleceń w pliku skryptu i uruchomienie go tak, jak sugerował @ larry-cai:

CMD /start.sh
Francesco Casula
źródło
3

W moim przypadku mam aplikację internetową PHP obsługiwaną przez Apache2 w kontenerze docker, który łączy się z bazą danych MYSQL. Rozwiązanie Larry Cai działało z niewielkimi modyfikacjami. Utworzyłem entrypoint.shplik, w którym zarządzam swoimi usługami. Myślę, że utworzenie polecenia, entrypoint.shgdy masz więcej niż jedno polecenie do wykonania podczas uruchamiania kontenera, jest czystszym sposobem na załadowanie dockera.

#!/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
Panie Doomsbuster
źródło
Po prostu umieść go obok swojego pliku Dockerfile. Następnie w pliku Dockerfile powinna znajdować się instrukcja kopiująca ten plik do wybranej lokalizacji. Następnie kierujesz ENTRYPOINT ['your location']instrukcję do pliku skryptu. Pamiętaj jednak, aby ustawić uprawnienia do wykonywania skryptu. COPY entrypoint.sh /entrypoint.sh RUN chmod 755 /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]. W tym przykładzie skopiowałem mój punkt wejścia do katalogu głównego w kontenerze Dockera.
Mr. Doomsbuster
gdzie jest Dockerfile?
Viktor Joras
3

Mam ten sam problem, gdy chcę automatycznie uruchomić usługę ssh. Znalazłem ten dodatek

/etc/init.d/ssh start
do
~ / .bashrc
możesz go rozwiązać, ale tylko Ty otworzysz go za pomocą basha.

Weiping.Chen
źródło
1

Dodaję następujący kod do /root/.bashrc, aby uruchomić kod tylko raz,

Zatwierdź kontener do obrazu przed uruchomieniem tego skryptu, w przeciwnym razie w obrazach zostanie utworzony plik „docker_services” i żadna usługa nie zostanie uruchomiona.

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
źródło
1

Oto jak automatycznie uruchamiam usługę MySQL po uruchomieniu kontenera docker.

W moim przypadku muszę uruchomić nie tylko MySQL, ale także PHP, Nginx i Memcached

Mam następujące wiersze w pliku 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

Dodanie && bash sprawiłoby, że Nginx, MySQL, PHP i Memcached działałyby w kontenerze.

Chris
źródło
1

To nie działa CMD service mysql start && /bin/bash

To nie działa CMD service mysql start ; /bin/bash ;

- Domyślam się, że tryb interaktywny nie obsługuje pierwszego planu.

To działa !! CMD service nginx start ; while true ; do sleep 100; done;

To działa !! CMD service nginx start && tail -F /var/log/nginx/access.log

uważaj, powinieneś używać docker run -p 80:80 nginx_bashbez parametru polecenia.

user3073309
źródło
0

Poniższa dokumentacja z witryny sieci Web platformy Docker pokazuje, jak zaimplementować usługę SSH w kontenerze platformy Docker. Powinien być łatwy do dostosowania do Twojej usługi:

Zadano tu również odmianę tego pytania:

Zammalad
źródło
Narzędzie nsenter to kolejne podejście do wejścia do kontenera, bez konieczności instalacji serwera SSH: github.com/jpetazzo/nsenter . Ale to podejście wymaga dostępu do twojego hosta Docker (zwykle wystarczy dostęp SSH).
Fabien Balageas
Link docs.docker.com/sorry/#/examples/running_ssh_service nie działa. Czy możesz to zaktualizować?
Ankur
0
docker export -o <nameOfContainer>.tar <nameOfContainer>

Może być konieczne przycięcie istniejącego kontenera za pomocą narzędzia docker prune ...

Import z wymaganymi modyfikacjami:

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

Uruchom kontener, na przykład z opcją Zawsze restartuj, aby upewnić się, że zostanie automatycznie wznowiony po ponownym uruchomieniu hosta / demona:

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

Uwaga boczna: Moim zdaniem rozsądne jest uruchamianie tylko usługi cron, pozostawiając kontener tak czysty, jak to tylko możliwe, a następnie po prostu zmodyfikuj crontab lub cron.hourly, .daily itd ... za pomocą odpowiednich skryptów sprawdzania / monitorowania. Powodem jest to, że polegasz tylko na jednym demonie, aw przypadku zmian łatwiej jest redystrybuować skrypty crona z ansible lub puppet zamiast śledzić usługi uruchamiane podczas rozruchu.

Daniel
źródło