Running a docker logs command in background remotely over ssh - linux

We have a use case where the docker remote execution is seperately executed on another server.
so users login to server A and submt an ssh command which runs a script on remote server B.
The script performs several docker commands like prune,build,run which are working fine.
I have this command at the end of the script which is supposed to write the docker logs in background to an efs file system which is mounted on both
servers A and B.This way users can access the logfile from server A without actually logging into server B (to prevent access to containers).
I have tried all available solutions related to this and nothing seems to be working for running a process in background remotely.
Any help is greatly appreciated.
The below code is the script on remote server.user calls this script from server A over ssh like ssh id#serverB-IP docker_script.sh
loc=${args[0]}
cd $loc
# Set parameters
imagename=${args[1]}
port=${args[2]}
desired_port=${args[3]}
docker stop $imagename && sleep 10 || true
docker build -t $imagename $loc |& tee build.log
docker system prune -f
port_config=$([[ -z "${port}" ]] && echo '' || echo -p $desired_port:$port)
docker run -d --rm --name $imagename $port_config $imagename
sleep 10
docker_gen_log $loc $imagename
echo ""
echo "Docker build and run are now complete ....Please refer to the logs under $loc/build.log $loc/run.log"
}
docker_gen_log(){
loc=${args[0]}
cd $loc
imagename=${args[1]}
docker logs -f $imagename &> run.log &
}

If you're only running a single container like you show, you can just run it in the foreground. The container logs will go to the docker run stdout/stderr and you can collect them normally.
docker run --rm --name "$imagename" $port_config "$imagename" \
> "$loc/run.log" 2>&1
# also note no `-d` option
echo ""
echo "Docker build and run are now complete ....Please refer to the logs under $loc/build.log $loc/run.log"
If you have multiple containers, or if you want the container to keep running if the script disconnects, you can collect logs at any point until the container is removed. For this sort of setup you'd want to explicitly docker rm the container.
docker run -d --name "$imagename" $port_config "$imagename"
# note, no --rm option
docker wait "$imagename" # actually container name
docker logs "$imagename" >"$loc/run.log" 2>&1
docker rm "$imagename"
This latter approach won't give you incremental logs while the container is running. Given that your script seems to assume the container will be finished within 10 seconds that's probably not a concern for you.

Related

Can an Azure Machine Learning Compute Instance shut down itself automatically with a bash script executed by crontab?

I have a compute instance that starts at 12:00 with the scheduler of Azure ML and does a job scheduled in the crontab of the CI at 12:10. The thing is that this job doesn't always takes the same time to finish. So i want the CI to shut down itself when done.
The script that the crontab executes is the following:
---------------------------------------------------------
#!/bin/bash
...
# CRREATE FOLDER FOR LOGS
foldername=$PROJECT_PATH/$(date '+%d_%m_%Y_%H_%M_%S')
mkdir $foldername
filename=az_login.txt
path=$foldername/$filename
touch $path
az login -u *<USERNAME>* -p *<PASSWORD>* > $path
filename=acr_login.txt
path=$foldername/$filename
touch $path
# Authenticate to ACR
az acr login --name $ACR_NAME > $path
filename=pull_container.txt
path=$foldername/$filename
touch $path
# Pull the container image from ACR
docker pull $ACR_NAME.azurecr.io/$IMAGE_NAME:$IMAGE_TAG > $path
filename=run.txt
path=$foldername/$filename
touch $path
# Run the container image
docker run -v $CREDENTIALS_PATH:/app/config_privilegies $ACR_NAME.azurecr.io/$IMAGE_NAME:$IMAGE_TAG > $path
filename=rm_container.txt
path=$foldername/$filename
touch $path
# Delete the exited containers
docker rm $(docker ps -a -q --filter "status=exited") > $path
az ml compute stop --name *<CI_NAME>* --resource-group *<RESOURCE_NAME>* --workspace-name *<WORKSPACE_NAME>* --subscription *<SUBSCRIPTION_NAME>*
Everything works great until the stop command. In this particular code, it does nothing.
I've tried to put the last command in a seperate bash script and changing the last line for "./close_ci.sh". However, this doesn't work either, it restarts the CI instead of stopping it.

docker logs within a bash script doesn't work

I'm experimenting a weird behaviour of Docker in a bash script.
Let's see these two examples:
logs-are-showed() {
docker rm -f mybash &>/dev/null
docker run -it --rm -d --name mybash bash -c "echo hello; tail -f /dev/null"
docker logs mybash
}
# usage:
# $ localtunnel 8080
localtunnel() {
docker rm -f localtunnel &>/dev/null
docker run -it -d --network host --name localtunnel efrecon/localtunnel --port $1
docker logs localtunnel
}
In the first function logs-are-showed the command docker logs returns me the logs of the container mybash
In the second function localtunnel the command docker logs doesn't return me anything.
After having called the localtunnel function, if I ask for the container logs from outside the script, it shows me the logs correctly.
Why does this happen?
Processes take time to react. They may be no logs right after starting a process - it has not written anything yet. Wait a bit.

How to retain docker alpine container after "exit" is used?

Like for example if I use command docker run -it alpine /bin/sh
it starts a terminal after which I can install packages and all. Now when I use exit command it goes back to the terminal. (main one)
So how can I access the same container again?
When I run that command again, I get a fresh alpine.
Please help
The container lives as long as the specified run command process is still running. When you specify to run /bin/sh, once you exit, the sh process will die and so will you container.
If you want to keep your container running, you have to keep the process inside running. For your case (I am not sure what you want to acheive, I assume you are just testing), the following will keep it running
docker run -d --name alpine alpine tail -f /dev/null
Then you can sh into the container using
docker exec -it alpine sh
Pull an image
docker image pull alpine
See that image is there
docker image ls OR just docker images
see what is inside the alpine
docker run alpine ls -al
Now your question is how to stay with the shell
docker container run -it alpine /bin/sh
You are inside shell script command line. Some distribution may have bash shell.
docker exec -it 5f4 sh
/ # (<-- you can run linux command here!)
At this point, you can use command line of alpine and do
ls -al
type exit to come out-
You can run it in detached mode and it will keep running.
With exec command we can login again
docker container run -it -d alpine /bin/sh
verify that it is UP and copy the FIRST 2 -3 digits of the container ID
docker container ls
login with exec command
docker exec -it <CONTAINER ID or just 2-3 digits> sh
You will need to STOP otherwise it will keep running.
docker stop <CONTAINER ID>
Run Alpine in background
$ docker run --name alpy -dit alpine
$ docker ps
Attach to Alpine
$ docker attach alpy
You should use docker start, which allows you to start a stopped container. If you didn't name your container, you'll need to get it's name/id using docker ps.
For example,
$docker ps
CONTAINER ID IMAGE COMMAND
4c01db0b339c alpine bash
$docker start -i -a 4c01db0b339c
What you should do is below
docker run -d --name myalpine alpine tail -f /dev/null
This would make sure that your container doesn't die. Now whenever you need to install packages inside you just get inside the container using sh
docker exec -it myalpine /bin/sh
If for some reason your container dies, you can still start it again using
docker start myalpine

Issue shell commands on the remote server from local machine

The following command issued on a Mac terminal is failing the docker command on the remote shell.
However it works if I log in to the server and issue the command there with replacing ";" with "&&"
ssh -i "myKey.pem" user#host ‘docker stop $(docker ps -a -q --filter ancestor=name/kind); docker rm $(docker ps -a -q --filter ancestor=name/kind); docker rmi name/kind; docker build -t name/kind .; sudo docker run -it -d -p 80:80 name/kind’
Cannot connect to the Docker daemon. Is the docker daemon running on this host?
I need to run this command form the local terminal because if is part of bigger command which first build the project locally and scp it to the server.
`$bigger-command && then-the-ssh-as-shown-above.
How do I go about it? Thanks
The best way to pass very complex commands to ssh is the create a script on the server side.
If you need to pass some parameters, proceed this way:
create a .sh file on your localhost
scp it to your remote host
run `ssh user#remotehost 'bash scriptfile.sh'
This should do the trick without giving you headaches about escapement.

Docker container does not give me a shell

I am trying to get a shell inside the Docker container moul/phoronix-test-suite on Docker Hub using this command
docker run -t -i moul/phoronix-test-suite /bin/bash
but just after executing the command (binary file), the container stops and I get no shell into it.
[slazer#localhost ~]$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0993189463e6 moul/phoronix-test-suite "phoronix-test-suite " 7 seconds ago Exited (0) 3 seconds ago kickass_shockley
It is a ubuntu:trusty container. How can I get a shell into it, so that I can send arguments to the command phoronix-test-suite?
docker run -t -i moul/phoronix-test-suite /bin/bash will not give you a bash (contrary to docker run -it fedora bash)
According to its Dockerfile, what it will do is execute
phoronix-test-suite /bin/bash
Meaning, it will pass /bin/bash as parameter to phoronix-test-suite, which will exit immediately. That leaves you no time to execute a docker exec -it <container> bash in order to open a bash in an active container session.
Have you tried restarting your docker? It might need to restart or even reboot the host.

Resources