Introduction to Docker
After installing Docker, one can check its version by the following command:
docker version
The output of the above command would be somethign like below:
Client:
Cloud integration: v1.0.25
Version: 20.10.16
API version: 1.41
Go version: go1.17.10
Git commit: aa7e414
Built: Thu May 12 09:20:34 2022
OS/Arch: darwin/arm64
Context: default
Experimental: true
Server: Docker Desktop 4.9.1 (81317)
Engine:
Version: 20.10.16
API version: 1.41 (minimum version 1.12)
Go version: go1.17.10
Git commit: f756502
Built: Thu May 12 09:14:19 2022
OS/Arch: linux/arm64
Experimental: false
containerd:
Version: 1.6.4
GitCommit: 212e8b6fa2f44b9c21b2798135fc6fb7c53efc16
runc:
Version: 1.1.1
GitCommit: v1.1.1-0-g52de29d
docker-init:
Version: 0.19.0
GitCommit: de40ad0
Hello World
We would execute the following command now:
docker run hello-world
Hello from Docker!
For the above command, docker takes the following steps:
The Docker client contacted the Docker daemon.
The Docker daemon pulled the "hello-world" image from the Docker Hub. (arm64v8)
The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
The Docker daemon streamed that output to the Docker client, which sent it to your terminal.
Docker CLI
docker run
The first command we would look in details is the docker run
command. The below figure provides details about this command:

The docker run
command is used for creating and running a container from an image.
Overriding Default Commands
To override the default startup command, the following figure shows how to do it:

For example, following command uses a override command with docker run
:
docker run busybox echo hi there
Output would be:
hi there
Another example is listing out the files and directories within a container:
docker run busybox ls
Output of the above command would be:
bin dev etc home proc
root sys tmp usr var
Now, let's try the echo
and ls
override commands with the hello-world
image with docker run
.
docker run hello-world ls
docker: Error response from daemon: failed to create shim task: OCI runtime create
failed: runc create failed: unable to start container process: exec: "ls": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
docker run hello-world echo hi there
docker: Error response from daemon: failed to create shim task: OCI runtime create
failed: runc create failed: unable to start container process: exec: "echo": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
As we can observe, we get an error for both the commands. This is because inside the hello-world
image file-system, the ls
and echo
programs do not exist. The only thing that exists inside the hello-world
image snaphot file-system is a single program. All this program does is print out the singular message: Hello from Docker!
.
The same commands work with the busybox
image because these programs exist inside the busybox
file-system image.
Listing Running Containers
Next, we will look at a command to list all currently running containers on a local machine.

First of all we will run a container for a meaningful amount of time, like below:
docker run busybox ping google.com
PING google.com (172.217.161.14): 56 data bytes
64 bytes from 172.217.161.14: seq=0 ttl=37 time=11.497 ms
64 bytes from 172.217.161.14: seq=1 ttl=37 time=12.000 ms
64 bytes from 172.217.161.14: seq=2 ttl=37 time=18.183 ms
64 bytes from 172.217.161.14: seq=3 ttl=37 time=13.093 ms
64 bytes from 172.217.161.14: seq=4 ttl=37 time=11.236 ms
Next, we would list the running containers:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b60202284ace busybox "ping google.com" 2 minutes ago Up 2 minutes exciting_tharp
As can be observed from the output of the command, it prints out a bunch of information about the running container.
We can modify the docker ps
command to list all containers created on a local machine like the following:
docker ps --all
Executing the above command will give the output something like below:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b60202284ace busybox "ping google.com" 3 hours ago Exited (0) 3 hours ago exciting_tharp
298176ed2948 hello-world "/hello" 3 hours ago Exited (0) 3 hours ago zen_johnson
38f01afc355f hello-world "echo hi there" 3 hours ago Created distracted_austin
b25255cc9ef7 hello-world "ls" 3 hours ago Created awesome_swirles
b09147ec3aae busybox "ls" 4 hours ago Exited (0) 4 hours ago youthful_wu
ab8b6c0bf713 busybox "echo hi there" 4 hours ago Exited (0) 4 hours ago wonderful_archimedes
9435b6d0c6f7 hello-world "/hello" 5 hours ago Exited (0) 5 hours ago xenodochial_kepler
Container Lifecycle
The docker run
command is actually equivalent to running 2 seperate commands as detailed below:

The docker create
command creates a container while the docker start
command starts a container:

For example, the below command creates a new container using the hello-world
image:
docker create hello-world
43b0148310bad8560734d780be5b7f7aac788b646a046efaa93e50d4558395d9
As can be observed, the docker create
command outputs the id of the container that was created.
Next, we can execute the hello world
command inside of this container using docker start
, like below:
docker start -a 43b0148310bad8560734d780be5b7f7aac788b646a046efaa93e50d4558395d9
Like running the docker run
command, the above command will output the following:
Hello from Docker!
Running docker start
without the -a
arguement does the following:
docker start 43b0148310bad8560734d780be5b7f7aac788b646a046efaa93e50d4558395d9
43b0148310bad8560734d780be5b7f7aac788b646a046efaa93e50d4558395d9
As can be observed above, without the -a
argement, the command returns back the id of the container. The -a
arguement will make docker actually watch for output from the container and print it out on the terminal.
Restarting Stopped Containers
An exited container can be started back again. For example, first we list all the containers created on a machine like below:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
43b0148310ba hello-world "/hello" 16 minutes ago Exited (0) 9 minutes ago serene_poincare
b60202284ace busybox "ping google.com" 3 hours ago Exited (0) 3 hours ago exciting_tharp
298176ed2948 hello-world "/hello" 3 hours ago Exited (0) 3 hours ago zen_johnson
38f01afc355f hello-world "echo hi there" 4 hours ago Created distracted_austin
b25255cc9ef7 hello-world "ls" 4 hours ago Created awesome_swirles
b09147ec3aae busybox "ls" 4 hours ago Exited (0) 4 hours ago youthful_wu
ab8b6c0bf713 busybox "echo hi there" 4 hours ago Exited (0) 4 hours ago wonderful_archimedes
9435b6d0c6f7 hello-world "/hello" 5 hours ago Exited (0) 5 hours ago xenodochial_kepler
Then, let's say we pick the seventh entry (second last) from the list. Using the container id, we can issue the following command to start the container again.
docker start -a ab8b6c0bf713
hi there
One thing to note is that we cannot modify the start command for a container which has been already created. For example,
docker start -a ab8b6c0bf713 echo bye there
you cannot start and attach multiple containers at once
As can be observed, docker misinterprets the command and throws an error.
Removing Stopped Containers
To remove all containers, following is the command:
docker system prune
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all dangling images
- all dangling build cache
Are you sure you want to continue? [y/N] y
Deleted Containers:
43b0148310bad8560734d780be5b7f7aac788b646a046efaa93e50d4558395d9
b60202284acedd38ed38988290017182071b2fc152ab14414dce96435a5ae749
298176ed29480b90d5ac928ec1d8b8c474c9dd04941c4fdf8f7387632a36d670
38f01afc355fc6bdc96dec59b560cfcce81302e8a3939f0e55bf48bafc2a10c7
b25255cc9ef76f1bdd6ca4317f388ebff7890b526f2817292b2dc4264fe7f7a1
b09147ec3aaeb26d8e396564ee2638178048da49b7d0623d40606c77be56bf6b
ab8b6c0bf7138516fd84ccd78c3352515549df6012a90540720437443cf587c6
9435b6d0c6f71a5db9eb23f93a863a33a8b269e2179d1c7ccb71fb36a1899ee5
Total reclaimed space: 0B
As can be observed above, before removing all the stopped containers, docker outputs a warning and requests a confirmation from the user to actually remove the stopped containers.
Retrieving Log Outputs
Another way of getting the output from a container without using the -a
flag with docker start
is using the docker logs
command. Specifically, below is the command to get logs from a container.

Following is the series of command that shows usage of docker logs
command:
docker create busybox echo hi there
1a75b9eec51c364c71d12cfbeb96d3e6adc6789a4551a2de6ae22a72fe3d954c
docker start 1a75b9eec51c364c71d12cfbeb96d3e6adc6789a4551a2de6ae22a72fe3d954c
1a75b9eec51c364c71d12cfbeb96d3e6adc6789a4551a2de6ae22a72fe3d954c
docker logs 1a75b9eec51c364c71d12cfbeb96d3e6adc6789a4551a2de6ae22a72fe3d954c
hi there
Stopping Containers
There are 2 ways of stopping a running container:

Both the above commands are going to stop a running container. While both these commands kind of do the same thing, internally there is a difference between them.
When docker stop
command is issued, a hardware signal SIGTERM is sent to the primary process inside the concerned container. This message tells the container to shutdown on its own time.
On the other hand, the docker kill
command issues a SIGKILL signal to the primary process inside the concerned container. SIGKILL essentially means the conatiner has to shutdown right away without doing any additional work.
Ideally, docker stop
should be used to stop a container. If a container is non-responsive, we can use docker kill
command instead.
One thing to note about the docker stop
command is that, when this command is executed and the concerned container does not stop automatically in 10 seconds, then docker will automatically fall back to executing docker kill
command.
Following is a series of commands which creates and start a busybox container. Then it outputs the logs from the container. Finally, we stop the running container.
docker create busybox ping google.com
d506eaabd695a57e27fcec70f1f3caae1b8f5006e40f668e5c2a95388ce6c793
docker start d506eaabd695a57e27fcec70f1f3caae1b8f5006e40f668e5c2a95388ce6c793
d506eaabd695a57e27fcec70f1f3caae1b8f5006e40f668e5c2a95388ce6c793
docker logs d506eaabd695a57e27fcec70f1f3caae1b8f5006e40f668e5c2a95388ce6c793
PING google.com (172.217.160.238): 56 data bytes
64 bytes from 172.217.160.238: seq=0 ttl=37 time=12.531 ms
64 bytes from 172.217.160.238: seq=1 ttl=37 time=15.300 ms
64 bytes from 172.217.160.238: seq=2 ttl=37 time=18.923 ms
64 bytes from 172.217.160.238: seq=3 ttl=37 time=16.998 ms
64 bytes from 172.217.160.238: seq=4 ttl=37 time=15.382 ms
64 bytes from 172.217.160.238: seq=5 ttl=37 time=16.754 ms
64 bytes from 172.217.160.238: seq=6 ttl=37 time=15.589 ms
64 bytes from 172.217.160.238: seq=7 ttl=37 time=14.521 ms
64 bytes from 172.217.160.238: seq=8 ttl=37 time=13.746 ms
docker stop d506eaabd695a57e27fcec70f1f3caae1b8f5006e40f668e5c2a95388ce6c793
d506eaabd695a57e27fcec70f1f3caae1b8f5006e40f668e5c2a95388ce6c793
Multi-Command Containers
As an illustration, let's start running a new container with redis-server
running inside it. Redis is an in memory data structure store. Following is the command to do so:
docker run redis
Executing Commands in Running Containers
After starting the container using the redis
image, we now need to somehow start-up the the redis-cli
also inside the container. For this, we would use the docker exec
command:

Following is how to run redis-cli
in the started container:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b025f927bfa2 redis "docker-entrypoint.s…" 27 minutes ago Up 27 minutes 6379/tcp flamboyant_sammet
docker exec -it b025f927bfa2 redis-cli
127.0.0.1:6379> set myvalue 5
OK
127.0.0.1:6379> get myvalue
"5"
Command Prompt in a Container
There is another usecase for the docker exec
command which is more commonly used. This usecase is getting shell or terminal access to a running container. In other words, this would be mean running shell commands inside of a container without running docker exec
repeatedly.
Following is the command for this:
docker exec -it b025f927bfa2 sh
# cd /
# ls
bin boot data dev etc home lib media mnt
opt proc root run sbin srv sys tmp usr var
# export b=5
# echo $b
5
# redis-cli
127.0.0.1:6379>
# exit
sh
is a command processor which allows to type commands in and have them be executed inside of that container. There are other command processors as listed below:

Starting a Shell
We can also start a shell via the docker run
command like below:
docker run -it busybox sh
/ # ls
bin dev etc home proc root sys tmp usr var
/ # echo hi there
hi there
/ # exit
One disadvantage of starting the shell via the docker run
command is that it does not allow to run the container's default process when starting up. In practice, generally we start the container and then use the docker exec
command to start a shell within a container.
Last updated