Install and Deploy Docker in Raspberry Pi
Tags: docker, raspberrypi, beginners, tutorial
Published: 2020-02-12 17:39:01

Im not going to talk too much about benefits of Docker or any Container Engines around, there is already too many good guides you can check to see why is so important to learn about Docker and what you can achieve with it.

In this case, we will start using Docker in our lovely Raspberry Pi, so it is not the fastest system, but is always nice to know what you can achieve with this cheap system available for everybody.

The main mission on this first Docker project will be simulate couple of Ubuntu servers we can later use for small Ansible projects in our Raspberry Pi

***Lets start!!***

Like I was mentioning earlier, we are using a small Raspberry Pi 2:

    Linux raspi-2 4.19.97-v7+ #1294 SMP Thu Jan 30 13:15:58 GMT 2020 armv7l
    
    The programs included with the Debian GNU/Linux system are free software;
    the exact distribution terms for each program are described in the
    individual files in /usr/share/doc/*/copyright.
    
    Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
    permitted by applicable law.
    Last login: Fri Feb  7 15:10:01 2020 from 192.168.0.21
        .',;:cc;,'.    .,;::c:,,.    P-42@raspi-2
       ,ooolcloooo:  'oooooccloo:    OS: Raspbian 10 buster
       .looooc;;:ol  :oc;;:ooooo'    Kernel: armv7l Linux 4.19.97-v7+
         ;oooooo:      ,ooooooc.     Uptime: 4d 23h 1m
           .,:;'.       .;:;'.       Packages: 635
           .... ..'''''. ....        Shell: 25900
         .''.   ..'''''.  ..''.      WM: Not Found
         ..  .....    .....  ..      CPU: ARMv7 rev 5 (v7l) @ 4x 900MHz
        .  .'''''''  .''''''.  .     GPU: BCM2708
      .'' .''''''''  .'''''''. ''.   RAM: 193MiB / 926MiB
      '''  '''''''    .''''''  '''
      .'    ........... ...    .'.
        ....    ''''''''.   .''.
        '''''.  ''''''''. .'''''
         '''''.  .'''''. .'''''.
          ..''.     .    .''..
                .'''''''
                 ......
    P-42@raspi-2:~#
    '

## Installing Docker


To Install Docker, instead of using your Distro package manager, use the following script from docker.com  to make sure you are getting latest version:



    P-42@raspi-2:~#curl -sSL https://get.docker.com | sh
    # Executing docker install script, commit: f45d7c11389849ff46a6b4d94e0dd1ffebca32c1
    + sudo -E sh -c apt-get update -qq >/dev/null
    + sudo -E sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null
    + sudo -E sh -c curl -fsSL "https://download.docker.com/linux/raspbian/gpg" | apt-key add -qq - >/dev/null
    Warning: apt-key output should not be parsed (stdout is not a terminal)
    + sudo -E sh -c echo "deb [arch=armhf] https://download.docker.com/linux/raspbian buster stable" > /etc/apt/sources.list.d/docker.list
    + sudo -E sh -c apt-get update -qq >/dev/null
    + [ -n  ]
    + sudo -E sh -c apt-get install -y -qq --no-install-recommends docker-ce >/dev/null
    + sudo -E sh -c docker version
    Client: Docker Engine - Community
     Version:           19.03.5
     API version:       1.40
     Go version:        go1.12.12
     Git commit:        633a0ea
     Built:             Wed Nov 13 07:37:22 2019
     OS/Arch:           linux/arm
     Experimental:      false
    
    Server: Docker Engine - Community
     Engine:
      Version:          19.03.5
      API version:      1.40 (minimum version 1.12)
      Go version:       go1.12.12
      Git commit:       633a0ea
      Built:            Wed Nov 13 07:31:17 2019
      OS/Arch:          linux/arm
      Experimental:     false
     containerd:
      Version:          1.2.10
      GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
     runc:
      Version:          1.0.0-rc8+dev
      GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
     docker-init:
      Version:          0.18.0
      GitCommit:        fec3683
    If you would like to use Docker as a non-root user, you should now consider
    adding your user to the "docker" group with something like:
    
      sudo usermod -aG docker P-42
    
    Remember that you will have to log out and back in for this to take effect!
    
    WARNING: Adding a user to the "docker" group will grant the ability to run
             containers which can be used to obtain root privileges on the
             docker host.
             Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface
             for more information.
    P-42@raspi-2:~/Docker#

In order to be able use Docker with our user and no root, lets add our user to the docker group

    P-42@raspi-2:~#sudo usermod -aG docker P-42

Make sure you restart your user session so the changes are applied.

To test your installation, is good idea you execute the traditional `hello-world` build 


    P-42@raspi-2:~#docker run hello-world
    Unable to find image 'hello-world:latest' locally
    latest: Pulling from library/hello-world
    c1eda109e4da: Pull complete
    Digest: sha256:4df8ca8a7e309c256d60d7971ea14c27672fc0d10c5f303856d7bc48f8cc17ff
    Status: Downloaded newer image for hello-world:latest
    
    Hello from Docker!
    This message shows that your installation appears to be working correctly.
    
    To generate this message, Docker took the following steps:
     1. The Docker client contacted the Docker daemon.
     2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
        (arm32v7)
     3. The Docker daemon created a new container from that image which runs the
        executable that produces the output you are currently reading.
     4. The Docker daemon streamed that output to the Docker client, which sent it
        to your terminal.
    
    To try something more ambitious, you can run an Ubuntu container with:
     $ docker run -it ubuntu bash
    
    Share images, automate workflows, and more with a free Docker ID:
     https://hub.docker.com/
    
    For more examples and ideas, visit:
     https://docs.docker.com/get-started/
    
    P-42@raspi-2:~#

## Docker Configuration

Lets create a folder for our projec where the different containers will be deployed.

    P-42@raspi-2:~#mkdir Docker
    mkdir: created directory 'Docker'
    P-42@raspi-2:~#

Lets create now our first Dockerfile, which will setup our docker image for this first project.

This example, will make sure we create an image that will allow us to create containers based in Ubuntu which will have ssh access, python installed (so we can use Ansible on it) and will also add a new user to it, in case we want to try different things with different users in the future.


    P-42@raspi-2:~/Docker#cat Dockerfile
    # BUILD VERSION
    FROM ubuntu:16.04
    
    # INSTALL SSH AND PYTHON
    
    RUN apt-get update && apt-get install -y openssh-server sshpass python-minimal software-properties-common
    RUN apt-get update
    RUN mkdir /var/run/sshd
    
    
    #SET ROOT PASSWORD
    RUN echo "root:Welcome1" | chpasswd
    
    # ALLOW SSHLOGIN TO ROOT
    
    RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
    
    # SSH login fix. Otherwise user is kicked off after login
    RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
    
    ENV NOTVISIBLE "in users profile"
    RUN echo "export VISIBLE=now" >> /etc/profile
    EXPOSE 22
    EXPOSE 80
    CMD ["/usr/sbin/sshd", "-D"]
    
    # CREATE USER P-42
    
    RUN groupadd P-42 && useradd -ms /bin/bash -g P-42 P-42
    
    # SET P-42 PASSWORD
    RUN echo 'P-42:Welcome1' | chpasswd
    
    # COPY HOST SSH KEY
    
    ARG home=/home/P-42
    RUN mkdir $home/.ssh
    COPY /id_rsa.pub $home/.ssh/authorized_keys
    RUN chown P-42:P-42 $home/.ssh/authorized_keys && \
        chmod 600 $home/.ssh/authorized_keys
    P-42@raspi-2:~/Docker#

If you check latest part of the Dockerfile, you will notice we are making a copy of our user public ssh keys so we can connect to the containers using our ssh keys instead the user password.

In order to do that, make sure you have your Docker project directory

    P-42@raspi-2:~/Docker#cp -pr $HOME/.ssh/id_rsa.pub .
    '/home/P-42/.ssh/id_rsa.pub' -> './id_rsa.pub'
    P-42@raspi-2:~/Docker#


## Building Docker Image

Lets build our first image called "ansible" so we can later deploy our containers:

    P-42@raspi-2:~/Docker#time docker build -t ansible .
    Sending build context to Docker daemon  4.096kB
    Step 1/18 : FROM ubuntu:16.04
    16.04: Pulling from library/ubuntu
    e60df59fb597: Downloading [===================>                               ]  14.99MB/38.85MB
    99ba0251fafa: Download complete
    
    [......]
    
    Step 16/18 : RUN mkdir $home/.ssh
     ---> Running in df77faedd340
    Removing intermediate container df77faedd340
     ---> cb582bdc36f4
    Step 17/18 :COPY /id_rsa.pub $home/.ssh/authorized_keys
     ---> 572093ffb71c
    
    real	11m21.811s
    user	0m1.019s
    sys	0m0.513s
    P-42@raspi-2:~/Docker#

As you can see, we took around 10 minutes to get our image created.

Lets create our Docker network called "ANSIBLE"


    P-42@raspi-2:~/Docker#docker network create --subnet=172.168.0.0/24 ANSIBLE
    1f8498228e9578134ba203346b145ca4c5a4ecea85c932940ce8ffa200ff71ab
    P-42@raspi-2:~/Docker#

Now, lets add the IP and hostnames of your container to your `/etc/hosts` so we get direct access to them

    P-42@raspi-2:~/Docker#grep -i Ansible -A20 /etc/hosts
    ####### ANSIBLE #######
    
    172.168.0.121   server1
    172.168.0.122   server2
    172.168.0.123   server3
    172.168.0.124   server4
     
## Deploying Docker Containers

We are now ready to deploy our container with our recently created "ansible" image

    P-42@raspi-2:~/Docker#docker run --net ANSIBLE -h server1 --name server1 --ip 172.168.0.121 -t -d ansible
    2f9c42ddd085234c305f1b90d00981ae5109812b654aa9a9bb59fb017ecd0c27
    P-42@raspi-2:~/Docker#

and ***voila!*** we have our container created that allow us to connect using ssh and have python enabled to use Ansible








    P-42@raspi-2:~/Docker#ssh server1
    The authenticity of host 'server1 (172.168.0.121)' can't be established.
    ECDSA key fingerprint is SHA256:RgpMp25wAJRBNiUTDkfO6MaEX83is1EYP2NaB4dvMpA.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added 'server1,172.168.0.121' (ECDSA) to the list of known hosts.
    Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.19.97-v7+ armv7l)
    
     * Documentation:  https://help.ubuntu.com
     * Management:     https://landscape.canonical.com
     * Support:        https://ubuntu.com/advantage
    
    The programs included with the Ubuntu system are free software;
    the exact distribution terms for each program are described in the
    individual files in /usr/share/doc/*/copyright.
    
    Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
    applicable law.
    
    P-42@server1:~$
    
    P-42@server1:~$ python3 --version
    Python 3.5.2
    P-42@server1:~$

Now, we can create our "little servers" with a simple loop as follow

    P-42@raspi-2:~/Docker#for i in {1..4}; do docker run --net ANSIBLE -h server$i --name server$i --ip 172.168.0.12$i -t -d ansible; done
    91a8331a300269fbb328c553836af187e0c44557c04123bcefb87268eb21b87e
    f0ecab6a81e7650c8dcd251bf63da7fe79aac87a0cf463728d16db7765e7a8d0
    7d4327d9ed0d7515664dcaf04cb232ded89b002996aab690f05740c0208b0713
    3e6b458a42c2d58b1951797ebfa7675cc0da45d748471b78bf634fa40604d837
    P-42@raspi-2:~/Docker#
    
    
    P-42@raspi-2:~/Docker#docker ps
    CONTAINER ID        IMAGE               COMMAND               CREATED              STATUS              PORTS               NAMES
    3e6b458a42c2        ansible             "/usr/sbin/sshd -D"   58 seconds ago       Up 55 seconds       22/tcp, 80/tcp      server4
    7d4327d9ed0d        ansible             "/usr/sbin/sshd -D"   About a minute ago   Up 58 seconds       22/tcp, 80/tcp      server3
    f0ecab6a81e7        ansible             "/usr/sbin/sshd -D"   About a minute ago   Up About a minute   22/tcp, 80/tcp      server2
    91a8331a3002        ansible             "/usr/sbin/sshd -D"   About a minute ago   Up About a minute   22/tcp, 80/tcp      server1
    P-42@raspi-2:~/Docker#
    
    P-42@raspi-2:~/Docker#ssh server4
    The authenticity of host 'server4 (172.168.0.124)' can't be established.
    ECDSA key fingerprint is SHA256:RgpMp25wAJRBNiUTDkfO6MaEX83is1EYP2NaB4dvMpA.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added 'server4,172.168.0.124' (ECDSA) to the list of known hosts.
    Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.19.97-v7+ armv7l)
    
     * Documentation:  https://help.ubuntu.com
     * Management:     https://landscape.canonical.com
     * Support:        https://ubuntu.com/advantage
    
    The programs included with the Ubuntu system are free software;
    the exact distribution terms for each program are described in the
    individual files in /usr/share/doc/*/copyright.
    
    Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
    applicable law.
    
    P-42@server4:~$

To stop and delete all the containers, we can use the following:



    P-42@raspi-2:~/Docker#docker container stop $(docker container ls -aq)
    3e6b458a42c2
    7d4327d9ed0d
    f0ecab6a81e7
    91a8331a3002
    P-42@raspi-2:~/Docker#docker container prune
    WARNING! This will remove all stopped containers.
    Are you sure you want to continue? [y/N] y
    Deleted Containers:
    3e6b458a42c2d58b1951797ebfa7675cc0da45d748471b78bf634fa40604d837
    7d4327d9ed0d7515664dcaf04cb232ded89b002996aab690f05740c0208b0713
    f0ecab6a81e7650c8dcd251bf63da7fe79aac87a0cf463728d16db7765e7a8d0
    91a8331a300269fbb328c553836af187e0c44557c04123bcefb87268eb21b87e
    
    Total reclaimed space: 293.6kB
    P-42@raspi-2:~/Docker#

If you want to reclaim all the space and delete everything created so far, including Docker Network and Images, you can use the following


    P-42@raspi-2:~/Docker#docker system prune -a
    WARNING! This will remove:
      - all stopped containers
      - all networks not used by at least one container
      - all images without at least one container associated to them
      - all build cache
    
    Are you sure you want to continue? [y/N] y
    Deleted Networks:
    ANSIBLE
    
    Deleted Images:
    untagged: ubuntu:16.04
    untagged: ubuntu@sha256:3f3ee50cb89bc12028bab7d1e187ae57f12b957135b91648702e835c37c6c971
    untagged: ansible:latest
    deleted: sha256:15d994fd0e7e8568004401b288bacf0d8656f373467acb35cc413157c991b876
    deleted: sha256:7019b6089974020846d93a9588093b7dcf88fce59890f8ac2dfb89eade44cac1
    [...]
    
    Total reclaimed space: 255.9MB
    P-42@raspi-2:~/Docker#


There you go, a simple tutorial about getting Docker working in Rasperry Pi