Docker

Installing Docker

$ sudo apt-get update
$ sudo apt-get install -y ca-certificates curl gnupg
$ sudo install -m 0755 -d /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ sudo chmod a+r /etc/apt/keyrings/docker.gpg
$ echo \
"deb [arch="$(dpkg --print-architecture)" \
signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" \
stable" | sudo tee /etc/apt/sources.list.d/docker.list \
> /dev/null
$ sudo apt-get update
$ sudo apt-get -y install docker-ce docker-ce-cli \
containerd.io docker-buildx-plugin docker-compose-plugin

$ sudo docker --version

## Allow regular user to use docker 
$ sudo usermod -a -G docker <username>
  • Run a docker container

    • docker run hello-world
  • Docker registry

    • DockerHub , Google Container Registry (GCR)
  • Artifact Registry

    • Sonatype Nexus, JFrog Artifactory

Docker storage drivers and volumes

  • Docker data storage options

    • Volumes

      • store data directly in the host's filesystem.

      • Default - /var/lib/docker/volumes

    • Bind mounts

      • Allow to mount an existing host directory as a filesystem on the container

      • Processes other than docker can modify data.

    • tmpfs mounts

      • store data in memory
  • Docker storage drivers

    • overlay2

      • default and recommended
    • devicemapper

      • block based storage

      • Useful when writes > reads

    • btrfs and zfs

    • vfs

  • Configuring a storage driver

    • $ sudo vim /etc/docker/daemon.json

    • { "storage-driver": "devicemapper" }

    • sudo systemctl restart docker

    • $ docker info | grep 'Storage Driver'

  • Running your first container

    • $ docker run hello-world
  • Running containers from versioned images

    • $ docker run nginx:1.18.0
  • Running Docker containers in the background

    • $ docker run -d nginx:1.18.0
  • Troubleshooting containers

    • $ docker ps

    • $ docker logs beb5dfd529c9

  • Best setting for HA nginx

    • $ docker run -d --name nginx --restart unless-stopped -p 80:80 --memory 1000M --memory-reservation 250M nginx:1.18.0

    • Other options for flag unless-stopped , no, on_failure , always

    • -p 80:80: Forward traffic from host port 80 to container port 80

  • Restarting and removing containers

    • Stop $ docker stop nginx

    • Start $ docker start nginx

    • Stop and remove $ docker stop nginx && docker rm nginx or $ docker rm -f nginx

Docker logging

  • Logging drivers

    • none

    • local

    • json-file (default)

    • syslog

    • journald

    • gelf

    • fluentd

    • awslogs

    • splunk

    • etwlogs

    • gcplogs

    • logentries

  • Configuring logging drivers

    • $ docker info | grep "Logging Driver"

    • $ sudo vim /etc/docker/daemon.json

    • { "log-driver": "journald" }

    • $ sudo systemctl restart docker

    • $ docker run --name nginx-journald -d nginx

    • $ sudo journalctl CONTAINER_NAME=nginx-journald

    • For splunk

      •   {
          "log-driver": "splunk",
          "log-opts": {
          "splunk-token": "<Splunk HTTP Event Collector token>",
          "splunk-url": "<Splunk HTTP(S) url>"
          }
          }
        
    • Passing from command line

      • $ docker run --name nginx-json-file --log-driver json-file -d nginx
    • Log directory - /var/lib/docker/ containers/<container_id>/<container_id>-json.log

  • Approach to logging

    • Store logs locally using JSON files then use another container to push the logs to log analytics solution
  • Docker monitoring with Prometheus

    • Uses Prometheus query language (PromQL), time series database.

    • Prometheus + cAdvisor

    • cAdvisor is a metrics collector that scrapes metrics from containers

  • Metrics to monitor

    • Host metrics

      • Host CPU

      • Host memory

      • Host disk space

    • Docker container metrics

      • Container CPU

      • Throttled CPU time

      • Container memory fail counters

      • Container memory usage

      • Container swap

      • Container disk I/O

      • Container network metrics

Declarative container management with Docker Compose

  • Requirements

    • Python Flask application listens on port 5000

    • Application connects to Redis database as a backend service on port 6379

  • Docker File

    •   FROM python:3.7-alpine
        ENV FLASK_APP=app.py
        ENV FLASK_RUN_HOST=0.0.0.0
        RUN apk add --no-cache gcc musl-dev linux-headers
        COPY requirements.txt requirements.txt
        RUN pip install -r requirements.txt
        EXPOSE 5000
        COPY . .
        CMD ["flask", "run"]
      
  • Docker compose file

    •   version: "2.4"
        services:
            flask:
                image: "image-directory/python-flask-redis:latest"
                ports:
                    - "80:5000"
                networks:
                    - flask-app-net
            redis:
                image: "redis:alpine"
                networks:
                    - flask-app-net
                command: ["redis-server", "--appendonly", "yes"]
                volumes:
                    - redis-data:/data
        networks:
            flask-app-net:
                driver: bridge
        volumes:
            redis-data:
      
    • $ docker compose up -d

  • Best Practices

    • Use an .env file to store sensitive variables

    • Be mindful of dependencies in production

      • $ docker-compose up --no-deps -d <container_service_name>