Sunday, Aug 13, 2023

Docker


Docker

Docker delivers software in packages called containers. It’s main use is to kill the excuse “it runs on my computer” because if the software is ran on a docker container then it runs on every computer (if you can install docker on the new computer :)).

The main two components of docker are it’s server and client. Both are just software but they have different purposes. The docker server runs as a background process and waits for instructions. It’s main purpose is to create, delete, modify, stop docker containers (programs that are being run on it’s own isolated environment). The docker client is a command line software that we use as users. It’s main purpose is to help us request changes to the containers to the docker server, like requesting to spin up a docker container.

Docker Image

A docker image can be seen as a class in OOP (Object Oriented Programming). Docker images can be built via a Dockerfile file which contains the instructions to build such an image.

Images are made of multiple layers. These layers are instructions that are used to build the image. Each layer, except the last one is read only. The last layer is defined as the container layer which wraps all the other instructions. This layer is only created once the image is instantiated and any modification to the container is going to be applied to the last layer.

When a container is deleted only the container layer is deleted (last layer) while the image remains unchanged. This way multiple containers can use the same image but have different interactions and changes without duplication of the previous layers of the image.

Docker Hub

Docker Hub is a public registry, it’s like GitHub but for sharing docker images. It contains public and private repositories.

Commands

Below there is a series of useful commands that I’ll probably forget and instead of googling them I can access them whenever I want on my website.


Basic Commands

How to run a container. This will create a new “instance” of the image

docker run <image>

Look at the running containers

docker ps

Look at all the containers

docker ps -a

Run container and drop to shell

docker run -it <image>
docker run --interactive --tty <image>

Run container in the background (de-attach)

docker run -d <image>

Container restart settings

docker run --restart (always|no|on-failure[:maxretries]|unless-stopped) <image>

Remove container when exited

docker run --rm <image>

Provide a nickname to a container

docker run --name <name> <image>

How to start a stopped container (instance)

docker start <container>

Run a command against a container

docker exec <container> <command>

Drop into the container shell. Note that the shell must be available in the image OS. For example, for alpine the default one is ash but for ubuntu it is bash

docker exec -it <container> <shell>

Copy / move files from and to the container.

docker cp <source> <container>:<destination>
docker cp <container>:<source> <destination>

View container information

docker inspect <container>

Create a container image

docker commint <container> <name>

Map container port to host server

docker run -p <host_port>:<container_port> <container>

Run a container de-attach exposing a port with a name

docker run -dt -p <local-port>:<docker-port> --name <container-name> <image-name>

Get an image from docker hub

docker pull <image>

Look at the images you have locally

docker image ls

Remove an image

docker image rm <image-name>

Remove images without at least one container associated to them

docker image prune -a

Get information about an image

docker image inspect <image-name>

Log in to the Docker hub

docker loging --username=<username>

Tag an image

docker tag <image> <username>/<repo>:<tag>

Push image to docker hub

docker push <username>/<repo-name>

Log out of Docker hub

docker logout

Build a Dockerfile image

docker build <dockerfile-path> <name>

Example of Dockerfile

FROM alpine:3.13
RUN apk upgrade
RUN apk add nginx
COPY files/default.conf /etc/nginx/conf.d/default.conf
RUN mkdir -p /var/www/html
WORKDIR /var/www/html
COPY --chown=nginx:nginx /files/html/ .
EXPOSE 80
CMD [ "nginx", "-g", "pid /tmp/nginx.pid; daemon off;" ]

Delete a container once it finished running

docker container run --rm <container-name>

Remove all stopped containers. The -f flag is to force it and do not prompt for confirmation.

docker container prune -f

Exposing a port of the container

docker container run -d --expose <port-number> <image-name>

Look at the exposed ports of a container

docker container port <container-name>

Start a container with a command

docker container run <image-name> <command>

Executing a command on a container

docker container exec -it <container-name> <command>

Show the logs of a container

docker container logs <container-name>

Show the logs of all the containers in a service

docker service logs <service-name>

Note: Logs need to be output to stdout and stderr. For example (nginx):

RUN ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log

Networking

List of networks

docker network ls

Get detailed information of a network

docker network inspect <network-name>

Create a new network

docker network create <network-name>

Delete a network

docker network rm <network-name>

Delete all unused networks

docker network prune

Adding a container to a network

docker network connect <network-name> <container-name>

Removing a container from a network

docker network disconnect <network-name> <container-name>

Create a network with a subnet and gateway

docker network create --subnet <subnet> --gateway <gateway> <network-name>
docker network create --subnet <subnet> --gateway <gateway> --ip=range=<ip_range> --driver=<driver> <network-name>

Volumes

Docker containers have two types of data. The first one is non-persistent data which is tied to the life-cycle of the container. The persistent type of data in docker is called volumes and it isn’t tied to the life-cycle of the container.

List all volumes on a host

docker volume ls

Create a volume

docker volume create <volume-name>

Inspect a volume

docker volume inspect <volume-name>

Deleting a volume

docker volume rm <volumen-name>

Remove all unused volumes

docker volume prune

Using bind mounts

# With the mount flag
docker container run -d --name <container-name> --mount type=bind,source=<source>,target=<target> <image-name>

# Using the volume flag
docker container run -d --name <container-name> -v <source>:<target> <image-name>

Dockerfile

Dockerfiles are instructions on how to build an image. It has the following instructions.

FROM: sets the base image.

RUN: execute any commands.

CMD: default execution of the container. There can only be one at the end of the dockerfile.

LABEL: adds metadata to an image.

EXPOSE: informs docker that the container listens to the specified network ports at runtime.

ENV: set the environment variable to the

ADD: copies new files, directories, or remote file URLs from and adds them to the file-system of the image at the path

WORKDIR: set the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile.

ARG: Defines a variable that users can pass at build-time to the builder with the docker build command using the --build-arg <varname>=<value flag.

ONBUILD: Adds a trigger instruction to the image that executes when the image is used as the base for another build.

HEALTHCHECK: Tells docker how to test a container to check that it is still working.

SHELL: Allows the default shell used for the shell form of commands to be overridden.

USER: Specifies the user that is going to run all the commands (RUN and CMD)

VOLUME: Creates a mount point with the specified name and marks it as holding externally mounted volumes from native host or other containers.

Images

Build an image

docker image built -t <image-name>:<tag>

Build an image from a docker repository

docker image build -t <image-name>:<tag> <git-url>\#<branch>

Adding a name and an optional tag

docker image build -t <name>:<tag>

Use the commit hash as the image tag

git log -1 --pretty=%H

Create an image for docker hub

docker image tag <image-name>:<tag> <username>/<image-name>:<tag>

Pushing an image to docker hub

docker image push <username>/<image-name>:<tag>

Show the history of an image

docker image history <image-name>

Export image into a tar file

docker iamge save <image-name> > <filename>.tar
docker image save <image-name> -o <filename>.tar

Loading an image from a tar file

docker image load < <filename>.tar
docker iamge load -i <filename>.tar
docker image load --input <filename>.tar

Container Management

Display running processes on a container

docker container top <container-name>

Display stats of a docker container

docker container stats <container-name>

To make a container auto restart you can do the following with the flags:

docker container run -d --name <container-name> --restart <flag> <image-name>

To get docker events

docker system events

Docker Compose

Create a compose service

docker-compose  up -d

List containers created by docker-compose

docker-compose ps

Stop a compose service

docker-compose stop

Start a compose service

docker-compose start

Delete a compose service

docker-compose down

Example of a docker-compose.yml file

version: '3'
services:
  app-name:
    build:
      context: .
      args:
        - VERSION=v2.0
    ports:
      - "8081:3000"
    environment:
      - NODE_ENV=production

Note the following, docker compose has 4 top level keys: version, services, networks and volumes. The version key is mandatory and it’s used to define the compose file format. The compose file format is tied to the docker engine version.

Docker Swarm

Docker Swarm has two major components. The first one is the cluster. This clusters manages one or more Docker nodes. The communication between the nodes is encrypted. The second component is an orchestration engine for creating micro-services.

List all nodes

docker node ls

Inspecting a node

docker node inspect <node-name>

Promoting a worker to a manager

docker node promote <node-name>

Demoting a manager to a worker

docker node demote <node-name>

Removing a node form the swarm

docker node rm -f <node-name>

Have a node leave the swarm

docker swarm leave

Getting the join token

docker swarm join-token <worker|manager>

Have the node rejoin the swarm

docker swarm join --token <token> <private-ip>:2377

Creating a docker service

docker service create -d --name <service-name> -p <host-port>:<container-port> --replicas <number-of-replicas> <image-name> <cmd>

List all services

docker service ls

Inspecting a service

docker service inspect <service-name>

Getting logs for a service

docker service logs <service-name>

List all tasks of a service

docker service ps <service-name>

Scaling a service up and down

docker service scale <service-name>=<replicas-number>

Updating a service

docker service update [options] <service-name>

Creating a overlay network

docker network create -d overlay <network-name>

Creating a service with an overlay network

docker service create -d --name <service-name> \
    -p <host-port>:<container-port>  \
    --replicas <replicas-number> \
    <image-name> <cmd>

Adding a service to a network

docker service update --network-add <network-name> <service>

Removing a service from a network

docker service update --network-rm <network-name> <service-name>

Adding plugins

docker plugin install <plugin-name> [options]

Listing plugins

docker plugin ls

Disable a plugin

docker plugin disable <plugin-id>

Delete a plugin

docker plugin rm <plugin-id>

To deploy a whole application one could use stacks and docker-compose

docker stack deploy --compose-file docker-compose.yml <stack-name>

Docker Security

Using a custom seccomp profile

docker contianer run --security-opt seccomp=<profile> <image-name> <cmd>

Dropping capabilities (commands) from a container

docker container run --cap-drop=<command> <image-name> <cmd>

Limiting CPU and Memory

docker container run -it --cpus=<value> --memory=<value> <size> --memory-swap <value> <size> <image-name> <cmd>

Docker Content Trust

Creating a key

docker trust key generate <name>

Importing a key

docker trust key load <pem> --name <name>

Add signer

docker trust signer add --key <pem> <name> <repository>

Remove signer

docker trust signer remove <name> <repository>

Signing an image

docker trust sign <image-name>:<tag>

Docker secrets

Creating a secret using STDIN

STDIN | docker secret create <secret-name>

Creating a secret using a file

docker secret create <name> <file>

List secrets

docker secret ls

Inspecting a secret

docker secret inspect <secret-name>

Using a secret

docker service create --name <service-name> --secret <secret-name> <image-name>

Deleting a secret

docker secret rm <secret-name>