Docker

In a recent project , it was decided to deploy the new service with Docker Containers . A crash course of learning Docker has become part of the scope of this project . While I understood the conceptually Docker is a way to abstract various components of the an underlying operating system without using the full resources of the Virtual Machine. There is the concept of Images and Containers. Images are the Operating Systems , Containers are the running instance of them.

Docker Engine Install

For my instance for Ubuntu20.04 this was

  1. Updating the local linux packages (as one does on all new installs)
  2. Installing the packages to pull the Docker Repo over HTTPS .
  3. Add Docker GPG Key
  4. Set up the Repository
    • Stable , Nightly or Test Repo options
    • Stable was selected
  5. Install the Docker Engine
    • Check the versions installed in the repo
  6. Hello-World
  7. Manage Docker as a non root user
  8. Enable Docker on boot
# 1. Update the local linux packages 
sudo apt-get update

# 2. Install packages for HTTPS 
sudo apt-get install \
  ca-certificates \ 
  curl \ 
  gnupg \ 
  lsb-release

# 3 Add Docker GPG Key 
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 4 Set up the Repo 
deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu   focal stable

# 5 Install Docker Engine 
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
#Check the versions 
apt-cache madison docker-ce
root@server:/home/# apt-cache madison docker-ce
 docker-ce | 5:20.10.14~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.13~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.12~3-0~ubuntu-focal | 


#6 Hello World 
sudo docker run hello-world

#7 Manage Docker as Non root 
sudo groupadd docker
#Add user to docker group 
sudo usermod -aG docker $USER
#Add new group 
newgrp docker 
# Test you can run without sudo 
docker run hello-world

#8 Enable Docker on Boot default on Ubuntu 
sudo systemctl enable docker.service
sudo systemctl enable containerd.service


Running Containers:

Installing my projects container from a repo was easy , but then it was a requirement to install more images

#Container repo  
docker pull example.com/pathtocontainer 

#Run the container 
docker run --name example 

Docker Engine vs Docker Compose ?

After Docker Engine was installed it , I was able to install the containers image from the project repo. This was easy enough. What I did learn is projects often need multiple images/containers to run. Docker Compose is what is needed to run these.

#Install Docker Compose 
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

#Apply executable to the library 
sudo chmod +x /usr/local/bin/docker-compose

#Validate Installation 
docker-compose --version
docker-compose version 1.29.2, build 5becea4c

Docker Compose is great , you are able to make changes to the configuration in the yaml file “`docker-compose.yml“`. Inside of here you can config each of the containers. You can create a volume or mount the container directory to a directory on the virtual machine itself.

version: "3.7"
services:
  nautobot:
    image: "image"
    env_file:
      - "local.env"
    ports:
      - "8443:8443"
      - "8080:8080"
    restart: "unless-stopped"
    volumes:
      - ./secret:/opt/nb/secret. #This is a mount location 
      - ./secret:/var/lib/docker/volumes/nbvolume/_data # This is a volume 
volumes:
  postgres_data:
  nbvolume:

Docker Images:

Images are installed and now we have run the container , lets check out what is installed and running.

#List running containers 
docker ps 
#List all container 
docker ps -a 
#Inspect Images 
docker image inspect batfish/batfish:latest 
docker run <IMAGE>
#Docker add a DNS entry 
docker run --hostname HOSTNAME IMAGE 

Docker Volumes:

One lesson learned quickly is the need to mount and or have volumes . Containers do not save info on a reboot. Make sure you create a volume and add it to the docker-compose.yml.

#Create the Volume
docker volume create nbvolume

#Check for the volumes 
docker volume ls

# Inspect the volume  
docker volume inspect nbvolume 
docker volume inspect nbvolume 
[
    {
        "CreatedAt": "2022-04-20T09:04:12-04:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/nbvolume/_data",
        "Name": "nbvolume",
        "Options": {},
        "Scope": "local" 
}
]

The you can rebuild the service to connect the container to the storage volume

docker-compose up --build 

---this will output the log messages to determine if there is any issues with the container builds 

docker-compose up -d --build    

Docker Install Linux Packages from Container

Containers are intended to be minimal installations. If you need to install packages on the container . You need to enter as root

#Enter the shell as root 
 docker exec -u 0 -it  container_name bash

#install stuff 
apt-get -y install firefox
apt-get -y install vim

Docker Networking

You may also need to move the networks of these containers to be shared . The following is how I was able to review and move a containers network to one shared with another one.

#Inspect All Networks 
docker network ls
NETWORK ID     NAME                              DRIVER    SCOPE
345c8863e2dd   bridge                            bridge    local
d728aeb8fb17   host                              host      local
93ccefdc0b5c   container                        bridge    local
e61e468c0c0a   none                              null      local


#Connect container to a network 
docker network connect b46076c7a7b5 batfish/batfish 

Inspecting Networks

Bridge Network is the containers — the virtual machines network , but you can learn details about the networks with the inspect command .

docker network inspect host

# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "345c8863e2dd24587aa1410b20ffd5092c8e30c58a8ec035f223541b5b70679b",
        "Created": "2022-04-04T22:34:26.153453995-04:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
        "Containers": {
            "c17dcdd680b4a766c557ba74dc5fa5335508cf30cbc67524f936e0470afeb344": {
                "Name": "affectionate_engelbart",
                "EndpointID": "16889b97db32a412731453a77ba99a5085375884db1e1d37de66386001d02117",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        
]

Learning container abstraction is an important component to implementing solutions, I hope this post might help you in your journey while enhancing my own understanding.

Leave a comment