Running a script in Docker container by accepting -e parameter - docker

I have a very simple script called as myscript.sh
echo "this is test " > /tmp/myfile.txt
echo $TEST >> /tmp/myfile.txt
I have stored this script in my disk which i plan to pass it to the container as a volume like this below
docker run -d --name test \
-v /home/docker/test/myscript.sh:/tmp/myscript.sh \
-e TESTING=just-a-test \
test
The Dockerfile looks like this below
FROM ubuntu
CMD ["bash", "/tmp/myscript.sh"]
So the thought process is to get this script executed and get the result as a file myfile.txt which would contain the -e passed.
Instead i am getting
docker#boot2docker:~/test$ docker exec -it test /bin/bash Error
response from daemon: Container test is not running
Which means that this simplest program did not execute as a container.
I Could not figure it out.

The container ran, executed the script, then exited. A container only runs as long as its main process. When that stops, the container stops.
A simpler test would be to change your test script to:
#!/bin/bash
echo $TEST
I would change your Dockerfile to copy the file in and remove the "bash" part of the CMD instruction:
FROM ubuntu
COPY myscript.sh /myscript.sh
CMD /myscript.sh
Now rebuild and run:
$ docker build -t test .
...
$ docker run -e TEST=VAL test
...
The container should echo the value of the test variable and exit. (I haven't tested any of this, so apologies for any mistakes).

The answer to this question is to use the entrypoint instead of cmd.
I did some research and i came up with the solution that looks like this
ENTRYPOINT ["bash", "<script>"]
To run the script just use
docker run -d --name [--privileged] -p : \
- v /script.sh:/tmp/script.sh \
where -v <> : YOU CAN ALSO USE THE WGET TO GET THE SCRIPT LIKE MOST PEOPLE AND EXECUTE AT RUNTIME.
Appreciate all the people who tried to solve the query

Related

Trying to copy a script into a detached Docker container, and execute it with docker exec

Right now I am setting my Docker instance running with:
sudo docker run --name docker_verify --rm \
-t -d daoplays/rust_v1.63
so that it runs in detached mode in the background. I then copy a script to that instance:
sudo docker cp verify_run_script.sh docker_verify:/.
and I want to be able to execute that script with what I expected to be:
sudo docker exec -d docker_verify bash \
-c "./verify_run_script.sh"
However, this doesn't seem to do anything. If from another terminal I run
sudo docker container logs -f docker_verify
nothing is shown. If I attach myself to the Docker instance then I can run the script myself but that sort of defeats the point of running in detached mode.
I assume I am just not passing the right arguments here, but I am really not clear what I should be doing!
When you run a command in a container you need to also allocate a pseudo-TTY if you want to see the results.
Your command should be:
sudo docker exec -t docker_verify bash \
-c "./verify_run_script.sh"
(note the -t flag)
Steps to reproduce it:
# create a dummy script
cat > script.sh <<EOF
echo This is running!
EOF
# run a container to work with
docker run --rm --name docker_verify -d alpine:latest sleep 3000
# copy the script
docker cp script.sh docker_verify:/
# run the script
docker exec -t docker_verify sh -c "chmod a+x /script.sh && /script.sh"
# clean up
docker container rm -f docker_verify
You should see This is running! in the output.

How to run a "docker run .." command from within a shell script

I have a shell script containing a call to docker run. The script looks like this:
#!/bin/sh
#Local directory where your data is.
PATH_TO_EXPORTS="/home/user/data"
iType_NAME="iType.csv"
colIDs="X,Y,W,Z"
FLAG="FALSE"
#These next three variables don't need to, and should not be changed.
#They refer to locations within the docker container - DO NOT CHANGE !!!
IMG_EXPORTS_DIR="/home/rstudio/project/exports"
#Execute docker run to carry out your analysis
docker run -v $PATH_TO_EXPORTS:$IMG_EXPORTS_DIR \
-e PATH_TO_EXPORTS=$IMG_EXPORTS_DIR \
-e iType_NAME=$iType_NAME \
-e colIDs=$colIDs \
-e FLAG=$FLAG \
--user "$(id -u)" \
my_docker_image:3.0
If I try to run this script via command line by calling: sh myScript.sh , I get the following error:
docker: invalid reference format.
See 'docker run --help'.
However, if I manually run the docker run ... command on the command line, everything works as expected.
Does anybody know why this docker run ... command fails when inside a shell script ?
Many thanks in advance !
-M.

Require environment variables to be given to image when run using `-e`

I have a container image that requires an environment variable to be set in order to run. But if run with -d, unless the container is monitored, the person running the container won't notice something is missing. Is there a way that docker [container] run checks that an environment variable is given to the container before starting it.
In detach mode it not possible to print message that env is required, in your word when running with -d, but you can try a workaround:
Dockerfile
FROM alpine
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
entrypoint.sh
#!/bin/sh
echo "starting container $hostname"
if [ -z "$REQUIRED_ENV" ]; then
echo "Container failed to start, pls pass -e REQUIRED_ENV=sometest"
exit 1
fi
echo "starting container with $REQUIRED_ENV"
#your long-running command from CMD
exec "$#"
So when you run with
docker run -it --name envtest --rm env-test-image
it will exit with the message
starting container
Container failed to start, pls pass -e REQUIRED_ENV=sometest
The workaround with detach mode
docker run -it --name envtest -d --rm env-test-image && docker logs envtest
No: there is currently no way to make Docker aware of "dependencies" in the form of environment variables. This answer isĀ for those who actually came here just looking for a canonical way to exit an entrypoint script in case of missing values.
A POSIX shell takes the option -u (error when expanding unset variables) and -e (exit the shell when any statement returns an error/non-zero exit code). We also have : to evaluate-but-not-invoke an expression. Putting these together, we should be able to make an entrypoint.sh that works irrespective of sh-implementation like this:
#!/bin/sh -e -u
( : $USERNAME )
( : $PASSWORD )
exec "$#"
which will exit the script with an error akin to PASSWORD: parameter not set.
Another way of doing the same thing, but in context of the original example with a custom error message, could make use of the "Display Error if Null or Unset" operator (${parm:?error}) and look something like so:
#!/bin/sh
echo "starting container $hostname"
( : ${REQUIRED_ENV?"pls pass -e REQUIRED_ENV=sometest"} ) || exit 1
echo "starting container with $REQUIRED_ENV"
#your long-running command from CMD
exec "$#"

override default docker run from host with options/arguments

FROM alpine:3.5
CMD ["echo", "hello world"]
So after building docker build -t hello . I can run hello by calling docker run hello and I get the output hello world.
Now let's assume I wish to run ls or sh - this is fine. But what I really want is to be able to pass arguments. e.g. ls -al, or even tail -f /dev/null to keep the container running without having to change the Dockerfile
How do I go about doing this? my attempt at exec mode fails miserably... docker run hello --cmd=["ls", "-al"]
Anything after the image name in the docker run command becomes the new value of CMD. So you can run:
docker run hello ls -al
Note that if an ENTRYPOINT is defined, the ENTRYPOINT will receive the value of CMD as args rather than running CMD directly. So you can define an entrypoint as a shell script with something like:
#!/bin/sh
echo "running the entrypoint code"
# if no args are passed, default to a /bin/sh shell
if [ $# -eq 0 ]; then
set -- /bin/sh
fi
# run the "CMD" with exec to replace the pid 1 of this shell script
exec "$#"
Q. But what I really want is to be able to pass arguments. e.g. ls -al, or even tail -f /dev/null to keep the container running without having to change the Dockerfile
This is just achieved with:
docker run -d hello tail -f /dev/null
So the container is running in background, and it let you to execute arbitrary commands inside it:
docker exec <container-id> ls -la
And, for example a shell:
docker exec -it <container-id> bash
Also, I recommend you what #BMitch says.

Enter into docker container after shell script execution is complete

If I want to execute one shell script as ENTRYPOINT and enter into docker container when shell script execution is complete.
My Dockerfile has following lines at the end:
WORKDIR artifacts
ENTRYPOINT ./my_shell.sh
When I run it with following command, it executes shell script but doesn't enter into docker container.
docker run -it testub /bin/bash
Can someone please let me know if I am missing anything here?
There are two options that control what a container runs when it starts, the entrypoint (ENTRYPOINT) and the command (CMD). They follow the following logic:
If the entrypoint is defined, then it is run with the value for the command included as additional arguments.
If the entrypoint is not defined, then the command is run by itself.
You can override one or both of the values defined in the image. docker run -it --entrypoint /bin/sh testub would run /bin/sh instead of ./my_shell.sh, overriding the entrypoint. And docker run -it testub /bin/bash will override the command, making the container start with ./my_shell.sh /bin/bash.
The quick answer is to run docker run -it --entrypoint /bin/bash testub and from there, kick off your ./my_shell.sh. A better solution is to update ./my_shell.sh to check for any additional parameters and run them with the following at the end of the script:
if [ $# -gt 0 ]; then
exec "$#"
fi

Resources