Restarting and attaching to containers
Building Docker images with a Dockerfile
Hello World
$ docker run busybox echo hello world
hello world
We used one of the smallest, simplest images available: busybox. busybox is typically used in embedded systems (phones, routers...) We ran a single process and echo'ed hello world.
A more useful container
$ docker run -it amazonlinux
Unable to find image 'amazonlinux:latest' locally
Trying to pull repository docker.io/library/amazonlinux ...
sha256:b852ce504670f604074bb0a0285849c95541453c39da4a6abe19c096695ccfca: Pulling from docker.io/library/amazonlinux
40280b975f14: Pull complete
Digest: sha256:b852ce504670f604074bb0a0285849c95541453c39da4a6abe19c096695ccfca
Status: Downloaded newer image for docker.io/amazonlinux:latest
bash-4.2#
- -it is shorthand for -i -t.
- -i tells Docker to connect us to the container's stdin.
- -t tells Docker that we want a pseudo-terminal.
Do something in our container
bash-4.2# figlet hello
bash: figlet: command not found
An observation
Let's check how many packages are installed here.
bash-4.2# rpm -qa | wc -l
102
- rpm -qa lists the packages installed in our container
- wc -l counts them
Install a package in our container
We want figlet, so let's install it:
bash-4.2# yum update -y && yum install figlet -y
One minute later, figlet is installed!
bash-4.2# figlet 'Hello Team'
Exiting our container
Just exit the shell, like you would usually do.
(E.g. with ^D or exit)
bash-4.2# exit
- Our container is now in a stopped state.
- It still exists on disk, but all compute resources have been freed up.
Starting another container
What if we start a new container, and try to run figlet again?
$ docker run -it amazonlinux
bash-4.2# figlet 'Hello Team'
Type exit to exit and proceed
exit
- We started a brand new container.
- The basic amazonlinux image was used, and figlet is not here.
Our first containers were interactive. Let's continue.
A non-interactive container
- We will run a small custom container.
- This container just displays the time every second.
$ docker run hbravo/quartz
...
^C
This container will run forever.
To stop it, press ^C.
- Docker has automatically downloaded the image hbravo/quartz
- This image is a user image, created by hbravo
Run a container in the background
Containers can be started in the background, with the -d flag (daemon mode):
$ docker run -d hbravo/quartz
47d677dcfba4277c6cc68fcaa51f932b544cab1a187c853b7d0caf4e8debe5ad
Docker gives us the ID of the container.
List running containers
With docker ps, just like the UNIX ps command, lists running processes.
$ docker ps
CONTAINER ID IMAGE ... CREATED STATUS ...
47d677dcfba4 jpetazzo/clock ... 2 minutes ago Up 2 minutes ...
Docker tells us:
- The (truncated) ID of our container
- The image used to start the container
- That our container has been running (Up) for a couple of minutes
Starting more containers
Let's start two more containers.
$ docker run -d hbravo/quartz
57ad9bdfc06bb4407c47220cf59ce21585dce9a1298d7a67488359aeaea8ae2a
$ docker run -d hbravo/quartz
068cc994ffd0190bbe025ba74e4c0771a5d8f14734af772ddee8dc1aaf20567d
Check that docker ps correctly reports all 2 containers.
View the logs of a container
$ docker logs 068
Fri Feb 20 00:39:52 UTC 2015
Fri Feb 20 00:39:53 UTC 2015
...
We specified a prefix of the full container ID. You can, of course, specify the full ID.
Stopping our containers
Let's stop one of our containers:
$ docker stop 47d6
47d6
- This will take 10 seconds:
- Docker sends the TERM signal;
- the container doesn't react to this signal (it's a simple Shell script with no special signal handling);
- 10 seconds later, since the container is still running, Docker sends the KILL signal;
- this terminates the container.
List stopped containers
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS
bd8506a11b98 hbravo/quartz "/bin/sh -c 'while..." 22 minutes ago Exited (0) 22 minutes ago 6ace1563fd52 amazonlinux "/bin/bash" 25 minutes ago Exited (0) 22 minutes ago 0be0fcd6c807 amazonlinux "/bin/bash" 25 minutes ago Exited (127) 25 minutes ago 891d63c20cb3 amazonlinux "/bin/bash" 26 minutes ago Exited (0) 25 minutes ago ff4d569e8e80 amazonlinux "/bin/bash" 53 minutes ago Exited (0) 26 minutes ago
- The distinction between foreground and background containers is arbitrary
- From Docker's point of view, all containers are the same
- All containers run the same way, whether there is a client attached to them or not
- It is always possible to detach from a container, and to reattach to a container
- Analogy: attaching to a container is like plugging a keyboard and screen to a physical server
Detaching from a container
If you have started an interactive container (with option -it), you can detach from it.
The "detach" sequence is ^P^Q.
Otherwise you can detach by killing the Docker client.
(But not by hitting ^C, as this would deliver SIGINT to the container.)
What does -it stand for?
-t means "allocate a terminal." -i means "connect stdin to the terminal."
Attaching to a container
You can attach to a container:
$ docker attach <containerID>
- The container must be running
- There can be multiple clients attached to the same container
- If you don't specify --detach-keys when attaching, it defaults back to ^P^Q
Try it on our previous container:
$ docker attach $(docker ps -lq)
Check that ^X x doesn't work, but ^P ^Q does.
Showing current images
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/node latest c888d933885c 35 hours ago 676 MB
docker.io/centos latest ff426288ea90 3 days ago 207 MB
docker.io/ubuntu latest 00fd29ccc6f1 4 weeks ago 111 MB
docker.io/amazonlinux latest 6133b2c7d7c2 2 months ago 165 MB
docker.io/hbravo/quartz latest 9fa18fecadd7 4 days ago 6.03 MB
Searching for images
We cannot list all images on a remote registry, but we can search for a specific keyword:
$ docker search marathon
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mesosphere/marathon A cluster-wide init and co... 105 [OK]
mesoscloud/marathon Marathon 31 [OK]
mesosphere/marathon-lb Script to update haproxy b... 22 [OK]
tobilg/mongodb-marathon A Docker image to start a ... 4 [OK]
- "Stars" indicate the popularity of the image
- "Official" images are those in the root namespace
- "Automated" images are built automatically by the Docker Hub. (This means that their build recipe is always available.)
Downloading images
Explicitly, with
$ docker pull.
Implicitly, when executing $ docker run
and the image is not found locally
docker pull node
Using default tag: latest
Trying to pull repository docker.io/library/node ...
sha256:30f98963fd361b0241db107e68da88a1ebed0561e3ecc7bf221586901863e4b1: Pulling from docker.io/library/node
f49cf87b52c1: Pull complete
7b491c575b06: Pull complete
b313b08bab3b: Pull complete
51d6678c3f0e: Pull complete
da59faba155b: Pull complete
7f84ea62c1fd: Pull complete
c565d8353be2: Pull complete
d5ff402a260a: Pull complete
Digest: sha256:30f98963fd361b0241db107e68da88a1ebed0561e3ecc7bf221586901863e4b1
Status: Downloaded newer image for docker.io/node:latest
Create a new container and make some changes
Start an Ubuntu container:
$ docker run -it ubuntu
root@<yourContainerId>:#/
- Run the command apt-get update to refresh the list of packages available to install.
- Then run the command apt-get install figlet to install the program we are interested in.
root@<yourContainerId>:#/ apt-get update && apt-get install figlet
.... OUTPUT OF APT-GET COMMANDS ....
Inspect the changes
Type exit
at the container prompt to leave the interactive session.
Now let's run docker diff to see the difference between the base image and our container.
docker diff $(docker ps -l -q)
...
C /etc/alternatives
A /etc/alternatives/figlet
A /etc/alternatives/figlet.6.gz
C /root
A /root/.bash_history
C /run
D /run/secrets
C /tmp
C /usr/bin
A /usr/bin/chkfont
A /usr/bin/figlet
A /usr/bin/figlet-figlet
A /usr/bin/figlist
...
Commit and run your image
The docker commit command will create a new layer with those changes, and a new image using this new layer.
$ docker commit <yourContainerId>
<newImageId>
$ docker run -it <newImageId>
root@e2072fdfa86e:/# figlet 'It Works!'
Tagging images
Referring to an image by its ID is not convenient. Let's tag it instead.
We can use the tag command:
$ docker tag <newImageId> figlet
But we can also specify the tag as an extra argument to commit:
$ docker commit <containerId> figlet
And then run it using its tag:
$ docker run -it figlet
- A Dockerfile is a build recipe for a Docker image
- It contains a series of instructions telling Docker how an image is constructed
- The docker build command builds an image from a Dockerfile
Writing our first Dockerfile
Our Dockerfile must be in a new, empty directory.
Create a directory to hold our Dockerfile.
$ mkdir myimage
Create a Dockerfile inside this directory.
$ cd myimage
$ vim Dockerfile
*Of course, you can use any other editor of your choice.
Type this into our Dockerfile
FROM amazonlinux
RUN yum update -y
RUN yum install -y figlet
CMD ["/usr/bin/figlet","Hello World!"]
- FROM indicates the base image for our build
- Each RUN line will be executed by Docker during the build
- Our RUN commands must be non-interactive (No input can be provided to Docker during the build)
- In many cases, we will add the -y flag to yum commands
- The CMD instruction can be used for executing a specific command when a container is instantiated using the image being built
Build it
Save our file, then execute:
$ docker build -t amzlinuxfiglet:dev .
- -t indicates the tag to apply to the image.
- . indicates the location of the build context.
Running the image
The resulting image is not different from the one produced manually.
$ docker run amzlinuxfiglet:dev
Using image and viewing history
The history command lists all the layers composing an image.
For each layer, it shows its creation time, size, and creation command.
When an image was built with a Dockerfile, each layer corresponds to a line of the Dockerfile.
$ docker history figlet
IMAGE CREATED CREATED BY SIZE
fb3992dbaea0 12 minutes ago /bin/bash 41 MB
00fd29ccc6f1 4 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
<missing> 4 weeks ago /bin/sh -c mkdir -p /run/systemd && echo '... 7 B
<missing> 4 weeks ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\... 2.76 kB
<missing> 4 weeks ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0 B
<missing> 4 weeks ago /bin/sh -c set -xe && echo '#!/bin/sh' >... 745 B
<missing> 4 weeks ago /bin/sh -c #(nop) ADD file:f5a2d04c3f3cafa... 111 MB
In this example we are going to commit our new image to Amazon ECR - so we can e.g. use it in Amazon ECS or Amazon Fargate Tasks.
aws ecr create-repository --repository-name myamzlinuxfiglet
aws ecr get-login
docker login -u AWS *****
docker tag amzlinuxfiglet:dev *****.dkr.ecr.eu-west-1.amazonaws.com/amzlinuxfiglet:dev
docker push *****.dkr.ecr.eu-west-1.amazonaws.com/amzlinuxfiglet:dev
Run the Docker Hub image nginx, which contains a basic web server
$ docker run -d -P nginx
66b1ce719198711292c8f34f84a7b68c3876cf9f67015e752b94e189d35a204e
Docker will download the image from the Docker Hub.
- -d tells Docker to run the image in the background
- -P tells Docker to make this service reachable from other computers. (-P is the short version of --publish-all.)
But, how do we connect to our web server now?
Finding our web server port
We will use docker ps:
$ docker ps
CONTAINER ID IMAGE ... PORTS ...
e40ffb406c9e nginx ... 0.0.0.0:32769->80/tcp, 0.0.0.0:32768->443/tcp ...
- The web server is running on ports 80 and 443 inside the container
- Those ports are mapped to ports 32769 and 32768 on our Docker host
Manual allocation of port numbers
If you want to set port numbers yourself, no problem:
$ docker run -d -p 80:80 nginx
$ docker run -d -p 8000:80 nginx
$ docker run -d -p 8080:80 -p 8888:80 nginx
- We are running 3 NGINX web servers.
- The first one is exposed on port 80
- The second one is exposed on port 8000
- The third one is exposed on ports 8080 and 8888
Note: the convention is port-on-host:port-on-contain
Finding the container's IP address
We can use the docker inspect command to find the IP address of the container.
$ docker inspect --format '{{ .NetworkSettings.IPAddress }}' <yourContainerID>
172.17.0.3
This manual is based on the exellent material from http://container.training
- Docker homepage - http://www.docker.com
- Docker Hub - https://hub.docker.com
- Docker blog - http://blog.docker.com
- Docker documentation - http://docs.docker.com
- Docker code on GitHub - https://github.com/docker/docker
- Docker mailing list - [https://groups.google.com/forum/#!forum/docker-user
- Docker on IRC: irc.freenode.net and channels #docker and #docker-dev
- Docker on Twitter - http://twitter.com/docker
- Get Docker help on Stack Overflow - http://stackoverflow.com/search?q=docker
- Play With Docker Hands-On Labs - http://training.play-with-docker.com