2016-06-15 15 views
7

Ich habe ein Docker Image, das ein Script (/bin/bash /init.sh) als Entrypoint verwendet. Ich möchte dieses Skript nur beim ersten Start eines Containers ausführen. Es sollte weggelassen werden, wenn die Container nach einem Absturz des Docker-Daemons neu gestartet oder neu gestartet werden.Befehl im Docker Container nur beim ersten Start ausführen

Gibt es eine Möglichkeit, dies mit docker selbst zu tun, oder tun, wenn Sie eine Art von Überprüfung im Skript implementieren müssen?

Antwort

9

Der Einstiegspunkt für einen Andock-Container teilt dem Andock-Dämon mit, was ausgeführt werden soll, wenn Sie diesen spezifischen Container "ausführen" möchten. Stellen wir uns die Frage "Was sollte der Container beim zweiten Start?" oder "Was sollte der Container nach dem Neustart ausführen?"

Wahrscheinlich folgen Sie dem gleichen Ansatz, den Sie mit "Old-School" Provisioning-Mechanismen machen. Dein Skript "installiert" die benötigten Skripte und du wirst deine App als Systemstart-Dienst starten, richtig? Wenn Sie das tun, sollten Sie das in eine "dockerisierte" Definition ändern.

Der Einstiegspunkt für diesen Container sollte ein Skript sein, das Ihre App tatsächlich startet, anstatt Dinge einzurichten. Angenommen, Sie benötigen Java installiert, um Ihre App ausführen zu können. So in der dockerfile legen Sie den Grundbehälter bis zu installieren, alle Dinge, die Sie brauchen, wie:

FROM alpine:edge 

RUN apk --update upgrade && apk add openjdk8-jre-base 
RUN mkdir -p /opt/your_app/ && adduser -HD userapp 

ADD target/your_app.jar /opt/your_app/your-app.jar 
ADD scripts/init.sh /opt/your_app/init.sh 

USER userapp 
EXPOSE 8081 

CMD ["/bin/bash", "/opt/your_app/init.sh"] 

Unsere Container, in der Firma für die ich arbeite, bevor die eigentliche App im init.sh Skript laufen sie holen die configs from consul (anstatt einen Bereitstellungspunkt bereitzustellen und die Konfigurationen innerhalb des Hosts zu platzieren oder sie in den Container zu integrieren). So wird das Skript in etwa so aussehen:

#!/bin/bash 

echo "Downloading config from consul..." 
confd -onetime -backend consul -node $CONSUL_URL -prefix /cfgs/$CONSUL_APP/$CONSUL_ENV_NAME 
echo "Launching your-app..." 
java -jar /opt/your_app/your-app.jar 

Ein Rat, den ich Ihnen geben kann, ist (in meiner wirklich kurzen Erfahrung mit Containern arbeitet) behandelt Ihre Container, als ob sie staatenlos waren, sobald sie bereitgestellt werden (alle Befehle, die Sie ausführen vor dem Einstiegspunkt).

+1

Stimmen Sie vollkommen überein, Container staatenlos zu betrachten. Wenn Daten initialisiert werden sollen, legen Sie sie in ein Volume. – BMitch

+2

Ich würde wirklich gerne Ihrem Rat folgen, aber es ist nicht so einfach. Ich habe sehr wenig Einfluss auf Änderungen der App und es musste geändert werden, um es so zu verwenden, wie Sie es beschrieben haben. Beispiel: Bei jedem Start eines Containers richtet das init-Skript eine Datenbank für die App ein. Dies sollte nicht passieren, wenn der Container neu gestartet wird, da er die bereits vorhandenen Daten überschreibt ... Leider hat es sich als sehr schwierig herausgestellt, den Entwicklern der App beizubringen, wie man docker verwendet. Also versuche ich es extrem einfach für sie zu halten. – christian

+0

Wie läuft das? – StarWind0

1

Ich wollte das gleiche auf Windows-Container tun. Dies kann mit dem Taskplaner in Windows erreicht werden. Linux-Äquivalent für Task-Scheduler ist Cron. Sie können das in Ihrem Fall verwenden. Zu tun, um die dockerfile dieses bearbeiten und fügen Sie die folgende Zeile am Ende

WORKDIR /app 
COPY myTask.ps1 . 
RUN schtasks /Create /TN myTask /SC ONSTART /TR "c:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe C:\app\myTask.ps1" /ru SYSTEM 

Dies schafft eine Aufgabe mit dem Namen myTask läuft es OnStart und die Aufgabe seiner selbst ist ein Powershell-Skript auszuführen, platziert auf „c: \ app \ myTask.ps1 ".

Dieses Skript myTask.ps1 führt die Initialisierung aus, die beim Start des Containers durchgeführt werden muss. Stellen Sie sicher, dass Sie diese Aufgabe löschen, sobald sie erfolgreich ausgeführt wurde, sonst wird sie bei jedem Start ausgeführt. Um es zu löschen, können Sie den folgenden Befehl am Ende von myTask.ps1 Skript verwenden.

schtasks /Delete /TN myTask /F 
0

Ich hatte dies zu tun, und ich beenden ein docker run -d da oben, die nur einen freistehenden Container erstellt und gestartet bash (im Hintergrund) von einem docker exec gefolgt, welche die notwendigen Initialisierung tat. hier ist ein Beispiel

docker run -itd --name=myContainer myImage /bin/bash 
docker exec -it myContainer /bin/bash -c /init.sh 

Nun, wenn ich meinen Container nur ein Neustart

, was ich kann
docker start myContainer 
docker attach myContainer 

dies nicht ideal sein kann, aber die Arbeit für mich.

Verwandte Themen