Arne Mertz Arne Mertz - 24 days ago 9
Java Question

Overriding inherited CMD in Dockerfile does not always work?

I am getting some inconsistent behavior in connection with overriding CMD in a derived Dockerfile.

The base Dockerfile looks something like this:

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


This base image is provided by another team and it would be difficult to change it. I am now composing a bunch of containers where I want to run the same app multiple times, but with different configurations.

So I figured I'd extend the image copying some more configuration into it and running it with a different spring profile:

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


And in the 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


I would have expected to have 2 containers running, using the
application-foo.properties
and
application-bar.properties
respectively.

It seems, though, that both use the appplication-docker.properties , i.e. the
docker
profile defined in the base Dockerfile.

If I change the CMD in the derived Dockerfile completely, it works:

CMD echo "${PROFILE}"


Output is "foo" and "bar", respectively. Any hints what might be going on?

My versions are:

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


Update:

After @blackibiza's suggestions, I changed the derived Dockerfile to

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"]


Without the docker-compose stuff, just to see how the derived image would look like. I get error messages from java, trying to run the container. Inspecting the image gives the following:

$ 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 it still tries to execute
/bin/sh
and not java. That doesn't look like what I would have expected from the documentation.

Update2:
Using the JSON-array syntax for CMD triggers another problem:

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


Will not expand the use of
${WEBAPP_CONTEXT}
and therefore result in an error

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

Answer

Don't just copy & paste faulty Java commands. The -Dspring.profile.active argument will not be recognized if it comes after the .jar file.

Fix the CMD line to be

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

and all is well.

See also "Setting active profile and config location from command line in spring boot"