2016-11-11 2 views
0

Ich bekomme ein inkonsistentes Verhalten in Verbindung mit überschreiben CMD in einer abgeleiteten Dockerfile.Überschreiben geerbten CMD in Dockerfile funktioniert nicht immer?

Die Basis Dockerfile sieht ungefähr so ​​aus:

FROM myVeryBaseImage 

ENV WEBAPP_CONTEXT=my-app 
WORKDIR /opt/${WEBAPP_CONTEXT} 

COPY app/*.jar ./${WEBAPP_CONTEXT}.jar 
COPY baseconfig/* ./config/${WEBAPP_CONTEXT}/ 

CMD java -jar ${WEBAPP_CONTEXT}.jar --Dspring.profiles.active=docker 

Diese Basisbild wird von einem anderen Team zur Verfügung gestellt und es würde schwierig sein, sie zu ändern. Ich stelle jetzt eine Reihe von Containern zusammen, in denen ich die gleiche App mehrmals, aber mit unterschiedlichen Konfigurationen ausführen möchte.

Also dachte ich, dass ich das Bild verlängern würde etwas mehr Konfiguration in kopiert und mit einer anderen Federprofil ausgeführt wird:

FROM baseImage 
COPY config/application-*.properties ./config/${WEBAPP_CONTEXT}/ 
CMD java -jar ${WEBAPP_CONTEXT}.jar -Dspring.profiles.active=${PROFILE} 

Und in der Docker-compose.yml:

myapp-foo: 
build: ./myapp-custom 
image: myapp-custom 
environment: 
    PROFILE: foo 
volumes: 
    - /opt/my-app/foo:/opt/my-app 

myapp-bar: 
image: myapp-custom 
environment: 
    PROFILE: bar 
volumes: 
    - /opt/my-app/bar:/opt/my-app 

Ich hätte erwartet, 2 Container laufen zu haben, mit den application-foo.properties bzw. application-bar.properties.

Es scheint jedoch, dass beide die appplication-docker.properties, d. H. Das docker Profil in der Basis-Dockerfile definiert verwenden.

Wenn ich die CMD in der abgeleiteten Dockerfile vollständig ändern, es funktioniert:

CMD echo "${PROFILE}" 

Ausgang ist "foo" und "bar" bezeichnet. Irgendwelche Hinweise was passieren könnte?

Meine Versionen sind:

docker-compose version 1.8.1, build 878cff1 
Docker version 1.12.3, build 6b644ec 

Update:
Nach @ Vorschläge blackibiza des änderte ich die abgeleitete Dockerfile zu

FROM baseImage 
COPY config/application-*.properties ./config/${WEBAPP_CONTEXT}/ 
ENTRYPOINT /opt/jdk1.8.0_102/bin/java 
CMD ["-jar", "${WEBAPP_CONTEXT}.jar", "-Dspring.profiles.active=foo"] 

Ohne die Docker-compose Sachen, nur um zu sehen, wie das abgeleitete Bild würde aussehen. Ich bekomme Fehlermeldungen von Java und versuche den Container auszuführen. Inspizieren des Bildes ergibt sich folgendes:

$ docker inspect --format='{{.Config.Cmd}} {{.Config.Entrypoint}}' testapp 
[-jar ${WEBAPP_CONTEXT}.jar -Dspring.profiles.active=french] [/bin/sh -c /opt/jdk1.8.0_102/bin/java] 

So versucht es noch /bin/sh und nicht die Ausführung von Java. Das sieht nicht so aus, wie ich es von der Dokumentation erwartet hätte.

Update2: für CMD die JSON-Array-Syntax löst ein weiteres Problem:

FROM baseImage 
COPY config/application-*.properties ./config/${WEBAPP_CONTEXT}/ 
CMD ["java", "-jar", "${WEBAPP_CONTEXT}.jar", "-Dspring.profiles.active=foo"] 

Wird die Verwendung von ${WEBAPP_CONTEXT} nicht erweitern und führen daher zu einem Fehler

Error: Unable to access jarfile ${WEBAPP_CONTEXT}.jar 

Antwort

3

Was Sie suchen ist die Überschreibung des Einstiegspunktes. Wie beschrieben in the Docker reference,

Wenn Sie ohne Schale Ihre ausführen möchten, dann müssen Sie den Befehl als JSON-Array auszudrücken und den vollständigen Pfad zu dem ausführbaren geben. Diese Array-Form ist das bevorzugte Format von CMD. Etwaige zusätzliche Parameter müssen einzeln als Zeichenfolgen in der Array ausgedrückt werden:

VON ubuntu

CMD [ "/ usr/bin/WC", "- help"]

Wenn Sie möchten, dass Ihr Container alle Mal dieselbe ausführbare Datei ausführt, sollten Sie ENTRYPOINT in Kombination mit CMD verwenden. Siehe ENTRYPOINT.

Während mit Composer Sie die CMD-Argumente wie explained here außer Kraft setzen können:

db: 
    command: '-d' 
    ports: 
    - 5432:5432 

sollten Sie eine ENTRYPOINT definieren, die in Ihrem Fall ist:

ENTRYPOINT java 
CMD ["-jar", "${WEBAPP_CONTEXT}.jar"] 

In Ihrem speziellen Fall, ich wird argumentieren, die Shell als Einstiegspunkt freizulegen und den CMD mit einem Skript zu überschreiben, wie:

ENTRYPOINT /bin/sh 
CMD ["./script.sh"] 

und in Ihrem compose YML:

command: './script2.sh' 

UPDATE (basierend auf geänderte Frage):

Was fehlt es ist die Definition der Variablen. In diesem Fall schlage ich ARG statt ENV zu bauen, den Behälter mit dem permanenten Wert in geben zu verwenden:

docker build -t your_image:your_version --build-arg WEBAPP_CONTEXT=your_context . 

eine Substitution des Wertes zum Zeitpunkt der Erstellung zu erhalten. Die ARG hat den Vorteil,

in Ihrem Kind Bildern vererbt
+0

Hallo Michele, ich das gleiche Programm in den abgeleiteten leite und das Basisbild, es ist nur der ein Parameter, der geändert werden soll. Ich wollte vermeiden, dass ich die gesamte Litanei in einem Befehl in der Compose-Datei wiederholen muss. Sollte ein CMD in der abgeleiteten Dockerfile das gleiche tun? –

+0

@ArneMertz Ja, aber Sie verwenden nicht das JSON-Formular, das in der Docker-Referenz angegeben ist, solange Sie keine Shell zum Starten verwenden.Versuchen Sie, als Standard ENTRYPOINT Java zu definieren und lassen Sie CMD nur den Parameter konfigurieren, wie: CMD ["$ {PROFILE}"] – madduci

+0

@ArneMertz IÄve hat den Vorschlag hinzugefügt, ARG anstelle von ENV für Ihren Fall zu verwenden, mit dem JSON-Ansatz – madduci

Verwandte Themen