it-swarm.com.de

Einen Dienst automatisch in einem Docker-Container ausführen

Ich baue ein einfaches Image auf: eines, das Riak (eine NoSQL-Datenbank) enthält. Das Bild startet den Riak-Dienst mit riak start als CMD. Wenn ich es als Daemon mit docker run -d quintenk/riak-dev starte, wird der Riak-Prozess gestartet (ich kann das in den Protokollen sehen). Es schließt sich jedoch automatisch nach einigen Sekunden. Wenn ich es mit docker run -i -t quintenk/riak-dev /bin/bash starte, wird der Riak-Prozess nicht gestartet (UPDATE: eine Antwort finden Sie in den Antworten). Tatsächlich laufen überhaupt keine Dienste. Ich kann es manuell über das Terminal starten, aber ich möchte, dass Riak automatisch startet. Ich denke, dieses Verhalten würde auch für andere Dienste auftreten. Riak ist nur ein Beispiel.

Wenn Sie den Container starten oder neu starten, sollte Riak automatisch gestartet werden. Was ist der richtige Ansatz, um dies einzurichten?


Als Referenz dient hier die Docker-Datei, mit der das Bild erstellt werden kann (UPDATE: mit der gewählten Antwort geändert):

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

BEARBEITEN: -f wurde in CMD entsprechend seiner Bemerkung in -F geändert


MEINE EIGENE ANTWORT

Nachdem ich einige Zeit mit Docker gearbeitet hatte, machte ich es mir zur Gewohnheit, Supervisord zu verwenden, um meine Prozesse zu optimieren. Wenn Sie dafür Beispielcode wünschen, besuchen Sie https://github.com/Krijger/docker-cookbooks . Ich verwende mein Supervisor-Bild als Basis für alle anderen Bilder. Ich habe gebloggt über Supervisor hier .

34
qkrijger

Damit Docker-Container aktiv bleiben, muss ein Prozess im Vordergrund aktiv bleiben.

Sie könnten also wahrscheinlich diese letzte Zeile in Ihrer Dockerfile durch ersetzen

CMD /bin/riak console

Oder auch

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

Beachten Sie, dass Sie nicht mehrere Zeilen mit CMD-Anweisungen haben können, nur die letzte wird ausgeführt.

41
Gigablah

Schwanz zu benutzen, um den Behälter am Leben zu erhalten, ist ein Hack. Beachten Sie außerdem, dass der Container mit der Option -f beendet wird, wenn die Protokollrotation erfolgt (dies kann durch die Verwendung von -F vermieden werden).

Eine bessere Lösung ist die Verwendung von supervisor . In diesem Tutorial erfahren Sie, wie Sie Riak in einem Docker-Container ausführen.

31
sesm

"Wenn ich es mit Docker-Run ausführe -i -t quintenk/riak-dev/bin/bash, wird der Riak-Prozess nicht gestartet."

Es klingt, als ob Sie nur das Protokoll überwachen möchten, wenn Sie an den Container anhängen. Mein Anwendungsfall unterscheidet sich ein wenig dahingehend, dass Befehle automatisch gestartet werden sollen, ich möchte jedoch an den Container anhängen und sich in einer Bash-Shell befinden. Ich konnte beide Probleme wie folgt lösen:

Fügen Sie im Image/Container die Befehle, die automatisch gestartet werden sollen, am Ende der /etc/bash.bashrc-Datei hinzu.

Fügen Sie in Ihrem Fall einfach die Zeile /bin/riak start && tail -F /var/log/riak/erlang.log.1 hinzu oder setzen Sie /bin/riak start und tail -F /var/log/riak/erlang.log.1 in separate Zeilen, je nach gewünschter Funktionalität.

Übernehmen Sie nun Ihre Änderungen in Ihren Container und führen Sie ihn erneut mit dem folgenden Code aus: docker run -i -t quintenk/riak-dev /bin/bash. Sie werden feststellen, dass die Befehle, die Sie in der Bashrc eingeben, bereits beim Anhängen ausgeführt werden.

4
damick

Die Erklärung für: 

Wenn ich es mit docker run -i -t quintenk/riak-dev /bin/bash starte, wird der Riak-Prozess nicht gestartet

ist wie folgt. Die Verwendung von CMD in der Docker-Datei entspricht eigentlich dem Starten des Containers mit docker run {image} {command}. Wie Gigablah bemerkt, wird nur die letzte CMD verwendet, so dass die in der Dockerfile geschriebene in diesem Fall überschrieben wird.

Mit CMD /bin/riak start && tail -f /var/log/riak/erlang.log.1 im Buildfile können Sie den Container als Hintergrundprozess mit docker run -d {image} starten, der wie ein Zauber wirkt.

4
qkrijger

Da der Prozess nach einem sauberen Verfahren später beendet werden soll, rufe ich den letzten Befehl an die Shell an read, wodurch der Prozess blockiert wird, bis ich ihn später anhebe und drücken Sie die Eingabetaste.

[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

wie Sie sehen, wird der Container beendet, nachdem Sie ihn anhängen und den Lesevorgang aufheben. Sie können natürlich ein komplexeres Skript als read -p verwenden, wenn Sie andere Bereinigungen durchführen möchten, z.

3
Arthur Ulfeldt

Ich benutze einen einfachen Trick, wenn ich anfange, einen neuen Docker-Container zu bauen. Um es am Leben zu erhalten, verwende ich einen Ping-Befehl in der Einstiegspunkt-Schrift.

In der Docker-Datei, zum Beispiel bei der Verwendung von Debian, stelle ich sicher, dass ich ping . Dies ist übrigens immer Nizza, um zu prüfen, was aus dem Container heraus erreichbar ist.

...
RUN DEBIAN_FRONTEND=noninteractive apt-get update \
 && apt-get install -y iputils-ping 
...
ENTRYPOINT ["entrypoint.sh"]

Und in der Datei entrypoint.sh

#!/bin/bash
...
ping 10.10.0.1 >/dev/null 2>/dev/null

Ich benutze dies anstelle von CMD bash, da ich immer eine Startup-Datei verwende.

0
Osiris