I am trying to override the entrypoint in a docker
image with a script execution that accepts arguments, and it fails as follows
▶ docker run --entrypoint "/bin/sh -c 'my-script.sh arg1 arg2'" my-image:latest
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "/bin/sh -c 'myscript.sh arg1 arg2'": stat /bin/sh -c 'my-script.sh arg1 arg2': no such file or directory: unknown.
However when I exec to the container, the above command succeeds:
▶ docker run --entrypoint sh -it my-image:latest
~ $ /bin/sh -c 'my-script.sh arg1 arg2'
Success
Am I missing sth in the syntax?
CodePudding user response:
Remember that arguments after the container image name are simply passed to the ENTRYPOINT script. So you can write:
docker run --entrypoint my-script.sh my-image:latest arg1 arg2
For example, if I have my-script.sh
(mode 0755
) containing:
#!/bin/sh
for arg in "$@"; do
echo "Arg: $arg"
done
And a Dockerfile like this:
FROM docker.io/alpine:latest
COPY my-script.sh /usr/local/bin/
ENTRYPOINT ["date"]
Then I can run:
docker run --rm --entrypoint my-script.sh my-image arg1 arg2
And get as output:
Arg: arg1
Arg: arg2
If you want to run an arbitrary sequence of shell commands, you can of course do this:
docker run --rm --entrypoint sh my-image \
-c 'ls -al && my-script.sh arg1 arg2'
CodePudding user response:
If you need to do this at all regularly, you can refactor your Dockerfile to make this easier to do.
A Docker container's main process is run by concatenating together the "entrypoint" and "command" argument lists. In a Dockerfile, these come from the ENTRYPOINT
and CMD
directives. In the docker run
command this is trickier: anything after the image name is the "command" part, but the "entrypoint" part needs to be provided by the --entrypoint
argument, it needs to be before the image name, and it can only be a single word.
If you need to routinely replace the command, the syntax becomes much cleaner if you set it using CMD
and not ENTRYPOINT
in the Dockerfile.
# Dockerfile
CMD ["some", "main", "command"] # not ENTRYPOINT
If you make this change, then you can just put your alternate command after the image name in the docker run
command, without a --entrypoint
option and without splitting the command string around the image name.
docker run my-image:latest /bin/sh -c 'my-script.sh arg1 arg2'
I will somewhat routinely recommend a pattern where ENTRYPOINT
is a wrapper script that does some first-time setup, then does something like exec "$@"
to run the command that's passed to it as arguments. That setup is compatible with this CMD
-first approach: the entrypoint wrapper will do its setup and then run the override command instead of the image's command.