1

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?

pkaramol
  • 16,451
  • 43
  • 149
  • 324

3 Answers3

0

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'
larsks
  • 277,717
  • 41
  • 399
  • 399
  • I have accpeted your answer but what is the syntax if I want to run something else before `my-script.sh`? e.g. `/bin/sh -c "ls -al && my-script.sh arg1 arg2"` – pkaramol Sep 21 '22 at 17:04
  • Well you can run anything you want after all options, say `docker run --rm -it debian /bin/sh -c "echo hi && echo bye"`, is this what you want to do? – Arkadiusz Drabczyk Sep 21 '22 at 17:11
  • 1
    I've updated the answer in response to your comment, but it helps to make sure your question accurately reflects what you're trying to do, because that will impact the content of the answers. – larsks Sep 21 '22 at 18:08
0

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.

David Maze
  • 130,717
  • 29
  • 175
  • 215
0

Not pretty but this worked for me:

docker run image "/bin/bash" "-c" "source ~/.bashrc && /bin/bash"
tdy
  • 36,675
  • 19
  • 86
  • 83