Docker basics hands-on

Posted in automation on April 27, 2017 by Adrian Wyssmann ‐ 3 min read

I wrote quick "Hands-on" for beginners to cover docker basics with simple containers so I won't go into details of complex application, service definitions or swarms. What I want to do is run a webserver inside a container with persistent data

Check Docker

Let’s check if docker is running

ubuntu@docker-host:~$ docker version
Client:
 Version:      1.12.6
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   78d1802
 Built:        Tue Jan 31 23:47:34 2017
 OS/Arch:      linux/amd64
Server:
 Version:      1.12.6
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   78d1802
 Built:        Tue Jan 31 23:47:34 2017
 OS/Arch:      linux/amd64

For now there are no images available but this will change in a little:

ubuntu@docker-host:~$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZ

There are also no running containers:

ubuntu@docker-host:~$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                          PORTS               NAMES

Maybe also quickly check the network configuration especially what IP’s our docker host has:

ubuntu@docker-host:~$ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 02:75:fc:25:d7:25 brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global enp0s3
       valid_lft forever preferred_lft forever
    inet6 fe80::75:fcff:fe25:d725/64 scope link
       valid_lft forever preferred_lft forever
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:08:be:4c brd ff:ff:ff:ff:ff:ff
    inet 192.168.33.10/24 brd 192.168.33.255 scope global enp0s8
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe08:be4c/64 scope link
       valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:d4:b5:a1:57 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever

Get your first image

Images have to be downloaded to the docker host once in order to be able to create containers. You can simply pull images with pull command{.external-link}

$ docker pull [OPTIONS] NAME[:TAG|@DIGEST]

Once done, you can see the images with images command{.external-link}. So let’s pull the webserver image ngnix and then check

ubuntu@docker-host:~$ docker pull nginx
....
57168433389f: Extracting [===============================================>   ] 20.64 MB/21.53 MB
57168433389f: Extracting [================================================>  ] 20.87 MB/21.53 MB
57168433389f: Extracting [=================================================> ]  21.1 MB/21.53 MB
57168433389f: Extracting [=================================================> ] 21.33 MB/21.53 MB
57168433389f: Extracting [==================================================>] 21.53 MB/21.53 MB
57168433389f: Pull complete
 
332ec8285c50: Extracting [==================================================>]    193 B/193 B
332ec8285c50: Extracting [==================================================>]    193 B/193 B
332ec8285c50: Pull complete
Digest: sha256:c15f1fb8fd55c60c72f940a76da76a5fccce2fefa0dd9b17967b9e40b0355316
Status: Downloaded newer image for nginx:latest
ubuntu@docker-host:~$ images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              46102226f2fd        12 hours ago        109.

Details on how this image is composed can be found by checking the image description on Docker-Hub, in the original Dockerfile or by inspecting the image with the docker inspect{.external-link} nginx command

Start your first container

A container can be started by docker run{.external-link} command:

ubuntu@docker-host:~$ docker run nginx

As you can see, so far nothing else happens. Well not entirely true, let’s quickly open another terminal and check whether we have a running container

ubuntu@docker-host:~$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
a4a7e4f36d5b        nginx               "nginx -g 'daemon off"   3 minutes ago       Up 3 minutes        80/tcp              pedantic_yonath

So there is a container running and it is named “pedantic_yonath” - this name is given automatically by docker, but you can force a proper name by aggregating parameter -name. So when the container is running, then we should be able to connect to the webserver right? Well first we need to figure out the ip address of the container, which can be simply achieved by inspect command

ubuntu@docker-host:~$ docker inspect pedantic_yonath
[
    {
        "Id": "a4a7e4f36d5b5c19d6f67381726dbe54b5feec81aeec150b816a81d8a671fd0f",
        "Created": "2017-04-26T13:54:36.632963616Z",
        "Path": "nginx",
        "Args": [
            "-g",
            "daemon off;"
        ],
...
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02"
                }
            }
        }
    }
]
ubuntu@docker-host:~$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' pedantic_yonath
172.17.0.2