Kann ich mehrere Programme in einem Docker-Container ausführen?


150

Ich versuche, mich mit Docker zu beschäftigen, um eine Anwendung bereitzustellen, die auf den Benutzern auf dem Desktop ausgeführt werden soll. Meine Anwendung ist einfach eine Flask-Webanwendung und eine Mongo-Datenbank. Normalerweise würde ich beide in einer VM installieren und einen Host-Port an die Gast-Web-App weiterleiten. Ich würde Docker gerne ausprobieren, bin mir aber nicht sicher, wie ich mehr als ein Programm verwenden soll. Die Dokumentation besagt, dass es nur ENTRYPOINT geben kann. Wie kann ich Mongo und meine Kolbenanwendung haben? Oder müssen sie sich in separaten Containern befinden. In diesem Fall, wie sprechen sie miteinander und wie erleichtert dies die Verteilung der App?


2
Spot on: Ich frage mich, warum Docker so beliebt waren. (Einzelprozess.?) - aber mal sehen, was die Antworten uns sagen.
Javadba

Antworten:


120

Es kann nur einen ENTRYPOINT geben, aber dieses Ziel ist normalerweise ein Skript, das so viele Programme startet, wie benötigt werden. Sie können beispielsweise beispielsweise Supervisord oder ähnliches verwenden, um mehrere Dienste in einem einzigen Container zu starten. Dies ist ein Beispiel für einen Docker-Container, in dem MySQL, Apache und WordPress in einem einzigen Container ausgeführt werden .

Angenommen, Sie haben eine Datenbank, die von einer einzelnen Webanwendung verwendet wird. Dann ist es wahrscheinlich einfacher, beide in einem einzigen Container auszuführen.

Wenn Sie eine gemeinsam genutzte Datenbank haben, die von mehr als einer Anwendung verwendet wird, ist es besser, die Datenbank in einem eigenen Container und die Anwendungen jeweils in einem eigenen Container auszuführen.

Es gibt mindestens zwei Möglichkeiten, wie die Anwendungen miteinander kommunizieren können, wenn sie in verschiedenen Containern ausgeführt werden:

  1. Verwenden Sie exponierte IP-Ports und stellen Sie eine Verbindung über diese her.
  2. Aktuelle Docker-Versionen unterstützen das Verknüpfen .

1
Es sieht so aus, als ob neue Versionen von Docker jetzt Docker-Containernetzwerke unterstützen .
Jpierson

Docker unterstützt jetzt das Ausführen von Supervisor, sodass Sie das Verhalten für jeden Prozess wie autorestart = true, stdout_logfile, stderr_logfile usw. festlegen können. Schauen Sie sich docs.docker.com/engine/admin/using_supervisord
Andreas Lundgren

4
Ich würde definitiv nicht empfehlen, in diesem Beispiel zu versuchen, die Webanwendung und Mongodb im selben Container auszuführen. Es gibt gute Anwendungsfälle für Supervisord- oder ähnliche init-ähnliche Prozesse in Docker, aber dieser ist nicht Teil davon. Es ist viel einfacher, Docker-Compose zu verwenden, um die beiden Dienste nur in separaten Containern auszuführen.
Nicolas-van

@ nicolas-van warum ist es einfacher? Liegt es daran, dass ich, wenn die Datenbank stirbt, den Container der Datenbank neu starten kann, anstatt das Ganze neu starten zu müssen?
Brillout

Anwendungen auf demselben Computer können auch über Unix-Domänensockets kommunizieren . Höchste Leistung garantiert.
Skeptical Jule

21

Ich hatte eine ähnliche Anforderung, einen LAMP-Stack, Mongo DB und meine eigenen Dienste auszuführen

Docker ist eine betriebssystembasierte Virtualisierung, weshalb der Container um einen laufenden Prozess herum isoliert wird. Daher ist mindestens ein Prozess erforderlich, der in FOREGROUND ausgeführt wird.

Sie stellen also Ihr eigenes Startskript als Einstiegspunkt bereit, sodass Ihr Startskript zu einem erweiterten Docker-Image-Skript wird, in dem Sie eine beliebige Anzahl von Diensten stapeln können, bis MINDESTENS EIN VORDERER SERVICE gestartet ist, DER AUCH ZUM ENDE STEHT

Meine Docker-Bilddatei enthält also ganz unten zwei Zeilen:

COPY myStartupScript.sh /usr/local/myscripts/myStartupScript.sh
CMD ["/bin/bash", "/usr/local/myscripts/myStartupScript.sh"]

In meinem Skript führe ich alle MySQL, MongoDB, Tomcat usw. aus. Am Ende führe ich meinen Apache als Vordergrund-Thread aus.

source /etc/apache2/envvars
/usr/sbin/apache2 -DFOREGROUND

Auf diese Weise kann ich alle meine Dienste starten und den Container am Leben erhalten, wobei der zuletzt gestartete Dienst im Vordergrund steht

Ich hoffe es hilft

UPDATE : Seit ich diese Frage das letzte Mal beantwortet habe, sind neue Dinge wie Docker Compose aufgetaucht, mit denen Sie jeden Dienst in einem eigenen Container ausführen und dennoch alle als Abhängigkeiten zwischen diesen Diensten zusammenbinden können. Versuchen Sie, mehr über Docker-Compose und zu erfahren Verwenden Sie es, es ist eleganter, es sei denn, Ihr Bedarf passt nicht dazu.


6

Ich bin mit einigen früheren Lösungen, die empfohlen haben, beide Dienste im selben Container auszuführen, nicht einverstanden. In der Dokumentation wird klar angegeben, dass dies nicht empfohlen wird :

Es wird allgemein empfohlen, Problembereiche durch Verwendung eines Dienstes pro Container zu trennen. Dieser Dienst kann sich in mehrere Prozesse aufteilen (z. B. startet der Apache-Webserver mehrere Arbeitsprozesse). Es ist in Ordnung, mehrere Prozesse zu haben, aber um den größtmöglichen Nutzen aus Docker zu ziehen, vermeiden Sie, dass ein Container für mehrere Aspekte Ihrer gesamten Anwendung verantwortlich ist. Sie können mehrere Container über benutzerdefinierte Netzwerke und freigegebene Volumes verbinden.

Es gibt gute Anwendungsfälle für Supervisord oder ähnliche Programme, aber das Ausführen einer Webanwendung + Datenbank ist nicht Teil davon.

Verwenden Sie dazu auf jeden Fall Docker-Compose und orchestrieren Sie mehrere Container mit unterschiedlichen Verantwortlichkeiten.


2
Dies ist ein Kommentar, keine Antwort. Bitte fügen Sie eine Erklärung und / oder Links hinzu, um diese Position zu unterstützen. Ansonsten ist es nicht hilfreich.
Ivan Ivanov

1
Dies ist eine Antwort in dem Sinne, dass die beste Empfehlung, die ich in einem solchen Anwendungsfall geben kann, die Verwendung von Docker-Compose ist. Wie auch immer, Sie haben Recht, dass ich mehr Links zu offiziellen Empfehlungen geben könnte. Ich werde das aktualisieren.
Nicolas-van

Bei der Frage geht es darum, zwei Prozesse in einem Container auszuführen. Daher werden Best Practices nicht berücksichtigt. Ich werde Ihnen ein Beispiel geben: Ich musste rabbitmq in einem PhotonOS-basierten Bild und einem Java-Prozess ausführen ... Also habe ich ein Eingabeskript verwendet und es als ENTRYPOINT verwendet :)
Vallerious

Die ursprüngliche Frage ist keine generische Frage zur technischen Machbarkeit der Ausführung von zwei Prozessen in einem Docker-Container. Es gibt einen bestimmten Anwendungsfall an, bei dem eine Python-Anwendung zusammen mit einer MongoDB-Datenbank bereitgestellt wird. In diesem Anwendungsfall empfiehlt es sich, von der Verwendung eines einzelnen Containers abzuraten und die Verwendung von Docker-Compose zu empfehlen.
Nicole-van

5

Sie können sich in separaten Containern befinden. Wenn die Anwendung auch in einer größeren Umgebung ausgeführt werden soll, ist dies wahrscheinlich der Fall.

Ein Multi-Container-System würde etwas mehr Orchestrierung erfordern, um alle erforderlichen Abhängigkeiten aufrufen zu können. In Docker v0.6.5 + gibt es jedoch eine neue Funktion, die bei der in Docker selbst integrierten Funktion hilft - das Verknüpfen . Bei einer Lösung mit mehreren Maschinen muss dies jedoch immer noch von außerhalb der Docker-Umgebung arrangiert werden.

Bei zwei verschiedenen Containern kommunizieren die beiden Teile weiterhin über TCP / IP. Wenn die Ports jedoch nicht speziell gesperrt wurden (nicht empfohlen, da Sie nicht mehr als eine Kopie ausführen können), müssen Sie den neuen Port übergeben dass die Datenbank in Bezug auf die Anwendung verfügbar gemacht wurde, damit sie mit Mongo kommunizieren kann. Dies ist wieder etwas, bei dem Linking helfen kann.

Für eine einfachere, kleine Installation, bei der sich alle Abhängigkeiten in demselben Container befinden, ist es auch möglich, dass sowohl die Datenbank als auch die Python-Laufzeit von dem Programm gestartet werden, das ursprünglich als ENTRYPOINT aufgerufen wird. Dies kann so einfach sein wie ein Shell-Skript oder ein anderer Prozess-Controller. Supervisord ist sehr beliebt, und in den öffentlichen Docker-Dateien gibt es eine Reihe von Beispielen.


3

Ich stimme den anderen Antworten zu, dass die Verwendung von zwei Containern vorzuziehen ist, aber wenn Sie es sich zum Ziel gesetzt haben, mehrere Dienste in einem einzigen Container zu bündeln, können Sie so etwas wie Supervisord verwenden.

In Hipache führt beispielsweise die enthaltene Docker-Datei Supervisord aus, und die Datei Supervisord.conf gibt an, dass sowohl Hipache als auch Redis-Server ausgeführt werden sollen.


2

Docker bietet einige Beispiele dafür. Die leichte Option ist:

Fügen Sie alle Ihre Befehle in ein Wrapper-Skript ein, das Informationen zum Testen und Debuggen enthält. Führen Sie das Wrapper-Skript als Ihr aus CMD. Dies ist ein sehr naives Beispiel. Zunächst das Wrapper-Skript:

#!/bin/bash

# Start the first process
./my_first_process -D
status=$?
if [ $status -ne 0 ]; then
  echo "Failed to start my_first_process: $status"
  exit $status
fi

# Start the second process
./my_second_process -D
status=$?
if [ $status -ne 0 ]; then
  echo "Failed to start my_second_process: $status"
  exit $status
fi

# Naive check runs checks once a minute to see if either of the processes exited.
# This illustrates part of the heavy lifting you need to do if you want to run
# more than one service in a container. The container will exit with an error
# if it detects that either of the processes has exited.
# Otherwise it will loop forever, waking up every 60 seconds

while /bin/true; do
  ps aux |grep my_first_process |grep -q -v grep
  PROCESS_1_STATUS=$?
  ps aux |grep my_second_process |grep -q -v grep
  PROCESS_2_STATUS=$?
  # If the greps above find anything, they will exit with 0 status
  # If they are not both 0, then something is wrong
  if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
    echo "One of the processes has already exited."
    exit -1
  fi
  sleep 60
done

Als nächstes die Docker-Datei:

FROM ubuntu:latest
COPY my_first_process my_first_process
COPY my_second_process my_second_process
COPY my_wrapper_script.sh my_wrapper_script.sh
CMD ./my_wrapper_script.sh

2

Sie können 2 Prozesse im Vordergrund ausführen, indem Sie verwenden wait. Erstellen Sie einfach ein Bash-Skript mit dem folgenden Inhalt. ZB start.sh:

# runs 2 commands simultaneously:

mongod & # your first application
P1=$!
python script.py & # your second application
P2=$!
wait $P1 $P2

Beginnen Sie in Ihrer Docker-Datei mit

CMD bash start.sh

0

Wenn ein dediziertes Skript zu viel Aufwand bedeutet, können Sie separate Prozesse explizit mit erzeugen sh -c. Beispielsweise:

CMD sh -c 'mini_httpd -C /my/config -D &' \
 && ./content_computing_loop
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.