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.