See full command of running/stopped container in Docker - 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>

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 do I inspect the stopped docker container files

Step 1:
docker ps -a
container Id: dd5cf6b519b4
I need to inspect inside the stopped docker container which is cannot start.
I tried with docker exec -it container-id bin/bash But this is for running container.
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
0dfd54557799 ubuntu "/bin/bash" 25 seconds ago Exited (1) 4 seconds ago peaceful_feynman
Commit the stopped image
$ docker commit 0dfd54557799 debug/ubuntu
now we have a new image
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
debug/ubuntu <none> cc9db32dcc2d 2 seconds ago 64.3MB
create a new container from the "broken" image
$ docker run -it --rm --entrypoint sh debug/ubuntu
inside of the container we can inspect - for example, the file system
$ ls /app
App.dll
App.pdb
App.deps.json
You can start container with specific entrypoint
docker run --entrypoint sleep YOUR_IMAGE 3600
It will block current terminal for 3600 seconds. You can open new terminal tab(do not close current one) and you can verify if your container is working with the
docker ps
If you do not want to block current terminal, you can add -d flag to docker run:
docker run -d --entrypoint sleep YOUR_IMAGE 3600
Above command will start docker which will be doing nothing, then you can ssh into the container when it is working with
docker exec -ti CONTAINER HASH sh

Docker ssh, back to container showing unexpected results

I'm studying the Docker documentation, but I'm having a hard time understanding the concept of creating a container, ssh, and ssh back.
I created a container with
docker run -ti ubuntu /bin/bash
Then, it starts the container and I can run commands. docker ps gives me
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0e37da213a37 ubuntu "/bin/bash" About a minute ago Up About a minute keen_sammet
The issue is after I exit the container I can't ssh back.
I tried docker attach that gives me Error: No such container and I tried docker exec -ti <container>/bin/bash that gives me the same message Error: No such container
How do I run and ssh back to the container?
When you exit the bash process, the container exits (in general, a container will exit when the foreground process exits). The error message you are seeing is accurately describing the situation (the container is no longer running).
If you want to be able to docker exec into a container, you will want to run some sort of persistent command. For example, if you were to run:
docker run -ti -d --name mycontainer ubuntu bash
This would start a "detached" container. That means you've started bash, but it's just hanging around doing nothing. You could use docker exec to start a new process in this container:
$ docker exec -it mycontainer ps -fe
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 16:28 pts/0 00:00:00 bash
root 17 0 0 16:28 pts/1 00:00:00 ps -fe
Or:
$ docker exec -it mycontainer bash
There's really no reason to start bash as the main process in this case, since you're not interacting with it. You can just as easily run...
docker run -ti -d --name mycontainer ubuntu sleep inf
...and the behavior would be the same.
The most common use case for all of this is when your docker run command starts up some sort of persistent service (like a web server, or a database server, etc), and then you use docker exec to perform diagnostic or maintenance tasks.
The docker attach command will re-connect you with the primary console of a detached container. In other words, if we return to the initial example:
docker run -ti -d --name mycontainer ubuntu bash
You could connect to that bash process (instead of starting a new one) by running:
docker attach mycontainer
At this point, exit would cause the container to exit.
First, you don't ssh to a docker container (unless you have a sshd process in that container). But you can execute a command with docker exec -ti mycontainer bash -l
But you can exec a command only on running container. If the container exited already you must use another approach : create an image from the container and run a new one.
Here is an example. First I create a container and create a file within then I exit it.
$ docker run -ti debian:9-slim bash -l
root#09f889e80153:/# echo aaaaaaaaaa > /zzz
root#09f889e80153:/# cat /zzz
aaaaaaaaaa
root#09f889e80153:/# exit
logout
As you can see the container is exited (Exited (0) 24 seconds ago)
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
09f889e80153 debian:9-slim "bash -l" 45 seconds ago Exited (0) 24 seconds ago thirsty_hodgkin
So I create a new image with docker commit
$ docker commit 09f889e80153 bla
sha256:6ceb88470326d2da4741099c144a11a00e7eb1f86310cfa745e8d3441ac9639e
So I can run a new container that contains previous container content.
$ docker run -ti bla bash -l
root#479a0af3d197:/# cat zzz
aaaaaaaaaa

Shell into swarm container

I'm unable to connect to a container that's running on a swarm. Seems like the following doesn't work:
docker exec -it <container_ID> bash
Here is some output:
>$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
4rliefwe74o5 login 1/1 login-arm64:1.0
>$ docker service ps login
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
2jk3s2xs7ce62piunbkiptypz login.1 login-arm64:1.0 odroid64-cluster4 Running Running 5 minutes ago
Then I'll run:
$ docker exec -it 2jk3s2xs7ce62piunbkiptypz bash
or
$ docker exec -it login.1 bash
and see the following errors
Error response from daemon: No such container: 2jk3s2xs7ce62piunbkiptypz
Error response from daemon: No such container: login.1
Use docker ps to find the names you can use. Look under both CONTAINER ID and NAMES, either will work.
>$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e53bff8bebfc login-arm64:1.0 "/bin/sh -c 'node ser" 27 seconds ago Up 25 seconds login.1.cg7fltcu3wfe7ixtnqzg8myy1
>$ docker exec -it e53bff8bebfc bash
root#e53bff8bebfc:/#
The long name is of the form $SERVICE_NAME.$REPLICA_NUMBER.$ID_FROM_SERVICE_PS
>$ docker exec -it login.1.cg7fltcu3wfe7ixtnqzg8myy1 bash
root#e53bff8bebfc:/#
Quite an older question, but just my two cents here: I very often run:
docker exec -it $(docker ps -q -f name="login*") sh
-q only returns the container id
-f name="login*" applies a filter based on container name, using a regex
This comes in handy because starting a new container will change the container name with some random characters in it. It's important that your filter returns just 1 container, so specify the name in a way that there will be just 1 result. For example: if you have a container "monster" and a container "monitor", you need -f name="moni*" to exclude the "monster" container.
The command will result in something like:docker exec -it login.1.cg7fltcu3wfe7ixtnqzg8myy1 sh

Docker look at the log of an exited container

Is there any way I can see the log of a container that has exited?
I can get the container id of the exited container using docker ps -a but I want to know what happened when it was running.
Use docker logs. It also works for stopped containers and captures the entire STDOUT and STDERR streams of the container's main process:
$ docker run -d --name test debian echo "Hello World"
02a279c37d5533ecde76976d7f9d1ca986b5e3ec03fac31a38e3dbed5ea65def
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
49daa9d41a24 debian "echo test" 2 minutes ago Exited (0) 2 minutes ago test
$ docker logs -t test
2016-04-16T15:47:58.988748693Z Hello World
docker logs --tail=50 <container id> for the last fifty lines - useful when your container has been running for a long time.
You can use below command to copy logs even from an exited container :
docker cp container_name:path_of_file_in_container destination_path_locally
Eg:
docker cp sample_container:/tmp/report /root/mylog
To directly view the logfile of an exited container in less, scrolled to the end of the file, I use:
docker inspect $1 | grep 'LogPath' | sed -n "s/^.*\(\/var.*\)\",$/\1/p" | xargs sudo less +G
run as ./viewLogs.sh CONTAINERNAME
This method has the benefit over docker logs based approaches, that the file is directly opened, instead of streamed.
sudo is necessary, as the LogPath/File usually is under root-owned
#icyerasor comment above actually helped me solve the issue. In my particular situation the container that has stopped running had no container name only container id.
Steps that found the logs also listed in this post
Find the stopped container via docker ps -a
grab the container id of the failed container
Substitute it in this command cat /var/lib/docker/containers/<container id>/<container id>-json.log

Resources