bash script hangs wihout obvious reason - shell

I've got this bash script that builds a Docker image and kicks off a set of tests on it:
#!/bin/bash
fails=''
inspect() {
if [ $1 -ne 0 ]; then
fails="${fails} $2"
fi
}
docker-compose up -d --build
docker-compose exec -T users python manage.py test
inspect $? users
docker-compose exec -T users flake8 project
inspect $? users-lint
docker-compose exec -T client npm test -- --coverage
inspect $? client
docker-compose down
docker-compose -f docker-compose-prod.yml up -d --build
docker-compose -f docker-compose-prod.yml exec -T users python manage.py recreate_db
./node_modules/.bin/cypress run --config baseUrl=http://localhost
inspect $? e2e
docker-compose -f docker-compose-prod.yml down
if [ -n "${fails}"]; then
echo "Test failed: ${fails}"
exit 1
else
echo "Tests passed !"
exit 0
fi
but it won't exit out when finished. It just hangs. What can I do to troubleshoot this ?

Related

Iterating bash commands inside docker container

I am a beginner to Docker and was trying to optimize the following bash shell code. The below code continuously has to create a docker container and remove it. What I would like is a one-time creation of the docker container; then based on the if-else condition, the corresponding command gets iteratively executed in while loop and finally, the docker container gets deleted. I have tried to play around with docker entrypoint commands but all of them seem to insist on a single line command with docker run. Some help will be deeply appreciated! Thanks!
#!/bin/bash
FILE=$1
flag=1
while read line; do
#echo $line
#echo $flag
if [ $flag -gt 0 ] && [ $flag -lt 23189 ]; then
docker run --rm -v $(pwd):/eric -w /eric --entrypoint /bin/sh fedora -c "dnf info $line | tee -a manifest-fed:Core.txt; dnf repoquery --srpm $line"
((++flag))
elif [ $flag -gt 23188 ] && [ $flag -lt 46379 ]; then
docker run --rm -v $(pwd):/eric -w /eric --entrypoint /bin/sh fedora -c "dnf info $line | tee -a manifest-fed:Old.txt; dnf info $line"
((++flag))
elif [ $flag -gt 46378 ] && [ $flag -lt 69571 ]; then
docker run --rm -v $(pwd):/eric -w /eric --entrypoint /bin/sh fedora -c "dnf info $line | tee -a manifest-fed:Graphics.txt"
((++flag))
fi
done<"$1"
Create container in detached mode:
docker run -d -t --rm --name my_container -v $(pwd):/eric -w /eric fedora
Run your commands in this container:
docker exec my_container sh -c "echo test"
You may wrap those commands in a single script and put it in your pwd mapped to '/eric' volume. And then execute them something like:
docker run --rm -v $(pwd):/eric -w /eric --entrypoint /bin/sh fedora -c "/eric/dnf-info.sh 1 '$line'"
Script dnf-info.sh may be:
#! /bin/sh
case $1 in
1)
dnf info "$2" | tee -a manifest-fed:Core.txt; dnf repoquery --srpm "$2"
;;
2)
dnf info "$2" | tee -a manifest-fed:Old.txt; dnf info "$2"
;;
3)
dnf info "$2" | tee -a manifest-fed:Graphics.txt
;;
esac

Install nvm inside Docker using bash as source for Docker's commands

When using bash to execute "docker exec" commands, I am trying to install nvm inside the Docker container. Those are the following commands inside the bash script:
Update:
I've added the whole script.
#!/bin/bash
ubuntu_version="ubuntu:$1"
node_version=$2
container_name="ubuntu_container"
green=`tput setaf 2`
reset=`tput sgr0`
red=`tput setaf 1`
echo "${green}Pulling Ubuntu version: $ubuntu_version ${reset}"
docker pull $ubuntu_version
echo "${green}Running Ubuntu in background...${reset}"
# Stop and remove an existing docker container
docker stop $container_name
docker rm $container_name
docker run -d --name $container_name --rm $ubuntu_version sleep inf
echo "${green}Updating Ubuntu...${reset}"
docker exec $container_name apt update
docker exec $container_name apt upgrade
echo "${green}Installing curl${reset}"
docker exec $container_name apt install -y curl
echo "${green}Installing nvm: ${red}$node_version${reset}"
docker exec -it $container_name bash -c "curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash"
docker exec $container_name bash -c ". ~/.bashrc; nvm"
This leads to the following output:
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 15037 100 15037 0 0 54481 0 --:--:-- --:--:-- --:--:-- 54481
=> Downloading nvm as script to '/root/.nvm'
=> Appending nvm source string to /root/.bashrc
=> Appending bash_completion source string to /root/.bashrc
=> Close and reopen your terminal to start using nvm or run the following to use it now:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "nvm": executable file not found in $PATH: unknown
Seems like nvm is either not in the path or not installed. What am I missing here?
The problem is with the third docker exec.
You have two options
Run :
docker exec -it test_container bash
in bash session, you can run nvm
Or
Run :
docker exec test_container bash -c '. ~/.bashrc; nvm'
Update
Regarding 1), I thought(wrongly) you were running your docker exec manually.
Regarding 2), save follwoing in test.sh :
#!/bin/bash
docker run -d --name test_container2 --rm node sleep inf
docker exec test_container2 apt install -y curl
docker exec -it test_container2 bash -c "curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash"
docker exec test_container2 bash -c '. ~/.bashrc; nvm'
and run bash test.sh
When I run it, I don't have nvm: command not found
Update 2
Your version of ~/.bashrc contains a test on $PS1, so a workaround, change the last line to :
docker exec $container_name bash -c "PS1=x; . ~/.bashrc; nvm"

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 docker-compose run in windows?

How to use this command in windows 10 familly :
docker-compose run api composer install --no-interaction
Example:
docker-compose run api composer install --no-interaction
- Interactive mode is not yet supported on Windows.
Please pass the -d flag when using `docker-compose run`.
Is it possible ?
Do you have an example ?
The interactive mode support for docker-compose on Windows is tracked by issue 2836 which proposes some alternatives:
Use bash from within the container:
docker exec -it MY_CONTAINER bash
Use a docker-compose-run script by Rodrigo Baron:
Script ( put the function in ~/.zshrc or ~/.bashrc in a Windows git bash shell for instance):
#!/bin/bash
function docker-compose-run() {
if [ "$1" = "-f" ] || [ "$1" = "--file" ] ; then
docker exec -i $(docker-compose -f $2 ps $3 |grep -m 1 $3 | cut -d ' ' -f1) "${#:4}"
else
docker exec -i $(docker-compose ps $1 | grep -m 1 $1 | cut -d ' ' -f1) "${#:2}"
fi
}
docker-compose-run "$#"
Usage:
usage:
docker-compose-run web rspec
# or:
docker-compose-run -f docker-compose.development.yml web rspec
Simpler alternative is to use option -d and to get logs
docker-compose run -rm <service> <command>
is replaced by:
docker-compose-run <service> <command>
For this to work, add this snippet in your ~/.bashrc :
docker-compose-run() {
CONTAINER_NAME=$(docker-compose run -d $#)
docker logs -f $CONTAINER_NAME
docker rm $CONTAINER_NAME
}

How to detect fully interactive shell in bash from docker?

I'm wanting to detect in "docker run" whether -ti has been passed to the entrypoint script.
docker run --help for -t -i
-i, --interactive=false Keep STDIN open even if not attached
-t, --tty=false Allocate a pseudo-TTY
I have tried the following but even when tested locally (not inside docker) it didn't work and printed out "Not interactive" always.
#!/bin/bash
[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'
entrypoint.sh:
#!/bin/bash
set -e
if [ -t 0 ] ; then
echo "(interactive shell)"
else
echo "(not interactive shell)"
fi
/bin/bash -c "$#"
Dockerfile:
FROM debian:7.8
COPY entrypoint.sh /usr/bin/entrypoint.sh
RUN chmod 755 /usr/bin/entrypoint.sh
ENTRYPOINT ["/usr/bin/entrypoint.sh"]
CMD ["/bin/bash"]
build the image:
$ docker build -t is_interactive .
run the image interactively:
$ docker run -ti --rm is_interactive "/bin/bash"
(interactive shell)
root#dd7dd9bf3f4e:/$ echo something
something
root#dd7dd9bf3f4e:/$ echo $HOME
/root
root#dd7dd9bf3f4e:/$ exit
exit
run the image not interactively:
$ docker run --rm is_interactive "echo \$HOME"
(not interactive shell)
/root
$
This stackoverflow answer helped me find [ -t 0 ].

Resources