Je crée une image simple: celle qui contient Riak (une base de données NoSQL). L'image démarre le service Riak avec riak start
en tant que CMD. À présent, si je l'exécute en tant que démon avec docker run -d quintenk/riak-dev
, le processus Riak démarre (je peux le voir dans les journaux). Cependant, il se ferme automatiquement après quelques secondes. Si je l'exécute en utilisant docker run -i -t quintenk/riak-dev /bin/bash
, le processus riak n'est pas lancé (UPDATE: voir les réponses pour une explication à ce sujet). En fait, aucun service ne fonctionne du tout. Je peux le démarrer manuellement à l'aide du terminal, mais j'aimerais que Riak démarre automatiquement. Je suppose que ce comportement se produirait également pour d'autres services, Riak n'est qu'un exemple.
Ainsi, l'exécution/le redémarrage du conteneur devrait automatiquement démarrer Riak. Quelle est la bonne approche pour mettre cela en place?
Pour référence, voici le fichier Docker avec lequel l'image peut être créée (UPDATE: modifié à l'aide de la réponse choisie):
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 changé en -F dans CMD conformément à sa remarque
Après avoir travaillé avec Docker pendant un certain temps, j’ai pris l’habitude d’utiliser Supervord pour optimiser mes processus. Si vous souhaitez un exemple de code pour cela, consultez https://github.com/Krijger/docker-cookbooks . J'utilise mon image de superviseur comme base pour toutes mes autres images. J'ai blogué sur l'utilisation de superviseur ici .
Pour que les conteneurs Docker continuent de fonctionner, vous devez conserver un processus actif au premier plan.
Donc, vous pourriez probablement remplacer cette dernière ligne dans votre fichier Docker avec
CMD /bin/riak console
Ou même
CMD /bin/riak start && tail -F /var/log/riak/erlang.log.1
Notez que vous ne pouvez pas avoir plusieurs lignes d'instructions CMD, seul le dernier est exécuté.
Utiliser la queue pour garder le conteneur en vie est un hack. Notez également que, avec l'option -f
, le conteneur d'options se termine lorsque la rotation du journal est effectuée (vous pouvez éviter cela en utilisant -F
).
Une meilleure solution consiste à utiliser supervisor . Jetez un coup d'œil à ce tutorial sur l'utilisation de Riak dans un conteneur Docker.
"Si je l'exécute en utilisant le menu fixe -i -t quintenk/riak-dev/bin/bash, le processus riak n'est pas démarré"
Il semble que vous souhaitiez uniquement pouvoir surveiller le journal lorsque vous vous attachez au conteneur. Mon cas d'utilisation est un peu différent en ce sens que je veux que les commandes soient lancées automatiquement, mais je veux pouvoir attacher au conteneur et être dans un shell bash. J'ai pu résoudre nos deux problèmes comme suit:
Dans l'image/conteneur, ajoutez les commandes souhaitées à la fin du fichier /etc/bash.bashrc
.
Dans votre cas, ajoutez simplement la ligne /bin/riak start && tail -F /var/log/riak/erlang.log.1
ou insérez /bin/riak start
et tail -F /var/log/riak/erlang.log.1
sur des lignes distinctes, en fonction de la fonctionnalité souhaitée.
Maintenant, validez vos modifications dans votre conteneur et réexécutez-le avec: docker run -i -t quintenk/riak-dev /bin/bash
. Vous constaterez que les commandes que vous avez insérées dans le bashrc sont déjà en cours d'exécution lorsque vous vous attachez.
L'explication de:
Si je l'exécute en utilisant
docker run -i -t quintenk/riak-dev /bin/bash
, le processus riak n'est pas lancé
est comme suit. L'utilisation de CMD dans le fichier Docker est en réalité la même fonctionnalité que le démarrage du conteneur à l'aide de docker run {image} {command}
. Comme Gigablah l'a fait remarquer, seul le dernier CMD est utilisé, de sorte que celui écrit dans le fichier Docker est remplacé dans ce cas.
En utilisant CMD /bin/riak start && tail -f /var/log/riak/erlang.log.1
dans le fichier de construction, vous pouvez démarrer le conteneur en tant que processus d'arrière-plan en utilisant docker run -d {image}
, qui fonctionne comme un charme.
Parce que je veux un moyen propre de quitter le processus plus tard, je fais de la dernière commande un appel au shell read
qui provoque le blocage de ce processus jusqu'à ce que j'y attache plus tard et appuyez sur Entrée.
arthur@macro:~/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
arthur@macro:~/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
arthur@macro:~/docker$ Sudo docker attach 35f253bdf45a
arthur@macro:~/docker$ Sudo docker ps
ID IMAGE COMMAND CREATED STATUS PORTS
comme vous pouvez voir le conteneur se ferme après que vous y avez attaché et débloqué la lecture. Vous pouvez bien sûr utiliser un script plus sophistiqué que read -p
si vous devez effectuer d'autres opérations de nettoyage, telles que l'arrêt des services et la sauvegarde des journaux, etc.
J'utilise une astuce simple à chaque fois que je commence à construire un nouveau conteneur Docker. Pour le garder en vie, j'utilise un ping dans le script du point d'entrée.
Ainsi, dans Dockerfile, lors de l’utilisation de Debian, par exemple, je m’assure de pouvoir cingler . C’est d'ailleurs, toujours agréable, pour vérifier ce qui est accessible depuis le conteneur.
...
RUN DEBIAN_FRONTEND=noninteractive apt-get update \
&& apt-get install -y iputils-ping
...
ENTRYPOINT ["entrypoint.sh"]
Et dans le fichier entrypoint.sh
#!/bin/bash
...
ping 10.10.0.1 >/dev/null 2>/dev/null
J'utilise ceci au lieu de CMD bash
, car je finis toujours par utiliser un fichier de démarrage.