Skip to main content

Installing Docker on Ubuntu 18.04 Using Snap

·4 mins

I recently revisited the installation of Docker, this time on my Ubuntu 18.04 virtual machine. I decided to use Snap this time to get the latest release of Docker and associated utilities. Here are the steps.

  1. Install docker.

    sudo snap install docker
    
  2. Verify the docker version.

    $ docker --version
    Docker version 18.06.1-ce, build e68fc7a
    $ docker.compose --version
    docker-compose version 1.22.0, build unknown
    

    Note that docker compose becomes available as docker.compose and not as docker-compose. This is due to Snap naming restrictions.

  3. Create the docker group and add my user account to it.

    sudo addgroup --system docker
    sudo adduser $USER docker
    newgrp docker
    
  4. Restart docker to activate the group change.

    sudo snap disable docker
    sudo snap enable docker
    
  5. Verify that docker is running by confirming that there are no images running.

    $ docker images
    REPOSITORY       TAG  IMAGE ID  CREATED  SIZE
    

I then proceeded to install and run the hello-world docker image, just to double-check the installation.

  1. Create a working directory for the new image.

    mkdir -p ~/Workspace/docker/hello-world
    cd ~/Workspace/docker/hello-world
    
  2. Create a docker configuration file with the following content.

    $ cat docker-compose.yml
    tests:
        image: hello-world
    
  3. Run the hello-world container.

    $ docker.compose up
    Pulling hello-world (hello-world:)...
    latest: Pulling from library/hello-world
    1b930d010525: Pull complete
    Digest: sha256:92695bc579f31df7a63da6922075d0666e565ceccad16b59c3374d2cf4e8e50e
    Status: Downloaded newer image for hello-world:latest
    Creating hello-world_tests_1 ... done
    Attaching to hello-world_tests_1
    hello-world_1  | 
    hello-world_1  | Hello from Docker!
    hello-world_1  | This message shows that your installation appears to be working correctly.
    hello-world_1  | 
    hello-world_1  | To generate this message, Docker took the following steps:
    hello-world_1  |  1. The Docker client contacted the Docker daemon.
    hello-world_1  |  2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    hello-world_1  |     (amd64)
    hello-world_1  |  3. The Docker daemon created a new container from that image which runs the
    hello-world_1  |     executable that produces the output you are currently reading.
    hello-world_1  |  4. The Docker daemon streamed that output to the Docker client, which sent it
    hello-world_1  |     to your terminal.
    hello-world_1  | 
    hello-world_1  | To try something more ambitious, you can run an Ubuntu container with:
    hello-world_1  |  $ docker run -it ubuntu bash
    hello-world_1  | 
    hello-world_1  | Share images, automate workflows, and more with a free Docker ID:
    hello-world_1  |  https://hub.docker.com/
    hello-world_1  | 
    hello-world_1  | For more examples and ideas, visit:
    hello-world_1  |  https://docs.docker.com/get-started/
    hello-world_1  | 
    hello-world_tests_1 exited with code 0
    
  4. Verify that the container is registered locally now.

    $ docker ps -a
    CONTAINER ID  IMAGE        COMMAND  CREATED        STATUS     PORTS           NAMES
    01f4d8ae5337  hello-world  "/hello" 52 seconds ago Exited (0) 51 seconds ago
    hello-world_tests_1
    

That’s it! … but there is more thing that requires attention.

Fixing DNS in the Containers #

Run the following command to verify that the containers resolve host names properly:

$ docker run --rm -it alpine ping -c3 debian.org
ping: bad address 'debian.org'

The command instantiates the alpine docker image and runs the ping command inside to access the debian.org host. In the example above, the container fails to resolve the host name.

By default, when docker instantiates an image it copies the DNS resolver file /etc/resolv.cof from the host into the new container. In Ubuntu 18.04, this file is a symlink:

$ ls -l /etc/resolv.conf
lrwxrwxrwx 1 root root 39 Apr 20  2018 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf
$ cat /etc/resolv.conf
nameserver 127.0.0.53
options edns0
search fosstel.com

The resolver file points to a DNS cache available at the address 127.0.0.53. This cache does not work inside the container and this is the reason why it fails to resolve the host name.

One way to solve this problem is to change the symlink to point to the real resolver file, as follows:

$ sudo rm /etc/resolv.conf
$ sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

You can run the ping test command again to verify that host resolution works:

$ docker run --rm -it alpine ping -c3 debian.org
PING debian.org (149.20.4.15): 56 data bytes
64 bytes from 149.20.4.15: seq=0 ttl=47 time=31.471 ms
64 bytes from 149.20.4.15: seq=1 ttl=47 time=28.204 ms
64 bytes from 149.20.4.15: seq=2 ttl=47 time=28.709 ms
 
--- debian.org ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss

There are other ways to change the way DNS resolution happens inside the containers. One of them is to modify the docker default values by editing the file /snap/docker/current/config/daemon.json and adding the following line, as an example:

"dns": ["8.8.8.8", "8.8.4.4"]

You may want investigate this and possible other options.