Lab: Getting Started with Docker Operations
In this chapter, we are going to learn about docker shell, the command line utility and how to use it to launch containers. We will also learn what it means to run a container, its lifecycle and perform basic operations such as creating, starting, stopping, removing, pausing containers and checking the status etc.
Using docker cli
We can use docker cli to interact with docker daemon. Various functions of docker command is given below. Try this yourself by runnig $sudo docker command
docker
[Output]
Usage: docker [OPTIONS] COMMAND [arg...]
docker [ --help | -v | --version ]
A self-sufficient runtime for containers.
Options:
--config=~/.docker Location of client config files
-D, --debug Enable debug mode
-H, --host=[] Daemon socket(s) to connect to
-h, --help Print usage
-l, --log-level=info Set the logging level
--tls Use TLS; implied by --tlsverify
--tlscacert=~/.docker/ca.pem Trust certs signed only by this CA
--tlscert=~/.docker/cert.pem Path to TLS certificate file
--tlskey=~/.docker/key.pem Path to TLS key file
--tlsverify Use TLS and verify the remote
-v, --version Print version information and quit
Commands:
attach Attach to a running container
build Build an image from a Dockerfile
commit Create a new image from a container's changes
cp Copy files/folders between a container and the local filesystem
create Create a new container
diff Inspect changes on a container's filesystem
events Get real time events from the server
exec Run a command in a running container
export Export a container's filesystem as a tar archive
history Show the history of an image
images List images
import Import the contents from a tarball to create a filesystem image
info Display system-wide information
inspect Return low-level information on a container, image or task
kill Kill one or more running containers
load Load an image from a tar archive or STDIN
login Log in to a Docker registry.
logout Log out from a Docker registry.
logs Fetch the logs of a container
network Manage Docker networks
node Manage Docker Swarm nodes
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
ps List containers
pull Pull an image or a repository from a registry
push Push an image or a repository to a registry
rename Rename a container
restart Restart a container
rm Remove one or more containers
rmi Remove one or more images
run Run a command in a new container
save Save one or more images to a tar archive (streamed to STDOUT by default)
search Search the Docker Hub for images
service Manage Docker services
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
swarm Manage Docker Swarm
tag Tag an image into a repository
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
version Show the Docker version information
volume Manage Docker volumes
wait Block until a container stops, then print its exit code
Getting Information about Docker Setup
We can get the information about our Docker setup in several ways. Namely,
docker version
docker -v
docker system info
The docker system info command gives a lot of useful information like total number of containers and images along with information about host resource utilization etc.
Stream events from the docker daemon
Docker events serves us with the stream of events or interactions that are happening with the docker daemon. This does not stream the log data of application inside the container. That is done by docker logs command. Let us see how this command works
Open an another terminal. Let us call the old terminal as Terminal 1 and the newer one as Terminal 2.
From Terminal 1, execute docker events. Now you are getting the data stream from docker daemon
docker system events
Launching our first container
Now we have a basic understanding of docker command and sub commands, let us dive straight into launching our very first container
docker run alpine:3.4 uptime
Where,
- we are using docker client to
- run a application/command uptime using
- an image by name alpine:3.4
[Output]
Unable to find image 'alpine:3.4' locally
3.4: Pulling from library/alpine
81033e7c1d6a: Pull complete
Digest: sha256:2532609239f3a96fbc30670716d87c8861b8a1974564211325633ca093b11c0b
Status: Downloaded newer image for alpine:3.4
15:24:34 up 7:36, load average: 0.00, 0.03, 0.04
What happened?
This command will
- Pull the alpine image file from docker hub, a cloud registry
- Create a runtime environment/ container with the above image
- Launch a program (called uptime) inside that container
- Stream that output to the terminal
- Stop the container once the program is exited
Where did my container go?
docker container ps
docker container ps -l
The point here to remember is that, when that executable stops running inside the container, the container itself will stop.
Let's see what happens when we run that command again,
[Output]
docker run alpine uptime
07:48:06 up 3:15, load average: 0.00, 0.00, 0.00
Now docker no longer pulls the image again from registry, because it has stored the image locally from the previous run. So once an image is pulled, we can make use of that image to create and run as many container as we want without the need of downloading the image again. However it has created a new instance of the iamge/container.
Checking Status of the containers
We have understood how docker run commands works. But what if you want to see list of running containers and history of containers that had run and exited? This can be done by executing the following commands
docker ps
[Output]
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
This command doesn't give us any information. Because, docker ps command will only show list of container(s) which are running
docker ps -l
[Output]
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
988f4d90d604 alpine "uptime" About a minute ago Exited (0) About a minute ago fervent_hypatia
the -l flag shows the last run container along with other details like image it used, command it executed, return code of that command, etc.,
docker ps -n 2
[Output]
NAMES
988f4d90d604 alpine "uptime" About a minute ago Exited (0) About a minute ago fervent_hypatia
acea3023dca4 alpine "uptime" 3 minutes ago Exited (0) 3 minutes ago mad_darwin
Docker gives us the flexibility to show the desirable number of last run containers. This can be achieved by using -n #no_of_results flag
docker ps -a
[Output]
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
988f4d90d604 alpine "uptime" About a minute ago Exited (0) About a minute ago fervent_hypatia
acea3023dca4 alpine "uptime" 4 minutes ago Exited (0) 4 minutes ago mad_darwin
60ffa94e69ec ubuntu:14.04.3 "bash" 27 hours ago Exited (0) 26 hours ago infallible_meninsky
dd75c04e7d2b schoolofdevops/ghost:0.3.1 "/entrypoint.sh npm s" 4 days ago Exited (0) 3 days ago kickass_bardeen
c082972f66d6 schoolofdevops/ghost:0.3.1 "/entrypoint.sh npm s" 4 days ago Exited (0) 3 days ago 0.0.0.0:80->2368/tcp sodcblog
This command will show all the container we have run so far.
Running Containers in Interactive Mode
We can interact with docker containers by giving -it flags at the run time. These flags stand for
* i - Interactive
* t - tty
docker run -it alpine:3.4 sh
[Output]
Unable to find image 'alpine:3.4' locally
latest: Pulling from library/alpine
ff3a5c916c92: Already exists
Digest: sha256:7df6db5aa61ae9480f52f0b3a06a140ab98d427f86d8d5de0bedab9b8df6b1c0
Status: Downloaded newer image for alpine:latest
/ #
As you see, we have landed straight into sh shell of that container. This is the result of using -it flags and mentioning that container to run the sh shell. Don't try to exit that container yet. We have to execute some other commands in it to understand the next topic
Namespaced:
Like a full fledged OS, Docker container has its own namespaces
This enables Docker container to isolate itself from the host as well as other containers
Run the following commands and see that alpine container has its own namespaces and not inheriting much from host OS
NAMESPACED
[Run the following commands inside the container]
cat /etc/issue
ps aux
ifconfig
hostname
Shared(NON NAMESPACED):
We have understood that containers have their own namespaces. But will they share something to some extent? the answer is YES. Let's run the following commands on both the container and the host machine
[Run the following commands inside the container]
uptime
uname -a
cat /proc/cpuinfo
date
free
As you can see, the container uses the same Linux Kernel from the host machine. Just like uname command, the following commands share the same information as well. In order to avoid repetition, we will see the output of container alone.
Now exit out of that container by running exit or by pressing ctrl+d
Making Containers Persist
Running Containers in Detached Mode
So far, we have run the containers interactively. But this is not always the case. Sometimes you may want to start a container without interacting with it. This can be achieved by using "detached mode" (-d) flag. Hence the container will launch the deafault application inside and run in the background. This saves a lot of time, we don't have to wait till the applications launches successfully. It will happen behind the screen. Let us run the following command to see this in action
[Command]
docker run -idt schoolofdevops/loop program
-d , --detach : detached mode
[Output]
2533adf280ac4838b446e4ee1151f52793e6ac499d2e631b2c752459bb18ad5f
This will run the container in detached mode. We are only given with full container id as the output
Let us check whether this container is running or not
[Command]
docker ps
[Output]
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2533adf280ac schoolofdevops/loop "program" 37 seconds ago Up 36 seconds prickly_bose
As we can see in the output, the container is running in the background
Checking Logs
To check the logs, find out the container id/name and run the following commands, replacing 08f0242aa61c with your container id
[Commands]
docker container ps
docker container logs <container_id/name>
docker container logs -f <container_id/name>
Connecting to running container to execute commands
We can connect to the containers which are running in detached mode by using these following commands
[Command]
docker exec -it <container_id/name> sh
[Output]
/ #
You could try running any commands on the shell e.g.
apk update
apk add vim
ps aux
Now exit the container.
Launching a container with a pre built app image
To launch vote container run the following command. Don't bother about the new flag -P now. We will explain about that flag later in this chapter
docker container run -idt -P schoolofdevops/vote
[Output]
Unable to find image 'schoolofdevops/vote:latest' locally
latest: Pulling from schoolofdevops/vote
Digest: sha256:9195942ea654fa8d8aeb37900be5619215c08e7e1bef0b7dfe4c04a9cc20a8c2
Status: Downloaded newer image for schoolofdevops/vote:latest
7d58ecc05754b5fd192c4ecceae334ac22565684c6923ea332bff5c88e3fca2b
Lets check the status of the container
docker ps -l
[Output]
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7d58ecc05754 schoolofdevops/vote "gunicorn app:app -b…" 27 seconds ago Up 26 seconds 0.0.0.0:32768->80/tcp peaceful_varahamihira
Renaming the container
We can rename the container by using following command
docker rename 7d58ecc05754 vote
[replace 7d58ecc05754 with the actual container id on your system ]
We have changed container's automatically generated name to vote. This new name can be of your choice. The point to understand is this command takes two arguments. The Old_name followed by New_name Run docker ps command to check the effect of changes
docker ps
[Output]
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7d58ecc05754 schoolofdevops/vote "gunicorn app:app -b…" 3 minutes ago Up 3 minutes 0.0.0.0:32768->80/tcp vote
As you can see here, the container is renamed to vote. This makes referencing container in cli very much easier.
Ready to vote ?
Let's see what this vote application does by connecting to that application. For that we need,
- Host machine's IP
- Container's port which is mapped to a host's port
Let's find out the port mapping of container to host. Docker provides subcommand called port which does this job
docker port vote
[Output]
80/tcp -> 0.0.0.0:32768
So whatever traffic the host gets in port 2368 will be mapped to container's port 32768
Let's connect to http://IP_ADDRESS:PORT to see the actual application
Finding Everything about the running container
This topic discusses about finding metadata of containers. These metadata include various parameters like,
* State of the container
* Mounts
* Configuration
* Network, etc.,
Inspecting
Lets try this inspect subcommand in action
docker inspect vote
Data output by above command contains detailed descriptino of the container an its properties. is represented in JSON format which makes filtering these results easier.
Copying files between container and client host
We can copy files/directories form host to container and vice-versa
Let us create a file on the host
touch testfile
To copy the testfile from host machine to ghsot contanier, try
docker cp testfile vote:/opt
This command will copy testfile to vote container's /opt directory and will not give any output. To verify the file has been copies or not, let us log into container by running,
docker exec -it vote bash
Change directory into /opt and list the files
cd /opt
ls
[Output]
testfile
There you can see that file has been successfully copied. Now exit the container
Now you may try to cp some files from the container to the host machine
docker cp vote:/app .
ls
Checking the Stats
Docker stats command returns a data stream of resource utilization used by containers. The flag --no-stream disables data stream and displays only first result
docker stats --no-stream=true vote
docker stats
Controlling Resources
Docker provides us the granularity to control each container's resource utilization. We have several commands in the inventory to achieve this
Putting limits on Running Containers
First, let us monitor the utilization
docker stats
You can see that Memory attribute has max as its value, which means unlimited usage of host's RAM. We can put a cap on that by using update command
docker update --memory 400M --memory-swap -1 vote
[Output]
vote
Let us check whether the change has taken effect or not with docker stats terminal
docker stat
As you can see, the memory utilization of the container is changed from xxxx (unlimited) to 400 mb
Limiting Resources while launching new containers
The following resources can be limited using the update command
* CPU
* Memory
* Disk IO
* Capabilities
Open two terminals, lets call them T1, and T2
In T1, start monitoring the stats
docker stats
[Output]
CONTAINER CPU % MEM USAGE / LIMIT MM % NET I/O BLOCK I/O PIDS
b28efeef41f8 0.16% 190.1 MiB / 400 MiB 47.51% 1.296 kB / 648 B 86.02 kB / 45.06 kB 0
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
b28efeef41f8 0.01% 190.1 MiB / 400 MiB 47.51% 1.296 kB / 648 B 86.02 kB / 45.06 kB 0
From T2, launch containers with different CPU shares as well as cpus configurations. Default CPU shares are set to 1024. This is a relative weight. Observe docker stats command after every launch to see the effect of your configurations.
[CPU Shares]
docker run -d --cpu-shares 1024 schoolofdevops/stresstest stress --cpu 2
docker run -d --cpu-shares 1024 schoolofdevops/stresstest stress --cpu 2
docker run -d --cpu-shares 512 schoolofdevops/stresstest stress --cpu 2
docker run -d --cpu-shares 512 schoolofdevops/stresstest stress --cpu 2
docker run -d --cpu-shares 4096 schoolofdevops/stresstest stress --cpu 2
[CPUs]
docker run -d --cpus 0.2 schoolofdevops/stresstest stress --cpu 2
Close the T2 terminal once you are done with this lab.
Checking disk utilisation by
docker system df
[output]
docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 7 5 1.031GB 914.5MB (88%)
Containers 8 4 27.97MB 27.73MB (99%)
Local Volumes 3 2 0B 0B
Build Cache 0B 0B
To prune, you could possibly use
docker container prune
docker system prune
e.g.
docker system prune
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all dangling images
- all build cache
Are you sure you want to continue? [y/N]
N
Make sure you understand what all will be removed before using this command.
Stopping and Removing Containers
We have learnt about interacting with a container, running a container, pausing and unpausing a container, creating and starting a container. But what if you want to stop the container or remove the container itself
Stop a container
A container can be stopped using stop command. This command will stop the application inside that container hence the container itself will be stopped. This command basically sends a SIGTERM signal to the container (graceful shutdown)
[Command]
docker stop <container_id/name>
Kill a container
This command will send SIGKILL signal and kills the container ungracefully
[Command]
docker kill <container_id/name>
If you want to remove a container, then execute the following command. Before running this command, run docker ps -a to see the list of pre run containers. Choose a container of your wish and then execute docker rm command. Then run docker ps -a again to check the removed container list or not
[Command]
docker rm <container_id/name>
docker rm -f <container_id/name>
Exercises
Launching Containers with Elevated Privileges
When the operator executes docker run --privileged, Docker will enable to access to all devices on the host as well as set some configuration in AppArmor or SELinux to allow the container nearly all the same access to the host as processes running outside containers on the host.