Running docker from bash script - bash

I am using a tool (gatk) distributed as a docker image and try to use its commands in a shell script.
I run the docker in detached mode.
sudo docker run --name my_container -d -v ~/test:/gatk/data -it broadinstitute/gatk:4.1.9.0
Then I run the commands from shell script
#!/bin/bash
docker exec my_container gatk command1
wait
docker exec my_container gatk command2
command2 needs input from command1 so I use wait, but still command2 is executed before command 1 is finished.
I also tried
#!/bin/bash
docker exec my_container gatk command1
docker wait my_container
docker exec my_container gatk command2
but then the script does not continue running after command1 is completed.

I managed to solve it. The problem was is that when I ran docker exec I did not define it to receive input from the shell. Adding -i flag to docker exec solved the problem. Here is the full solution.
I start docker in detached mode
sudo docker run --name my_container -d -v ~/test:/gatk/data -it broadinstitute/gatk:4.1.9.0
Now I can close the terminal, the docker container is up and running and I can use it in a new terminal.
I generate a bash script called myscript.sh with the following code.
#!/bin/bash
docker exec -i my_container gatk command1
wait
docker exec -i my_container gatk command2
I run the script, disown it and close the terminal.
./myscript.sh&disown;exit

You can run both commands in a single shot:
docker run image /bin/bash -c "gatk command1 && gatk command2"

Related

How to run a bash terminal in a Docker container along with additional commands?

To run a bash terminal in a Docker container I can run the following:
$ docker exec -it <container> /bin/bash
However, I want to execute a command in the container automatically. For example, if I want to open a bash terminal in the container and create a file I would expect to run something like:
docker exec -it <container> /bin/bash -c "touch foo.txt"
However, this doesn't work... Is there a simple way to achieve this? Of course, I could type the command after opening the container, but I want to open a bash terminal and run a command at the same time.
You can run your touch command and then spawn another shell :
docker exec -it <container> /bin/bash -c "touch foo.txt; exec bash"
Works perfectly fine for me
~# docker run -tid --rm --name test ubuntu:20.04
~# docker exec -it test /bin/bash -c "touch /foo.txt"
~# docker exec -it test /bin/bash
root#b6b0efbb13be:/# ls -ltr foo.txt
-rw-r--r-- 1 root root 0 Mar 7 05:35 foo.txt
Easy solution:
docker exec -it <container> touch foo.txt
You can verify
docker exec -it <container> ls
This was tested with alpine image.
Remember that in docker images there is a entrypoint and a command. Now we are editing the command of the default entrypoint for alpine, via docker exec
It depends of the entrypoint if env variablers are load or not, $PATH ..., so other images maybe you need to write /bin/touch or /usr/bin/ls
Good luck!
When you run docker exec -it <container> /bin/bash -c "touch foo.txt", container sends 0 exit code so that it means the task is done and you'll be returned to your host.
When you run docker exec -it <container /bin/bash, bash shell is not terminated until you explicitly type exit or use CTRL+D in bash environment. bash is continuously running.
This is why when you run the second command, it goes to bash, runs your command (touches) and then exits.

How to bash into a docker container

trying to bash into container and do a for loop which simply performs a command (which works on a single file by the way). it even seems to echo the right command...what did I forget
Untitled
for pdf in *.pdf ;
do
docker run --rm -v "$(pwd):/home/docker" leofcardoso/pdf2pdfocr -g jpeg2000 -v -i '\'''$pdf''\''';
done
You can bash in a container with this commands:
To see the docker container id
docker container ls
To enter in bash inside a container.
docker exec -it CONTAINER_ID bash
First thing, you are not allocating tty in the docker run command and the docker container dies soon after converting files. Here is main process of container
#!/bin/bash
cd /home/docker
exec pdf2pdfocr.py "$#"
So, in this case, the life of this container is the life of exec pdf2pdfocr.py "$#" command.
As mentioned by #Fra, override the entrypoint and run the command manually.
docker run --rm -v "$(pwd):/home/docker" -it --entrypoint /bin/bash leofcardoso/pdf2pdfocr
but in the above run command, docker container will do not a thing and will just allocate the tty and the bash will open. So you can convert files inside your containers using docker exec and then run pdf2pdfocr.py -g jpeg2000 -v -i mypdf.pdf
So, if you want to run with override entry point then you can try.
docker run -it --rm --entrypoint /bin/bash -v "$(pwd):/home/docker" leofcardoso/pdf2pdfocr -c "pdf2pdfocr.py -g jpeg2000 -v -i mypdf.pdf"
or with the bash script
#!/bin/bash
for pdf in *.pdf ;
do
echo "converting $pdf"
docker run -it --rm --entrypoint /bin/bash -v "$(pwd):/home/docker" leofcardoso/pdf2pdfocr -c "pdf2pdfocr.py -g jpeg2000 -v -i $pdf"
done
But the container will die after completing the conversion.

get command executed result from docker container

anyway for me to know when command is finished inside docker container? I have created a docker container and able to send command from my local into docker container by docker exec
so far in my bash script I am using sleep to wait until "cd root: npm install" command finished inside docker container. If I do not have sleep, done is printed out right away after npm install is sent into docker container. How can I remove sleep so done is printed out only after npm install is finished inside docker container?
docker exec -d <docker container name> bash -c "cd root;npm install"
sleep 100
echo "done"
Don't background the command if you want to keep it running in the foreground (the -d flag):
docker exec <docker container name> bash -c "cd root;npm install"
echo "done"
Run it as background process & and then wait for it:
docker exec -d <docker container name> bash -c "cd root;npm install" &
wait
echo "done"
If you omit the -d (detach) the docker exec will return only after completion (and not immediately), so no wait will be needed.

Docker kill not working when executed in shell script

The following works fine when running the commands manually line by line in the terminal:
docker create -it --name test path
docker start test
docker exec test /bin/sh -c "go test ./..."
docker stop test
docker rm -test
But when I run it as a shell script, the Docker container is neither stopped nor removed.
#!/usr/bin/env bash
set -e
docker create -it --name test path
docker start test
docker exec test /bin/sh -c "go test ./..."
docker stop test
docker rm -test
How can I make it work from within a shell script?
If you use set -e the script will exit when any command fails. i.e. when a commands return code != 0. This means if your start, exec or stop fails, you will be left with a container still there.
You can remove the set -e but you probably still want to use the return code for the go test command as the overall return code.
#!/usr/bin/env bash
docker create -it --name test path
docker start test
docker exec test /bin/sh -c "go test ./..."
rc=$?
docker stop test
docker rm test
exit $rc
Trap
Using set -e is actually quite useful and catches a lot of issues that are silently ignored in most scripts. A slightly more complex solution is to use a trap to run your clean up steps on EXIT, which means set -e can be used.
#!/usr/bin/env bash
set -e
# Set a default return code
RC=2
# Cleanup
function cleanup {
echo "Removing container"
docker stop test || true
docker rm -f test || true
exit $RC
}
trap cleanup EXIT
# Test steps
docker create -it --name test path
docker start test
docker exec test /bin/sh -c "go test ./..."
RC=$?

How to execute commands in docker container as part of bash shell script

I would like to write a bash script that automates the following:
Get inside running container
docker exec -it CONTAINER_NAME /bin/bash
Execute some commands:
cat /dev/null > /usr/local/tomcat/logs/app.log
exit
The problematic part is when docker exec is executed. The new shell is created, but the other commands are not executed.
Is there a way to solve it?
You can use heredoc with docker exec command:
docker exec -i CONTAINER_NAME bash <<'EOF'
cat /dev/null > /usr/local/tomcat/logs/app.log
exit
EOF
To use variables:
logname='/usr/local/tomcat/logs/app.log'
then use as:
docker exec -i CONTAINER_NAME bash <<EOF
cat /dev/null > "$logname"
exit
EOF
You can simply launch
docker exec -it container_id cat /dev/null > /usr/local/tomcat/logs/app.log

Resources