Come avviare automaticamente un servizio quando si esegue un contenitore finestra mobile?


157

Ho un Dockerfile per installare il server MySQL in un contenitore, che quindi inizio in questo modo:

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

Ma il servizio MySQL non si avvia automaticamente, devo eseguirlo manualmente (dall'interno del contenitore):

service mysql start

Come posso avviare automaticamente il servizio MySQL quando eseguo il contenitore docker?


1
no, per un semplice servizio, il supervisore non è necessario, rende complicato per l'utente iniziale
Larry Cai

8
potresti voler copiare il file docker qui invece di collegarti a un file che non esiste più
neo112,

L'articolo docker su supervisord è ora qui: docs.docker.com/config/containers/multi-service_container Ho usato il comando && tail per far funzionare il mio servizio - ma dovevo aggiungere "--cap-add SYS_PTRACE" alla docker esegui comando.
Ted Cahall,

Risposte:


205

Innanzitutto, c'è un problema nel tuo Dockerfile:

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

Le immagini Docker non salvano i processi in esecuzione. Pertanto, il RUNcomando viene eseguito solo durante la docker buildfase e si interrompe al termine della compilazione. Invece, è necessario specificare il comando all'avvio del contenitore usando i comandi CMDo ENTRYPOINTcome di seguito:

CMD mysql start

In secondo luogo, il contenitore docker necessita di un processo (ultimo comando) per continuare a funzionare, altrimenti il ​​contenitore verrà chiuso / arrestato. Pertanto, il normaleservice mysql start comando non può essere utilizzato direttamente nel Dockerfile.

Soluzione

Esistono tre modi tipici per mantenere il processo in esecuzione:

  • Usando il servicecomando e aggiungi il comando non-end dopo tale liketail -F

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

Questo è spesso preferito quando si dispone di un singolo servizio in esecuzione in quanto rende il registro in uscita accessibile alla finestra mobile.

  • Oppure usa il comando foreground per farlo

    CMD /usr/bin/mysqld_safe
    

Funziona solo se esiste uno script simile mysqld_safe.

  • O avvolgi i tuoi script start.she mettili alla fine

    CMD /start.sh
    

Questo è meglio se il comando deve eseguire una serie di passaggi, di nuovo, /start.sh dovrebbe rimanere in esecuzione.

Nota

Per i principianti che usano supervisord non è raccomandato. Onestamente, è eccessivo. È molto meglio usare il singolo servizio / comando singolo per il contenitore.

A proposito: consultare https://registry.hub.docker.com per le immagini docker mysql esistenti come riferimento


Come riavvieresti il ​​servizio una volta avviato nel contenitore della finestra mobile?
K - La tossicità in SO sta crescendo.

3
@KarlMorrisondocker exec -it <CONTAINER NAME> mysql /etc/init.d/mysqld restart
kaiser

1
Non consiglierei di personalizzare il registro degli errori di MySQL per determinare se il database è in esecuzione o meno. Nella maggior parte delle configurazioni mysqld, il server si riprenderà da errori soe e nel processo in tal modo il registro degli errori verrà chiuso e quindi riaperto. Non sono sicuro che la tua coda -F funzionerà per te in tutti o anche in alcuni casi.
Brian Aker,

Non sono sicuro del perché, ma la prima opzione di soluzione funziona bene per lo script di servizio. Quando non si usa tail, fallirà, anche se il servizio è avviato (almeno per il servizio tomcat7). Con la coda funziona. Per entrambi i casi devi usare switch cap_add (- cap-aggiungi SYS_PTRACE per l'esecuzione) con almeno SYS_PTRACE
zhrist,


73

Nel tuo Dockerfile, aggiungi all'ultima riga

ENTRYPOINT service ssh restart && bash

Per me funziona

E questo è il risultato:

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
è carino ma penso che non si possa avere un container staccato in questo modo.
mdob,

1
Questo ha funzionato alla grande per me. Ho avuto problemi con l'avvio automatico di Nginx 1.8. Potresti trovare utile l'aggiunta di: 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
Ci sono degli svantaggi in questa soluzione?
srph

2
L'avvio di Bash alla fine è una cattiva idea quando si desidera interrompere i propri servizi con garbo, perché in questo modo la finestra mobile non può essere fermata docker stopo docker restartaggraziata, solo può essere uccisa.
Mohammed Noureldin,

Stavo lavorando su packer per creare immagini docker e questo sembra risolvere il mio problema con il conaitner nel file packer. "changes": ["ENTRYPOINT service nginx start && / bin / bash"]
karthik101

8

Semplice! Aggiungi alla fine del file docker:

ENTRYPOINT service mysql start && /bin/bash

Questa è la migliore risposta che risolve il mio attuale problema Docker Contenitore: Docker version 18.09.7, build 2d0083dsenza && /bin/bashil servizio si fermerà immediatamente
Lunga

7

C'è un altro modo per farlo che ho sempre trovato più leggibile.

Dì che vuoi avviare rabbitmq e mongodb quando lo esegui, CMDsembreresti qualcosa del genere:

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

Dal momento che puoi avere solo uno CMDper Dockerfileil trucco è concatenare tutte le istruzioni &&e quindi utilizzare\ per ogni comando per iniziare una nuova riga.

Se finisci per aggiungere a molti di quelli ti suggerisco di mettere tutti i tuoi comandi in un file di script e avviarlo come suggerito da @ larry-cai:

CMD /start.sh

3

Nel mio caso, ho un'applicazione web PHP fornita da Apache2 all'interno del contenitore docker che si collega a un database back-end MYSQL. La soluzione di Larry Cai ha funzionato con lievi modifiche. Ho creato un entrypoint.shfile all'interno del quale gestisco i miei servizi. Penso che creare un entrypoint.shquando hai più di un comando da eseguire all'avvio del container sia un modo più pulito per la finestra mobile bootstrap.

#!/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

Mettilo accanto al tuo Dockerfile. Quindi nel Dockerfile dovresti avere un'istruzione che copia questo file nella posizione desiderata. Quindi si punta l' ENTRYPOINT ['your location']istruzione al file di script. Ricorda di impostare le autorizzazioni di esecuzione sullo script. COPY entrypoint.sh /entrypoint.sh RUN chmod 755 /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]. In questo esempio, ho copiato il mio punto di ingresso nella directory principale nel contenitore della finestra mobile.
Mr. Doomsbuster,

dov'è Dockerfile?
Viktor Joras,

3

Ho lo stesso problema quando voglio avviare automaticamente il servizio ssh. Ho trovato quell'appendice

/etc/init.d/ssh start
per
~ / .Bashrc
puoi risolverlo, ma solo tu lo apri con bash lo farà.


1

Aggiungo il seguente codice a /root/.bashrc per eseguire il codice una sola volta,

Commettere il contenitore sull'immagine prima di eseguire questo script, altrimenti il ​​file "docker_services" verrà creato nelle immagini e non verrà eseguito alcun servizio.

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

Ecco come avvio automaticamente il servizio MySQL ogni volta che viene eseguito il contenitore docker.

Nel mio caso, devo eseguire non solo MySQL ma anche PHP, Nginx e Memcached

Ho le seguenti righe in 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

L'aggiunta di && bash manterrebbe Nginx, MySQL, PHP e Memcached in esecuzione all'interno del contenitore.


1

Questo non funziona CMD service mysql start && /bin/bash

Questo non funziona CMD service mysql start ; /bin/bash ;

- Immagino che la modalità interattiva non supporti il ​​primo piano.

Questo funziona !! CMD service nginx start ; while true ; do sleep 100; done;

Questo funziona !! CMD service nginx start && tail -F /var/log/nginx/access.log

attenzione che si dovrebbe usare docker run -p 80:80 nginx_bashsenza parametro di comando.


0

La seguente documentazione dal sito Web Docker mostra come implementare un servizio SSH in un contenitore docker. Dovrebbe essere facilmente adattabile per il tuo servizio:

Una variazione su questa domanda è stata anche posta qui:


Lo strumento nsenter è un altro approccio per entrare in un contenitore, senza richiedere l'installazione del server SSH: github.com/jpetazzo/nsenter . Ma questo approccio richiede un accesso all'host Docker (in genere l'accesso SSH è sufficiente).
Fabien Balageas,

Il collegamento docs.docker.com/sorry/#/examples/running_ssh_service non funziona. Puoi aggiornarlo per favore?
Ankur,

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

Potrebbe essere necessario potare il contenitore esistente usando la docker potatura ...

Importa con le modifiche richieste:

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

Esegui il contenitore ad esempio con l'opzione di riavvio sempre per assicurarti che riprenda automaticamente dopo il riciclo di host / daemon:

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

Nota a margine: a mio avviso ragionevole è avviare solo il servizio cron lasciando il contenitore il più pulito possibile, quindi modificare semplicemente crontab o cron.hourly, .daily ecc ... con gli script di controllo / monitoraggio corrispondenti. Il motivo è che fai affidamento solo su un demone e in caso di modifiche è più facile con ansible o burattino ridistribuire gli script cron invece di tenere traccia dei servizi che iniziano all'avvio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.