Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to source an entry point script with Docker?

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.

like image 399
Dr. Fabien Tarrade Avatar asked Jun 13 '19 18:06

Dr. Fabien Tarrade


2 Answers

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.)

like image 159
David Maze Avatar answered Oct 06 '22 13:10

David Maze


In an interactive shell, source tells the shell to read the commands from the file without creating a subshell. In your case, you want the initial shell to execute the commands from a script. So all you have to do is give the script as an argument. Try the following:

ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]

However, it is not a good idea to run a shell as the initial process in a container. That screws up the signal handling. You'll notice that you cannot stop execution with Ctrl-C. Therefore, use CMD instead of ENTRYPOINT to start the shell. The initial process with id 1 should be a minimal init process, such as tini.

like image 43
Roland Weber Avatar answered Oct 06 '22 13:10

Roland Weber