Home > Software engineering >  Use cp in entrypoint for docker run
Use cp in entrypoint for docker run

Time:10-28

There is Dockerfile

FROM openjdk:11.0.12-jre-slim
COPY target/app.jar /app.jar
COPY configs configs
ENTRYPOINT ["java","-jar","/app.jar"]

In folder configs contains json configs for java application. The build docker command is:

docker build --build-arg -f ~/IdeaProjects/app --no-cache -t app:latest

And the run command is:

docker run --entrypoint="cp configs var/opt/configs/ && java -jar app.jar" app:latest

Let's omit the ability to copy configs in the Dockerfile via COPY command. Unfortunately, this must be done using --entrypoint.

An error occurs when the docker run command was executed:

docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "cp configs var/opt/configs/ && java -jar app.jar": stat cp configs var/opt/configs/ && java -jar app.jar: no such file or directory: unknown.

Could you explain why the error occurred in this case?

CodePudding user response:

I would do this with an entrypoint wrapper script. A Dockerfile can have both an ENTRYPOINT and a CMD; if you do, the CMD gets passed as arguments to the ENTRYPOINT. This means you can make the ENTRYPOINT a shell script that does first-time setup, then ends with exec "$@" to replace itself with the CMD.

#!/bin/sh
# docker-entrypoint.sh

# copy the configuration to the right place
cp configs var/opt/configs/

# run the main container command
exec "$@"

In the Dockerfile, make sure to COPY the script in (it should be checked in to source control as executable) and set it as the ENTRYPOINT.

...
COPY docker-entrypoint.sh .
ENTRYPOINT ["./docker-entrypoint.sh"] # must be JSON-array syntax
CMD ["java", "-jar", "/app.jar"]      # what was previously ENTRYPOINT

When you run the container it's straightforward to replace the CMD, so you can double-check that this is doing the right thing by running an interactive shell in place of the java application.

docker run -v "$PWD/alt-configs:/configs" --rm -it my-image sh

If you do need to override the command like this at docker run time, the command you show uses && to run two commands consecutively. This needs to run a shell to be understood correctly, and in this context you need to manually provide a /bin/sh -c wrapper.

I would still recommend changing ENTRYPOINT to CMD in your Dockerfile; then you could run a relatively straightforward

docker run \
  ... \
  -v "$PWD/alt-configs:/configs" \
  my-image \
  /bin/sh -c 'cp configs var/opt/configs && java -jar /app.jar'

If you use --entrypoint, it only takes the first word out of this command, and it is a Docker options so it needs to come before the image name. I'd recommend designing your image to avoid needing this awkward construct.

docker run \
  ... \
  -v "$PWD/alt-configs:/configs" \
  --entrypoint /bin/sh \
  my-image \
  -c 'cp configs var/opt/configs && java -jar /app.jar'

Your proposed command is having problems because it's trying to pass the entire command, including the embedded spaces and shell operators, as a single word, but that causes the OS-level process handling to try to look for an executable file with spaces and ampersands in the filename, hence the "no such file or directory" error.

  • Related