How to source an entry point script with Docker?

Dr. Fabien Tarrade picture Dr. Fabien Tarrade · Jun 13, 2019 · Viewed 11.8k times · Source

I have an Docker image and I can run it:

docker run -it --entrypoint="/bin/bash" gcr.io/docker:tag

Then I can source a script in the following way:

root@86bfac2f6ccc:/# source entrypoint.sh

The script looks like that:

more entrypoint.sh
#!/bin/bash
. /env.sh
. /root/miniconda3/etc/profile.d/conda.sh
conda activate base
exec "$@"

Which activate the base env:

(base) root@86bfac2f6ccc:/#

So far so good but I don't managed to include this in the Dockerfile or as parameters to docker run:

I tried many things:

For example:

docker run -it --entrypoint="/bin/bash"  gcr.io/docker:tag  source entrypoint.sh
/bin/bash: source: No such file or directory

But the script exist and can be executed:

docker run -it --entrypoint="/bin/ls"  gcr.io/docker:tag -la
...
-rwxr-xr-x  1 root root   94 Apr 26 20:36 entrypoint.sh
...

Or:

docker run -it --entrypoint="/bin/bash"  gcr.io/docker:tag  ". /entrypoint.sh"
/bin/bash: . /entrypoint.sh: No such file or directory

Or in the Docker file:

ENTRYPOINT ["source", "/entrypoint.sh"]

I guess the issue I have is maybe related the fact that source evaluate a script in the current shell.

Any guidance to achieve what I want ? It seems quite obvious but I am out of idea.

Answer

David Maze picture David Maze · Jun 13, 2019

When Docker launches a container, there are two parts, the “entrypoint” and the “command”. When both are specified, the “command” part is passed as command-line arguments to the “entrypoint” part.

In particular, the script you show has a very typical pattern for an entrypoint script:

#!/bin/sh
# ... do some setup ...
# then run the CMD passed as command-line arguments
exec "$@"

If your Dockerfile names this script as its ENTRYPOINT then you want to pass the command you want to run as the “command” part. If you run your shell as just

docker run --rm -it gcr.io/docker:tag sh

then sh will be passed to the entrypoint script, which will do the setup and then eventually run it.

(Remember that source is a vendor-specific extension and doesn’t exist in many shells, like the minimal BusyBox shell that Alpine base images use, but that . means the same thing and is in the POSIX standard. Since a container only runs one process it also doesn’t really make sense for that one process to be “source this file”; it would set up some environment variables, and then it’s done so the container exits. The entrypoint pattern does the setup and then runs the main container command.)