Skip to main content

Docker

Install

Ubuntu 24.04, 22.04 passed.

# Uninstall old versions
sudo apt-get remove docker docker-engine docker.io containerd runc

Images, containers, volumes, and networks stored in /var/lib/docker/ aren’t automatically removed when you uninstall Docker.

sudo apt-get install ca-certificates curl gnupg lsb-release

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# OR
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 install docker-ce docker-ce-cli containerd.io docker-compose-plugin

# Verify that the Docker Engine installation is successful by running the hello-world image
sudo docker run hello-world

Manage Docker as a non-root user

# Create the docker group.
sudo groupadd docker

# Add your user to the docker group.
# -a is a shortcut for --append: It means append the group to the list of groups the user belongs to!
# -G is a shortcut for --groups: It tells usermod that the next argument is a group. Note that you need to use a capital -G here because we don’t want to modify the user’s primary group but the list of supplemental groups the user belongs to.
sudo usermod -aG docker $USER

newgrp docker

# WARNING: Error loading config file: /home/user/.docker/config.json - stat /home/user/.docker/config.json: permission denied
sudo chown "$USER":"$USER" /home/"$USER"/.docker -R
sudo chmod g+rwx "$HOME/.docker" -R

Docker CLI

  • command docker need root permission, or add user to docker group

compose

container

exec

# Jump into running container
docker container exec --interactive --tty nginx bash

run

docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]

[OPTIONS]

--detach

Start container into background.

--name

Set identifier by name.

--publish

port, outer network : inner network.

# Different OS
docker container run --platform

# Start container and jump into, container will close after exit
docker container run --interactive --tty nginx bash

# Service at http://localhost:81/
docker container run --detach --publish 81:80 nginx

docker container run --name nginx --publish 80:80 --detach nginx

docker container run --name postgres --detach --publish 5432:5432 --env POSTGRES_PASSWORD=passw0rd postgres

# Run with connect to a custom virtual network
docker container run --detach --publish 80:80 --network app --name nginx nginx

start

docker start [OPTIONS] CONTAINER [CONTAINER...]

[OPTIONS]

--attach , -a

Attach STDOUT/STDERR and forward signals.

docker container start -ai update-server

Operation

# Short
--publish, -p
--env, -e
--volume, -v
--detach, -d
# Removes the anonymous volumes associated with the container when the container is removed.
--rm
# connect the input screen of container to host when attache
--interactive, -i
# connect the tty keyboard to host when attache
--tty, -t
# Open virtual terminal, equal -i + -t
-it
# Bind current host path to container virtual path /source
-v $PWD:/source
# The default path when jump into container
-w /source
# Keep containers alive during daemon downtime
--live-restore
# Auto yes
--force, -f

# Show information
docker info

# Verify that Docker Compose is installed correctly by checking the version.
docker compose version

# List running containers
docker container ls

# List all containers
docker container list --all

# Show docker volumn
docker system df

# Start
docker container start 6c438 # container ID



# Stop
docker container stop 6c438c6 # container ID

docker container inspect --format '{{ .Config.AttachStdout }}' 51b # container ID

# Delete all container
docker container rm --force $(sudo docker container ls -aq)

# Delete all stopped containers
docker container prune



# Stop by name
docker container stop nginx



# List process
docker container top nginx

# On linux it just process, other os is vm
ps aux



# Check port, left is container inner port
docker container port nginx

# Check container ip
docker container inspect --format '{{ .NetworkSettings.IPAddress }}' nginx

# check network
docker network ls

# inspect keyword is generic, get detail information
docker network inspect nginx
docker network inspect bridge

# Create virtual network
docker network create app



# Add connect to virtual network, no response is correct
docker network connect app pg

# Remove
docker network disconnect app pg

Image

docker image pull redis:7.0

docker image list

docker image list --filter=reference='golang-*'

docker image history nginx:latest

docker image inspect

docker image tag nginx:latest rojarsmith/nginx:latest

docker image push

# --tag, -t
# Build image, . will search Dockerfile in current path
docker image build --tag whoami .

docker image build --tag whoami:production --file Dockerfile.production .

# Show time
time sudo docker build . -t my-hello-world

sudo docker image rm <IMAGE ID:0ac85a4992a0>

# Remove all dangling images
docker image prune

# Remove all images without at least one container associated to them
docker image prune --all

Repository

# First time must create "Access Tokens"
docker login -u rojarsmith

docker image push rojarsmith/nginx:latest

# Create a repository
# REGISTRY_STORAGE_DELETE_ENABLED: support deleting the image
# registry:2, official image name: version
docker run -d -p 5000:5000 --name registry --env REGISTRY_STORAGE_DELETE_ENABLED=true registry:2

docker image tag rojarsmith/nginx:latest localhost:5000/rojarsmith/nginx:latest

# Push to local repository
docker image push localhost:5000/rojarsmith/nginx:latest

# Check image
curl http://localhost:5000/v2/rojarsmith/nginx/tags/list

# Fetch digest
curl --head http://localhost:5000/v2/rojarsmith/nginx/manifests/latest -H 'Accept: application/vnd.docker.distribution.manifest.v2+json'

# Delete image
curl -X DELETE http://localhost:5000/v2/rojarsmith/nginx/manifests/sha256:f26fbadb0acab4a21ecb4e337a326907e61fbec36c9a9b52e725669d99ed1261

Volume

docker volume create whatever

docker volume list

docker volume rm vol

docker volume inspect + `TAB`

docker volume prune

# Named volumn, include the path in the container
docker container run --detach --name mysql --env MYSQL_ROOT_PASSWORD=whatever --volume mysql-data:/var/lib/mysql mysql

Compose

docker compose up

# Background
docker compose up -d

docker compose logs

Example:

# compose version
version: "3.8"

# 1 services block can contain multi containers
services:
# a service named "app"
app:
build: .

Mysql

.env and dockerfile put on the same path.

services:
mysql:
image: mysql:8
restart: unless-stopped
ports:
- "3306:3306"
env_file:
- .env
volumes:
- /root/mysql:/var/lib/mysql

Log

docker logs container

docker compose logs [service-name]

# Log
docker container logs nginx

# Show logging
docker container logs --follow nginx

Concept

Docker at Windows/OSX is running on virtual machine.

Dockerize, packing app by docker.

Container will auto exit after default script is end.

Container ID can use by abridge.

Container ID and Container Name are equivalence.

Docker default net bus IP is 0.0.0.0.

Container Name can be the DNS for inner virtual network.

alpine is a Linux distribution for docker.

missing in history is not error, just hash is the same.

prefix 'library' is official image.

different image tag can exist same image hash.

docker.io is default repository.

image full name like: docker.io/rojarsmith/nginx:latest.

New CMD will replace old one.

ENTRYPOINT should be defined when using the container as an executable.

Change the order of script lines in dockerfile can optimize the compile.

.dockerignore can ignore files when building.

FROM scratch, a special FROM, mean empty.

You cannot COPY or ADD files outside the current path where Dockerfile exists.

Image

Full name : REPOSITORY(library/$IMAGE):TAG

Debian version LTS 10 buster, 11 bullseye.

-slim: not include buildpack-deps

node:lts-alpine tag will pull node LTS Alpine image. Smallest.

lts-slim is larger but can do more thing.

Dockerfile

WORKDIR must before copy.

All file must in the root of dockerfile's folder.

# Base image
FROM ruby:3.1.2-alpine
# echo $AUTHOR
ENV AUTHOR=rojarsmith

# Multi RUNs will make multi layers
RUN apk add --update --no-cache \
build-base \
curl

# Make dir and jump into
WORKDIR /app

# Copy all of files from the folder Dockerfile located to container work idr /app
COPY . .

RUN gem install bundler:2.3.19 && \
bundle install -j4 --retry 3 && \
bundle clean --force && \
find /usr/local/bundle -type f -name '*.c' -delete && \
find /usr/local/bundle -type f -name '*.o' -delete && \
rm -rf /usr/local/bundle/cache/*.gem

# Container service port, can write after ENV
EXPOSE 3000

# Startup command
CMD ["bundle", "exec", "ruby", "whoami.rb", "-p", "3000", "-o", "0.0.0.0"]

Optimized

# Dockerfile
FROM ruby:3.1.2-alpine
ENV AUTHOR=rojarsmith <- May omit

EXPOSE 3000 <- Move up

CMD ["bundle", "exec", "ruby", "whoami.rb", "-p", "3000", "-o", "0.0.0.0"] <- Move up

WORKDIR /app <- Move up

RUN apk add --update --no-cache \
build-base \
curl

COPY . .

RUN gem install bundler:2.3.19 && \
bundle install -j4 --retry 3 && \
bundle clean --force && \
find /usr/local/bundle -type f -name '*.c' -delete && \
find /usr/local/bundle -type f -name '*.o' -delete && \
rm -rf /usr/local/bundle/cache/*.gem

Multi section can resize image.

# builder section
FROM alpine:3.16.2 AS builder
RUN echo 'Builder' > /example.txt

# tester section
FROM alpine:3.16.2 AS tester
COPY --from=builder /example.txt /example.txt
RUN echo 'Tester' >> /example.txt

# final section
FROM alpine:3.16.2
COPY --from=tester /example.txt /example.txt
CMD [ "cat", "/example.txt" ]

# docker container run example
# Builder
# Tester

Parameters

--build-arg

ARG

VOLUME

# Data will retain, auto build the volume and connect to /var/lib/mysql
# The virtual path is in the container
VOLUME /var/lib/mysql

The volume will not auto delete when delete container without special command.

# connect real path to virtual path
--volume ${PWD}/logs:/app/logs

Scenario

Backup & Restore Image

docker save -o myimage.tar myimage
docker load -i myimage.tar

Read files in the volume

docker run -it --rm -v /path/on/host:/vol busybox ls -l /vol

Optimize

# Clean no need cache
apk -U --no-cache add git

or

apk -U add git && \
rm -rf /var/cache/apk/*

-t, --virtual NAME Instead of adding all the packages to 'world', create a new virtual package with the listed dependencies and add that to 'world'; the actions of the command are easily reverted by deleting the virtual package

Tools

Fluentd

Collect logs.