How to stop a container harmless? - docker

I use docker container stop xxx. It will cause jenkins fail if docker container xxx is not existed.
I want to know if there is an argument to stop a container without failing.It means when container exists, delete it, otherwise do nothing.

use this :
docker stop CONTAINER_NAME 2> /dev/null || true
will always give you exit code 0

You can use the below command :
docker container ps -all --filter "id=XXXXXX" --format {{.ID}} |xargs --no-run-if-empty docker container stop
Explanation :
docker container ps -all: This command will list all the containers.
docker container ps -all --filter "id=XXXXXX": This command will list the container with container id = XXXXXX.
docker container ps -all --filter "id=XXXXXX" --format {{.ID}} : This command will only print out the container id.
We will use this container id to pass it to the xargs command to run the docker container stop.
xargs --no-run-if-empty docker container stop: This command will stop docker container only if command before "|" (pipe) is non-empty.

You can manage in a simple way as mentioned below:
docker stop XXXX || true && docker rm XXXX || true
This will return true in either case and it will move out with success.
Reference in details at : stop and delete docker container if its running

Related

How can a script check if a particular Docker container is running?

I would like to have a shell script that checks if a particular container is running.
For example, I might want to start the container if it's not already running, or query some piece of information about it like what ports are exposed.
The docker ps command takes a -f / --filter option to locate the desired container. To test if the container is running by name we might try
$ docker ps --filter "name=myapp" --filter "status=running"
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
91959ed76e77 foo/barbaz:latest "/init" 10 minutes ago Up 10 minutes myapp
If we just want the container ID, because we're going to pass it to another command like docker exec, we can use -q / --quiet:
$ docker ps --filter "name=myapp" --filter "status=running" --quiet
91959ed76e77
To just check whether it is running, we can see if the output is non-empty:
if [ -n "$(docker ps -f "name=myapp" -f "status=running" -q )" ]; then
echo "the container is running!"
fi
Or if we want some other piece of information about it, --format:
$ docker ps -f "name=myapp" -f "status=running" --format "{{.Image}}"
foo/barbaz:latest
You might also try using the docker inspect command which works well with myapp as the container's name ... or the container's id :
if [ "$(docker inspect myapp --format '{{.State.Status}}')" = "running" ]; then
echo "the container is running!"
fi

How to correct docker in makefile which requires at least 1 argument for remove all containers command

The docker command "docker container rm $(docker ps -aq) -f" works fine from the command line. However, when I try to run it from a makefile using the following target ("remove_all_containers")...
remove_all_containers:
docker container rm $(docker ps -aq) -f
I get the error message:
host_name$ make remove_all_containers
docker container rm -f
"docker container rm" requires at least 1 argument.
See 'docker container rm --help'.
Usage: docker container rm [OPTIONS] CONTAINER [CONTAINER...]
Remove one or more containers
make: *** [remove_all_containers] Error 1
Clearly, when executed from within the makefile, the "docker ps" command is not being properly being properly executed in a way where its results can be collected and passed into the "container rm" command.
My Question: How do I get the "docker ps" command to run correctly from within the makefile and pass its results correctly into the "docker rm" command, also within the makefile?
Thanks, in advance, for any assistance you can offer.
You need a second $ in your recipe:
remove_all_containers:
docker container rm $$(docker ps -aq) -f
# ^
The single $ is expanded as a makefile variable when the makefile is parsed. It expands to blank. Make therefore passes docker container rm -f to your shell. The second $ sign causes make to expand $$ to $, and it will pass docker container rm $(docker ps -aq) -f to bash, which I'm guessing is what you want.
Notice, if you put the shell in there as #EricMd proposed, it will run a shell command, but that command will be run at Makefile read time, as opposed to the time that the recipe is executed. If the docker ps -aq command is dependent on any other artifacts of your build it would not work.
Sounds like you don't have any containers in docker to remove. I sometimes use a different syntax for this scenario:
remove_all_containers:
docker container ls -aq | xargs --no-run-if-empty docker container rm -f
The xargs syntax will not run docker container rm if there are no containers to delete.
According to the documentation, docker ps -a should list all containers.
You obtained this message "docker container rm" requires at least 1 argument certainly because you forgot to prepend the command at stake with Make's shell builtin:
remove_all_containers:
docker container rm $(shell docker ps -aq) -f
Note also that the docker ps admits a filtering feature: the online doc describes the various flavors of the corresponding -f flag.
For example, below are three Bash alias examples that can be useful to (i) stop all containers, (ii) remove all stopped containers; and (iii) remove dangling images−that would be tagged as <none> when doing docker images ls:
alias docker-stop='docker stop $(docker ps -a -q)'
alias docker-clean='docker rm $(docker ps -a -q -f status=exited)'
alias docker-purge='docker rmi $(docker images -q -f dangling=true)'
I tested for 2 way follow bellow answer:
remove_all_containers:
docker container rm $$(docker ps -aq) -f
remove_all_containers:
docker container rm $(shell docker ps -aq) -f

Stop all docker containers at once on Windows

How can I stop all docker containers running on Windows?
docker stop is for 1 container only.
Any command/script to make it stop all containers?
You could create a batch-file (.bat or .cmd) with these commands in it:
#ECHO OFF
FOR /f "tokens=*" %%i IN ('docker ps -q') DO docker stop %%i
If you want to run this command directly in the console, replace %%i with %i, like:
FOR /f "tokens=*" %i IN ('docker ps -q') DO docker stop %i
In Git Bash or Bash for Windows you can use this Linux command:
docker stop $(docker ps -q)
Note: this will fail if there are no containers running
For PowerShell, the command is very similar to the Linux one:
docker ps -q | % { docker stop $_ }
For those who are interested this can be accomplished in Powershell using
docker ps -q | % { docker stop $_ }
In PowerShell, you could also use this syntax
docker container stop $(docker container list -q)
If the motivation of the question is to recover the memory occupied by Docker (in my case, this was why I arrived at this page), I found that the only way was to stop Docker Desktop completely. You do that by right-clicking the whale icon in the notification area (bottom right) > Quit Docker Desktop.
When you restart Docker Desktop, all the containers reappear, and Docker even sets them to up again automatically.
My two cents.
If you want to stop them filtered by some criteria
docker ps -a -q --filter "name=container_name" --format="{{.ID}}" | ForEach-Object -Process {docker stop $_ }
or if you want to stop and remove them all together
docker ps -a -q --filter "name=container_name" --format="{{.ID}}" | ForEach-Object -Process {docker rm $_ -f}
By using pipe and foreach I avoid the error returned when there are no containers of this kind on the specific machine because docker stop or docker rm require at least one argument.
This script is used with combination of
docker container run image_tag --name=container_name
in order to use the filter later on when you want to stop and remove the containers.
docker stop $(docker ps -aq)
to stop all running containers.
docker rm $(docker ps -aq)
to delete all containers.

single command to stop and remove docker container

Is there any command which can combine the docker stop and docker rm command together ? Each time I want to delete a running container, I need to execute 2 commands sequentially, I wonder if there is a combined command can simplify this process.
docker stop CONTAINER_ID
docker rm CONTATINER_ID
You can use :
docker rm -f CONTAINER_ID
It will remove the container even if it is still running.
https://docs.docker.com/engine/reference/commandline/rm/
You can also run your containers with --rm option (e.g. docker run --rm -it alpine), it will be automatically removed when stopped.
https://docs.docker.com/engine/reference/run/#clean-up---rm
Edit: The rm -f might be dangerous for your data and is best suited for test or development containers. #Bernard's comment on this subject is worth reading.
docker stop CONTAINER_ID | xargs docker rm
You can stop and remove the container with a single command the $_ gives you the last echo
docker stop CONTAINER && docker rm $_
In my case, to remove the running containers I used
docker rm -f $(docker ps -a -q)
In case you also need to remove the images, then run
docker rmi $(docker images -q) afterwards.
Only run docker rmi $(docker images -q) if you want to remove the images.
https://www.ctl.io/developers/blog/post/gracefully-stopping-docker-containers/
You can use kill, and also by using rm and the force flag it will also use kill.
Remove all containers: docker ps -aq | xargs docker rm -f
This will stop and remove all images including running containers as we are using -f
docker rmi -f $(docker images -a -q)
Use the docker ps command with the -a flag to locate the name or ID of the containers you want to remove
docker ps -a
To remove: $ docker rm ID_or_Name ID_or_Name
Remove a container upon exit:
If you know when you’re creating a container that you won’t want to keep it around once you’re done, you can run docker run --rm to automatically delete it when it exits.
Run and Remove : docker run --rm image_name
Remove all exited containers:
You can locate containers using docker ps -a and filter them by their status: created, restarting, running, paused, or exited. To review the list of exited containers, use the -f flag to filter based on status. When you've verified you want to remove those containers, using -q to pass the IDs to the docker rm command.
List:
docker ps -a -f status=exited
docker rm $(docker ps -a -f status=exited -q)
Remove containers using more than one filter:
Docker filters can be combined by repeating the filter flag with an additional value. This results in a list of containers that meet either condition. For example, if you want to delete all containers marked as either Created (a state which can result when you run a container with an invalid command) or Exited, you can use two filters:
docker ps -a -f status=exited -f status=created
Stop and Remove all the containers:
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
For removing a single container
docker rm -f CONTAINER_ID
For removing all containers
docker rm -f `docker container ps -qa`
To remove all stopped containers docker system prune
To stop live container, docker stop CONTAINER_ID waits 10 sec and it calls docker kill CONTAINER_ID
Or with docker kill CONTAINER_ID, you can immediately stop the container
remove all container with xargs
docker ps -a -q | xargs docker rm
for stop all
sudo docker ps -a -q |sudo xargs docker stop
remove single container
docker rm -f <container_id>

See full command of running/stopped container in Docker

How can I see the full command of a running container/process in Docker?
$ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b6291859b61 nginx:1.7.8 "nginx -g 'daemon of 4 minutes ago Exited (0) 4 minutes ago thirsty_brattain
I can only see "nginx -g 'daemon of".. here, not the full command.
docker ps --no-trunc will display the full command along with the other details of the running containers.
Use:
docker inspect -f "{{.Name}} {{.Config.Cmd}}" $(docker ps -a -q)
... it does a "docker inspect" for all containers.
Use:
docker inspect -f "{{.Path}} {{.Args}} ({{.Id}})" $(docker ps -a -q)
That will display the command path and arguments, similar to docker ps.
Moving Dylan's comment into a full-blown answer because TOO USEFUL:
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike YOUR-CONTAINER
What does it do? Runs https://github.com/lavie/runlike inside a container, gets you the complete docker run command, then removes the container for you.
TL-DR
docker ps --no-trunc and docker inspect CONTAINER provide the entrypoint executed to start the container, along the command passed to, but that may miss some parts such as ${ANY_VAR} because container environment variables are not printed as resolved.
To overcome that, docker inspect CONTAINER has an advantage because it also allow to retrieve separately env variables and their values defined in the container from the Config.Env property.
docker ps and docker inspect provide information about the executed entrypoint and its command. Often, that is a wrapper entrypoint script (.sh) and not the "real" program started by the container. To get information on that, requesting process information with ps or /proc/1/cmdline help.
1) docker ps --no-trunc
It prints the entrypoint and the command executed for all running containers.
While it prints the command passed to the entrypoint (if we pass that), it doesn't show value of docker env variables (such as $FOO or ${FOO}).
If our containers use env variables, it may be not enough.
For example, run an alpine container :
docker run --name alpine-example -e MY_VAR=/var alpine:latest sh -c 'ls $MY_VAR'
When use docker -ps such as :
docker ps -a --filter name=alpine-example --no-trunc
It prints :
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b064a6de6d8417... alpine:latest "sh -c 'ls $MY_VAR'" 2 minutes ago Exited (0) 2 minutes ago alpine-example
We see the command passed to the entrypoint : sh -c 'ls $MY_VAR' but $MY_VAR is indeed not resolved.
2) docker inspect CONTAINER
When we inspect the alpine-example container :
docker inspect alpine-example | grep -4 Cmd
The command is also there but we don't still see the env variable value :
"Cmd": [
"sh",
"-c",
"ls $MY_VAR"
],
In fact, we could not see interpolated variables with these docker commands.
While as a trade-off, we could display separately both command and env variables for a container with docker inspect :
docker inspect alpine-example | grep -4 -E "Cmd|Env"
That prints :
"Env": [
"MY_VAR=/var",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"sh",
"-c",
"ls $MY_VAR"
]
A more docker way would be to use the --format flag of docker inspect that allows to specify JSON attributes to render :
docker inspect --format '{{.Name}} {{.Config.Cmd}} {{ (.Config.Env) }}' alpine-example
That outputs :
/alpine-example [sh -c ls $MY_VAR] [MY_VAR=/var PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin]
3) Retrieve the started process from the container itself for running containers
The entrypoint and command executed by docker may be helpful but in some cases, it is not enough because that is "only" a wrapper entrypoint script (.sh) that is responsible to start the real/core process.
For example when I run a Nexus container, the command executed and shown to run the container is "sh -c ${SONATYPE_DIR}/start-nexus-repository-manager.sh".
For PostgreSQL that is "docker-entrypoint.sh postgres".
To get more information, we could execute on a running container
docker exec CONTAINER ps aux.
It may print other processes that may not interest us.
To narrow to the initial process launched by the entrypoint, we could do :
docker exec CONTAINER ps -1
I specify 1 because the process executed by the entrypoint is generally the one with the 1 id.
Without ps, we could still find the information in /proc/1/cmdline (in most of Linux distros but not all). For example :
docker exec CONTAINER cat /proc/1/cmdline | sed -e "s/\x00/ /g"; echo
If we have access to the docker host that started the container, another alternative to get the full command of the process executed by the entrypoint is :
: execute ps -PID where PID is the local process created by the Docker daemon to run the container such as :
ps -$(docker container inspect --format '{{.State.Pid}}' CONTAINER)
User-friendly formatting with docker ps
docker ps --no-trunc is not always easy to read.
Specifying columns to print and in a tabular format may make it better :
docker ps --no-trunc --format "table{{.Names}}\t{{.CreatedAt}}\t{{.Command}}"
Create an alias may help :
alias dps='docker ps --no-trunc --format "table{{.Names}}\t{{.CreatedAt}}\t{{.Command}}"'
Use runlike from git repository https://github.com/lavie/runlike
To install runlike
pip install runlike
As it accept container id as an argument so to extract container id use following command
docker ps -a -q
You are good to use runlike to extract complete docker run command with following command
runlike <docker container ID>

Resources