一、安装和部署docker
(一) Ubuntu 包安装
官方文档:安装 |Docker 文档
我这里就用阿里的:Docker CE镜像-Docker CE镜像下载安装-开源镜像站-阿里云
bash
# step 1: 安装必要的一些系统工具
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
# step 2: 信任 Docker 的 GPG 公钥
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Step 3: 写入软件源信息
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Step 4: 安装Docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# apt-cache madison docker-ce
# docker-ce | 17.03.1~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
# docker-ce | 17.03.0~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
# Step 2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.1~ce-0~ubuntu-xenial)
# sudo apt-get -y install docker-ce=[VERSION]】
注意指定安装的时候 docker-ce docker-ce-cli 这两个都要指定一下版本
bash
root@ubuntu10:~ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
root@ubuntu10:~ ls /etc/apt/sources.list.d/ #在这个目录下建立一个 docker.list 文件,包就换成阿里云的地址了
docker.list ubuntu.sources ubuntu.sources.curtin.orig ubuntu.sources.save
(二) Linux 二进制离线安装
官网地址:https://download.docker.com/linux/
先搞一个安装包下来,放到要放得主机中
bash
root@ubuntu11:~ ls
docker-28.2.2.tgz
root@ubuntu11:~ tar xvf docker-28.2.2.tgz #解压出来
docker/
docker/containerd-shim-runc-v2
docker/containerd
docker/docker
docker/runc
docker/ctr
docker/dockerd
docker/docker-init
docker/docker-proxy
bash
root@ubuntu11:~ cd docker/
root@ubuntu11:~/docker mv * /usr/local/bin/
放到这个文件下有$PATH变量,可以方便直接调用它
启动docker程序
bash
root@ubuntu11:~/docker dockerd
最好还是写个service文件来控制
root@ubuntu11:/lib/systemd/system# vim docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
# 默认不使用systemd来管理cgroup,因为相关的委托机制问题仍然存在still
# 且systemd目前尚不支持Docker容器运行所需的cgroup功能集
# for containers run by docker
ExecStart=/usr/local/bin/dockerd -H unix://var/run/docker.sock
ExecReload=/bin/kill -s HUP \$MAINPID
# 若设置非零的Limit*类限制参数,会因内核中的资源记账开销导致性能问题
# 我们建议使用cgroups来实现容器级别的资源记账管理
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# 若你的systemd版本支持,可取消此行注释
# 仅systemd 226及更高版本支持此配置项
#TasksMax=infinity
TimeoutStartSec=0
# 设置delegate为yes,避免systemd重置Docker容器的cgroup配置containers
Delegate=yes
# 仅终止Docker主进程,而非cgroup中的所有进程
KillMode=process
# 若Docker进程异常退出,则重启该进程
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
重新加载配置并设置开机自启动
bash
root@ubuntu11:/lib/systemd/system systemctl daemon-reload
root@ubuntu11:/lib/systemd/system systemctl enable --now docker.service
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.
(三)官方的脚本
从Docker官方下载通用安装脚本
注意: 此脚本当前不支持 Rocky Linu
bashcurl -fsSL get.docker.com -o get-docker.sh #如果是Rocky,修改os-release文件如下,即可支持安装 vim /etc/os-release ID="centos"
二、docker配置优化
1.基本内容
bash
vim /etc/docker/daemon.json
{
"registry-mirrors": [ #官方镜像加速(必备没有魔法的话)
"https://docker.m.daocloud.io",
"https://docker.1panel.live",
"https://docker.1ms.run",
"https://docker.xuanyuan.me"
],
"insecure-registries": ["仓库地址"], #私有仓库地址
#开启远程:https://docs.docker.com/config/daemon/remote-access/ 或者在service文件中加入 ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H fd://
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"], #新版不支持此方式,这个方式不安全最好用SSH的方式
"insecure-registries": ["harbor.wang.org"],
"exec-opts": ["native.cgroupdriver=systemd"],
"data-root": "/data/docker", #方法1:指定docker数据目录,建议使用高速磁盘
#方法2:ExecStart=/usr/bin/dockerd --data-root=/data/docker
#"graph": "/data/docker", #旧版写法,指定docker数据目录,新版24.0.0不支持
"max-concurrent-downloads": 10, #定义下载的并发连接
"max-concurrent-uploads": 5, #定义上传的并发连接
"log-opts": { #日志设定
"max-size": "300m", #指定容器日志文件的最大值
"max-file": "2" #指定容器日志文件的个数,循环写入日志文件,即一个日志满,会写入第二个文件
},
"live-restore": true, #docker.service重启,不影响容器的运行
"proxies": { #代理 https://docs.docker.com/network/proxy/
"default": {
"httpProxy": "http://proxy.example.com:3128",
"httpsProxy": "https://proxy.example.com:3129",
"noProxy": "*.test.example.com,.example.org,127.0.0.0/8"
}
"tcp://docker-daemon1.example.com": {
"noProxy": "*.internal.example.net"
}
}
}
2.通过ssh 协议远程连接
bash
root@ubuntu10:~ ssh-keygen
root@ubuntu10:~ ssh-copy-id 10.0.0.11
root@ubuntu10:~ docker -H ssh://root@10.0.0.11 version
Client: Docker Engine - Community
Version: 29.1.4
API version: 1.50 (downgraded from 1.52)
Go version: go1.25.5
Git commit: 0e6fee6
......
3.docker 命令自动补全
bash
apt update && apt-get install bash-completion -y
curl https://raw.githubusercontent.com/docker/docker-ce/master/components/cli/contrib/completion/bash/docker -o /etc/bash_completion.d/docker.sh
exit
三、Docker基本命令
通用操作

容器操作

镜像操作

bash
docker save `docker images --format' {{.Repository}}:{{.Tag}}'` -o all.tar
docker save `docker images | awk 'NR!=1{print $1":"$2}'` -o all.tar
将本机的所有镜像打包到一个文件中
(一)启动容器
docker run [选项] [镜像名] [shell命令] [参数]
bash
后台运行并取名
root@ubuntu10:~ docker run -d --name mynginx01 nginx:1.24.0

容器运行的条件:
1)容器中需要定义一个默认启动程序
2)此程序持续运行
3)此程序在容器中前台运行
所以操作系统类型的容器直接启动启动不了
bash
创建一个容器的操作系统进入
root@ubuntu10:~ docker run -it --name ubuntu02 ubuntu:24.04

创建的文件其实质还是在宿主机上面

注意:容器启动后如果容器内没有前台运行的进程,将自动退出停止
从容器内退出,并停止容器:exit
从容器内退出,且容器不停止,同时按三个键:Ctr1+p+q
(二)查看容器信息
一下这三个命令通常用在排错当中
docker ps [OPTIONS]
docker container ls [OPTIONS]
#以下是一些常用的占位符:
{{.ID}}: 容器的ID。
{{.Image}}: 容器使用的映像名称。
{{.Command}}: 容器的启动命令。
{{.CreatedAt}}: 容器的创建时间。
{{.RunningFor}}: 容器运行的时间。
{{.Ports}}: 容器的端口映射信息。
{{.Status}}: 容器的状态。
{{.Size}}: 容器的大小。
{{.Names}}: 容器的名称。
{{.Label}}: 容器的标签。
bash
查看容器的详细信息
root@ubuntu10:~ docker inspect mynginx01
查看容器IP
docker inspect --format "{{.NetworkSettings.Networks.bridge.IPAddress}}" mynginx01
查看容器内的进程
docker top CONTAINER [ps OPTIONS]

查看容器的日志
docker logs [OPTIONS] CONTAINER
bash
root@ubuntu10:~ docker run -d --name alpine01 alpine /bin/sh -c 'i=1;while true;do echo hello$i;let i++;sleep 2;done'
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
Digest: sha256:865b95f46d98cf867a156fe4a135ad3fe50d2056aa3f25ed31662dff6da4eb62
Status: Downloaded newer image for alpine:latest
5d40e05827827d8388e105cc3b7a9fecbed0b83c6779f9ca3851b57c5c343e5b
root@ubuntu10:~ docker logs 5d40
hello1
hello2
hello3
hello4
hello5
hello6
hello7
hello8
hello9
(三)删除容器
docker rm [OPTIONS] CONTAINER [CONTAINER...]
docker container rm [OPTIONS] CONTAINER [CONTAINER...]

正在运行的容器不让删但是可以 -f 强制删除
bash
删除所有容器
docker rm -f `docker ps -a -q`
删除所有暂停的容器
docker rm `docker ps -qf status=exited`
(四)容器的启动和停止
docker start|stop|restart|pause|unpause 容器ID
stop和pause的区别
**1.docker stop(停止容器)------ 彻底终止,释放资源
docker stop 是 "永久性" 的停止(可恢复),核心是终止容器内的所有进程,释放服务器资源****2.docker pause(暂停容器)------ 临时冻结,快速恢复
docker pause 是 "临时性" 的暂停,核心是冻结进程但不终止,适合短时间暂停容器:**
(五)给正在运行的容器发信号
docker kill [OPTIONS] CONTAINER [CONTAINER...]
(六)进入正在运行的容器
attach命令一般不会用,互相会有干扰
exec 命令
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
bashroot@ubuntu10:~ docker exec -it nginx1 bash #-it 进入交互页面 root@9cabd8459636:/
(七)传递环境变量
有些容器运行时,需要传递变量,可以使用 -e <参数> 或 --env-file <参数文件> 实现
bash
docker run -p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_DATABASE=wordpress \
-e MYSQL_USER=wordpress \
-e MYSQL_PASSWORD=123456 \
--name mysql \
-d \
--restart=always \
registry.cn-beijing.aliyuncs.com/wangxiaochun/mysql:8.0.29-oracle
通过docker run命令启动一个 MySQL 8.0.29 容器,配置 root 密码、自定义数据库 / 用户,映射 3306 端口并设置开机自启
这种变量多的可以直接写到文件中,用--env-file <参数文件> 实现

(八)暴露所有容器端口
容器启动后,默认处于预定义的NAT网络中,所以外部网络的主机无法直接访问容器中网络服务docker run -P 可以将事先容器预定义的所有端口映射宿主机的网卡的随机端口,默认从32768开始使用随机端口 时,当停止容器后再启动可能会导致端口发生变化
bash
root@ubuntu10:~ docker run -d --name wordpress -P wordpress:php8.4-apache
ec9c48e9d8b9a2a5e9ad9ab2e9acd974be26781eebdc364883cca05b28b340b4
root@ubuntu10:~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec9c48e9d8b9 wordpress:php8.4-apache "docker-entrypoint.s..." 4 seconds ago Up 4 seconds 0.0.0.0:32768->80/tcp, [::]:32768->80/tcp
开启端口之后就可以通过外部主机比如Windows去实现访问

(九)指定端口映射
docker run -p 可以将容器的预定义的指定端口映射到宿主机的相应端口
bash
root@ubuntu10:~ docker run -d --name wordpress -p 80:80 wordpress:php8.4-apache

这里把数据库的端口也做暴露的话就可以直接填写宿主机的IP地址
bash
root@ubuntu10:~ docker run -d --name mysql -p 3306:3306 --env-file env.txt mysql:9.3.0-oracle
ef076e0cb28332e273f89beab25db398d15e8b4bec2c91adb5d1f9350ebf9eaa
root@ubuntu10:~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ef076e0cb283 mysql:9.3.0-oracle "docker-entrypoint.s..." 13 seconds ago Up 12 seconds 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060/tcp mysql
38eacbe85cdc wordpress:php8.4-apache "docker-entrypoint.s..." 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp, [::]:80->80/tcp wordpress

(十)容器内部的hosts文件
默认情况下
bash
root@ubuntu10:~ docker exec -it nginx01 bash
root@25e5f065fd1d:/ cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00:: ip6-localnet
ff00:: ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 25e5f065fd1d
--add-host 域名:IP地址;可以直接加入配置
bash
root@ubuntu10:~ docker run -d --name nginx02 -p 81:80 --add-host www.test.com:1.1.1.1 nginx:1.24.0
be61bf5725f9aa8e6b8e7f25163797d6a360be88bd83fbc8c176b22d951455d4
root@ubuntu10:~ docker exec -it nginx02 bash
root@be61bf5725f9:/ cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00:: ip6-localnet
ff00:: ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
1.1.1.1 www.test.com
172.17.0.4 be61bf5725f9
(十一)指定容器 DNS
--dns
bash
docker run -it --rm --dns 1.1.1.1 --dns 8.8.8.8 nginx
(十二)容器内和宿主机之间复制文件
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
-a, --archive 归档模式(复制所有的用户 ID / 组 ID 信息)
-L/--follow-link 始终跟随源路径(SRC_PATH)中的符号链接
bash
root@ubuntu10:~ docker cp /etc/issue nginx02:/tmp
Successfully copied 2.05kB to nginx02:/tmp
root@ubuntu10:~ docker exec nginx02 cat /tmp/issue
Ubuntu 24.04.3 LTS \n \l
(十三)清除不再使用的数据
docker system prune
bash
root@ubuntu10:~ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
be61bf5725f9 nginx:1.24.0 "/docker-entrypoint...." 28 minutes ago Up 28 minutes 0.0.0.0:81->80/tcp, [::]:81->80/tcp nginx02
25e5f065fd1d nginx:1.24.0 "/docker-entrypoint...." 33 minutes ago Up 33 minutes 0.0.0.0:80->80/tcp, [::]:80->80/tcp nginx01
ef076e0cb283 mysql:9.3.0-oracle "docker-entrypoint.s..." About an hour ago Up About an hour 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060/tcp mysql
root@ubuntu10:~ docker stop nginx01
nginx01
root@ubuntu10:~ docker system prune
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all dangling images
- unused build cache
Are you sure you want to continue? [y/N] y
Deleted Containers:
25e5f065fd1d06d67df65a64804bc9a5ccb06efdfa56952356026238103a204f
Total reclaimed space: 86.02kB
root@ubuntu10:~ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
be61bf5725f9 nginx:1.24.0 "/docker-entrypoint...." 29 minutes ago Up 29 minutes 0.0.0.0:81->80/tcp, [::]:81->80/tcp nginx02
ef076e0cb283 mysql:9.3.0-oracle "docker-entrypoint.s..." About an hour ago Up About an hour 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060/tcp mysql
(十四)导出和导出容器文件系统
docker export:此命令是用于将一个运行的或者停止的容器的文件系统导出为一个 tar 归档文件。
docker save:此命令用于将一个或多个镜像导出为一个 tar 归档文件。
docker save 和 docker export
镜像 --> docker save > tar file --> docker load -->镜像
docker export 和 docker import(不怎么用,会丢失很多属性)
容器 --> docker export > tar file --> docker import -->镜像
(十五)利用 Docker 快速部署自动化运维平台
时巴克Spug
官方说明:https://www.spug.cc/docs/install-docker/
1.安装docker
2.拉取镜像
bash
root@ubuntu10:~ docker run -d --restart=always --name=spug -p 80:80 registry.aliyuncs.com/openspug/spug
3.初始化
bash
docker exec spug init_spug admin 123456
(十六)查看 docker run 启动参数命令
如果想用同种方式启动但是又不知道前一个启动时命令是什么的情况下,可以使用 runlike工具实现
bash
#安装方式1: pip
apt install -y python3-pip
pip3 install runlike
#安装方法2: by docker,给个别名
root@ubuntu10:~ alias runlike="docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike"
测试
root@ubuntu10:~ runlike -p spug
docker run --name=spug \
--hostname=6ffe698b7a88 \
--mac-address=92:d6:24:e5:2b:11 \
--volume /data \
--network=bridge \
-p 80:80 \
--restart=always \
--runtime=runc \
--detach=true \
registry.aliyuncs.com/openspug/spug
四、基于CRIU实现容器热迁移
(一)理论
Docker容器热迁移是指在不停止或中断容器的情况下,将正在运行的Docker容器从一个主机迁移到另一个主机的过程。此过程确保了服务的高可用性,特别适用于负载均衡和故障转移场景。
CRIU(Checkpoint/Restore In Userspace)是一款 Linux 软件。它可以冻结正在运行的容器(或单个应用程序)并将其状态检查点到磁盘。
官方文档:https://docs.docker.com/reference/cli/docker/checkpoint/#using-checkpoint-and-restore
主要步骤可以分成三步:
1.创建检查点:
bashdocker checkpoint create <container_name><checkpoint_name>2.导出检查点:
将检查点文件导出到另一个主机。
Docker的检查点文件通常存储在
var/Iib/docker/containers/<container._id/checkpoints/目录下。每个检查点会生成-组文件,包括元数据文件和内存快照文件
rsync -avz
/var/lib/docker/containers/<container_id>/checkpoints/checkpoint1/user@target_host:/path/to/destination/
scp -r /var/lib/docker/containers/<container_id>/checkpoints/checkpoint1/user@target_host:/path/to/destination/
3.在日标主机上恢复容器:
bashdocker start --checkpoint=<checkpoint_name><container_name>
(二)具体实践
1.环境准备
安装 criu
安装 docker
配置 docker 支持CRIU(目前还是实验功能所以需要开启相关配置)
2.ubuntu环境
Ubuntu24.04默认没有criu包,需要添加安装源
bash
add-apt-repository ppa:criu/ppa -y
apt update
apt install criu docker.io -y
Ubuntu22.04默认有criu包
bash
apt update && apt install -y docker.io criu
默认情况下没有开启这个功能
bash
root@ubuntu10:~ docker checkpoint
docker checkpoint is only supported on a Docker daemon with experimental features enabled
启动CRIU功能
bash
root@ubuntu10:/etc/docker cat /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.1panel.live",
"https://docker.1ms.run",
"https://docker.xuanyuan.me"
],
"experimental":true
}
systemctl restart docker
root@ubuntu10:~ docker checkpoint
Usage: docker checkpoint COMMAND
Manage checkpoints
Commands:
create Create a checkpoint from a running container
ls List checkpoints for a container
rm Remove a checkpoint
Run 'docker checkpoint COMMAND --help' for more information on a command.
3.启动运行一个需要热迁移的容器
bash
root@ubuntu12:~ docker run --restart always --name cr -d registry.cn-beijing.aliyuncs.com/wangxiaochun/busybox:1.32.0 /bin/sh -c 'i=0; while true; do echo $i `date +%F_%T` ; i=$(expr $i + 1); sleep 1; done'
root@ubuntu12:~ docker logs -f cr
0 2026-01-20_05:32:50
1 2026-01-20_05:32:51
2 2026-01-20_05:32:52
3 2026-01-20_05:32:53
4 2026-01-20_05:32:54
5 2026-01-20_05:32:55
6 2026-01-20_05:32:56
......
4.备份
创建checkpoint快照10.0.0.12主机
方法1:checkpoint数据指定生成文件所在目录
bash
docker checkpoint create --checkpoint-dir /srv/ cr checkpoint1
不是使用的默认路径需要指定路径才能看到checkpoint
bash
docker checkpoint ls cr --checkpoint-dir /srv/
5.还原
10.0.0.10主机
bash
创建容器
docker create --restart always --name cr registry.cn-beijing.aliyuncs.com/wangxiaochun/busybox:1.32.0 /bin/sh -c 'i=0; while true; do echo $i `date +%F_%T` ; i=$(expr $i + 1); sleep 1; done'
主机上新的文件地址
root@ubuntu10:~ docker inspect --format "{{.ID}}" cr
7554de8d81185452fa1c07f214e235a01ee0025028e09151990d668e9711d54a
root@ubuntu10:~ ls /var/lib/docker/containers/
6ffe698b7a888238b42296bba6820ab46d1b2a1d847c74f488f7e31cae27061c be61bf5725f9aa8e6b8e7f25163797d6a360be88bd83fbc8c176b22d951455d4
7554de8d81185452fa1c07f214e235a01ee0025028e09151990d668e9711d54a ef076e0cb28332e273f89beab25db398d15e8b4bec2c91adb5d1f9350ebf9eaa
root@ubuntu10:~ ls /var/lib/docker/containers/7554de8d81185452fa1c07f214e235a01ee0025028e09151990d668e9711d54a/
checkpoints config.v2.json hostconfig.json
接下来就需要将10.0.0.12的checkpoints文件内容放入10.0.0.10主机之中
bash
root@ubuntu10:/var/lib/docker/containers/7554de8d81185452fa1c07f214e235a01ee0025028e09151990d668e9711d54a/checkpoints# scp -r 10.0.0.12:/srv/checkpoint1 .
root@ubuntu10:/var/lib/docker/containers/7554de8d81185452fa1c07f214e235a01ee0025028e09151990d668e9711d54a/checkpoints# ls checkpoint1/
cgroup.img fdinfo-2.img fs-1.img ipcns-var-11.img pagemap-1227.img pstree.img tmpfs-dev-84.tar.gz.img tmpfs-dev-88.tar.gz.img
core-1227.img fdinfo-3.img ids-1227.img mm-1227.img pagemap-1.img seccomp.img tmpfs-dev-85.tar.gz.img utsns-12.img
core-1.img files.img ids-1.img mm-1.img pages-1.img timens-0.img tmpfs-dev-86.tar.gz.img
descriptors.json fs-1227.img inventory.img mountpoints-13.img pages-2.img tmpfs-dev-81.tar.gz.img tmpfs-dev-87.tar.gz.img
root@ubuntu10:/var/lib/docker/containers/7554de8d81185452fa1c07f214e235a01ee0025028e09151990d668e9711d54a/checkpoints# docker checkpoint ls cr
CHECKPOINT NAME
checkpoint1
root@ubuntu10:/var/lib/docker/containers/7554de8d81185452fa1c07f214e235a01ee0025028e09151990d668e9711d54a/checkpoints# docker start --checkpoint checkpoint1 cr
观察日志说明容器是接着上前面的继续执行
docker logs -f cr
五、Docker 镜像制作
docker依赖的核心技术:
1)namespace 名称空间;为容器打造独立的资源视图(进程、网络、文件系统等),让容器 "自成一体"
2)control group 控制组;控制容器能使用的资源上限(CPU、内存等),避免资源抢占
3)storage driver:overlay2 联合文件系统;基于联合文件系统实现镜像分层存储
(一)基于容器手动制作镜像步骤
一种是基于现有的容器commit来制作,主要是第二种用dockerfile来实现镜像制作
基于 alpine 定制新的镜像
bash
root@ubuntu10:~ docker run -it --name test01 registry.cn-beijing.aliyuncs.com/wangxiaochun/alpine:3.20.0 sh
时区不是中国的,curl命令没有
/ # date
Tue Jan 20 07:39:20 UTC 2026
/ # curl
sh: curl: not found
目前的下载源是国外的,改到国内的源
bash
/ # cat /etc/apk/repositories
https://dl-cdn.alpinelinux.org/alpine/v3.20/main
https://dl-cdn.alpinelinux.org/alpine/v3.20/community
/ # sed -i 's@dl-cdn.alpinelinux.org@mirrors.tuna.tsinghua.edu.cn@' /etc/apk/repositories
/ # cat /etc/apk/repositories
https://mirrors.tuna.tsinghua.edu.cn/alpine/v3.20/main
https://mirrors.tuna.tsinghua.edu.cn/alpine/v3.20/community

修改时区
bash
apk update && apk --no-cache add tzdata curl && ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezone
/ # date
Tue Jan 20 15:56:40 CST 2026
手动制作镜像
bash
root@ubuntu10:~ docker commit test01 alpine:3.20.0-`date +%F`
root@ubuntu10:~ docker images
i Info → U In Use
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
alpine:3.20.0-2026-01-20 e86a60b67107 71.7MB 18.4MB
(二)利用 DockerFile 文件执行 docker build 自动构建镜像
Dockerfile 相关指令
常用的命令:
FROM
LABEL
RUN
ADD
COPY
CMD
ENTRYPOINT
ENV
EXPOSE
USER
VOLUME
WORKDIR

1.FROM: 指定基础镜像
格式:
FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
bash
FROM ubuntu
2.LABEL: 指定镜像元数据
可以指定镜像元数据,如: 镜像作者等
LABEL <key>=<value> <key>=<value> <key>=<value> ...
3.RUN: 执行 shell 命令
默认情况下是 sh shell环境中
#shell 格式: 相当于 /bin/sh -c <命令> 此种形式支持环境变量
RUN <命令>
#如果想使用其它shell,可以用SHELL指令指定不同的shell
SHELL ["/bin/bash", "-c"]
RUN <命令>
#exec 格式: 此种形式不支持环境变量,注意:是双引号,不能是单引号
RUN ["executable","param1","param2"...]
#exec格式可以指定其它shell
RUN ["/bin/bash","-c","echo hello wang"]
RUN <<EOFdd if=/dev/zero of=/tmp/f1.img bs=1M
rm -f /tmp/f1.img
EOF
4.ENV: 设置环境变量
ENV <key1>=<value1> <key2>=<value2> \
#此格式可以支持多个key赋值,定义多个变量建议使用,减少镜像层
#如果<value>中包含空格,可以以反斜线\进行转义,也可通过对<value>加引号进行标识;另外,反斜线也可用于续行
5.COPY: 复制文本
复制本地宿主机的 到容器中的 。
COPY [OPTIONS] [--chown=<user>:<group>] <src>... <dest>
COPY [OPTIONS] [--chown=<user>:<group>] ["<src>",... "<dest>"]
#路径中有空白字符时,建议使用此格式
注意:必须是build上下文中的相对路径(为 Dockerfile 所在目录的相对路径)
6.ADD: 复制和解包文件
该命令可认为是增强版的COPY,不仅支持COPY,还支持自动解压缩。
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
注意:1.可以是Dockerfile所在目录的一个相对路径;也可是一个 URL;还可是一个 tar 文件(自动解压)
2.可以是绝对路径或者是 WORKDIR 指定的相对路径
3.如果是目录,只复制目录中的内容,而非目录本身
4.如果是一个 URL ,下载后的文件权限自动设置为 600
5.如果为URL且不以/结尾,则指定的文件将被下载并直接被创建为,如果以 / 结尾,则文件名URL指定的文件将被直接下载并保存为/< filename>
6.如果是一个本地文件系统上的打包文件,如: gz, bz2 ,xz ,它将被解包 ,其行为类似于"tar -x"命令,但是通过URL获取到的tar文件将不会自动展开
7.如果有多个,或其间接或直接使用了通配符,则必须是一个以/结尾的目录路径;如果不以/结尾,则其被视作一个普通文件
7.CMD: 容器启动命令
一个容器中通常需要一个持续运行的业务主进程
CMD 用来指定启动容器时默认执行的一个初始命令
如果容器内没有一个持续运行的前台进程,容器会停止
所以一般CMD 指定的命令为持续运行且为前台命令,如果有多个命令,需要保证有一个命令是前台并持续运行的
bash#格式1:使用exec形式,推荐方式,第一个参数必须是命令的全路径,此种形式不支持环境变量,注意:是双引号,不能是单引号 CMD ["executable","param1","param2"] #格式2:shell形式,默认/bin/sh 中执行,提供给需要交互的应用;此种形式支持环境变量,相当于执行/bin/sh -c "command param1 param2" CMD command param1 param2 #指定不同的shell #方法1 SHELL ["/bin/bash", "-c"] CMD command param1 param2 #方法2 CMD ["/bin/bash", "-c","executable","param1","param2"] #格式3:使用exec形式,提供给 ENTRYPOINT 命令的充当其参数 CMD ["param1","param2"]
8. ENTRYPOINT: 入口点
主要是和CMD一起用,和CMD共同存在时,ENTRYPOINT实现容器启动命令,CMD会变成ENTRYPOINT的参数;
由下方案例脚本方法二的例子不难看出:CMD实现容器启动命令,ENTRYPOINT实现环境初始化
9.SHELL: 指定 Shell 类型
SHELL ["executable", "parameters"]
该指令允许默认 shell 用于 shell 形式的 要覆盖的命令。
Linux 上的默认 shell 是 ["/bin/sh", "-c"]
Windows 上的默认 shell 是["cmd", "/S", "/C"]``
该指令可以多次出现。每条指令都覆盖 所有先前的指令,并影响所有后续指令。
bash
SHELL ["bash", "-c"]
CMD test.sh
#相当于实现: bash -c test.sh
10.ARG: 构建参数
ARG指令在build 阶段指定变量
和ENV不同的是,容器运行时并不存在ARG定义的环境变量
ARG <name>[=<default value>]
bash
在FROM之前声明的ARG在构建阶段之外,所以它不能在FROM之后的任何指令中使用。 要使用在第一个FROM之前声明的ARG的默认值,请在构建阶段内使用没有值的ARG指令
#示例:
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version
11. VOLUME: 匿名卷
在容器中创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等,默认会将宿主机上的目录挂载至VOLUME 指令指定的容器目录。
即使容器后期被删除,此宿主机的目录仍会保留,从而实现容器数据的持久保存。
VOLUME <容器内路径>
VOLUME ["<容器内路径1>", "<容器内路径2>"...]
注意:
<容器内路径>如果在容器内不存在,在创建容器时会自动创建
<容器内路径>如果是存在的,同时目录内有内容,将会把此目录的内容复制到宿主机的实际目录
bash
FROM alpine:3.11
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
COPY repositories /etc/apk/repositories
VOLUME [ "/testdata","/testdata2" ]
比较鸡肋,下面有专门的持久化服务
12.EXPOSE: 暴露端口
EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会真正暴露端口,即不会自动在宿主进行端口映射因此,在启动容器时需要通过 -P 或 -p ,Docker 主机才会真正分配一个端口转发到指定暴露的端口才可使用
EXPOSE <port>[/ <protocol>] [<port>[/ <protocol>] ..]
#说明
<protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议
bash
EXPOSE 80 443
EXPOSE 11211/udp 11211/tcp
13.WORKDIR: 指定工作目录
为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录,当容器运行后,进入容器内WORKDIR指定的默认目录
bash
#两次RUN独立运行,不在同一个目录
RUN cd /app
RUN echo "hello" > world.txt
#如果想实现相同目录
RUN cd /app && echo "hello" > world.txt
#可以使用WORKDIR
WORKDIR /app
RUN echo "hello" > world.txt
14.ONBUILD: 子镜像引用父镜像的指令
可以用来配置当构建当前镜像的子镜像时,会自动触发执行的指令,但在当前镜像构建时,并不会执行,即延迟到子镜像构建时才执行
bash
例如,Dockerfile 使用如下的内容创建了镜像 image-A。
ONBUILD ADD http://www.wang.com/wp-content/uploads/2017/09/logo.png /data/
ONBUILD RUN rm -rf /*
ONBUILD RUN /usr/local/bin/python-build --dir /app/src...
15.USER: 指定当前用户
bash
USER <user>[:<group>]
USER <UID>[:<GID>]
16.HEALTHCHECK: 健康检查
bash
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s CMD curl -fs http://localhost/
17. STOPSIGNAL: 退出容器的信号
该 STOPSIGNAL 指令设置将被发送到容器退出的系统调用信号。它指定在docker stop 停止容器时发送给主进程的信号。
指定停止信号:通过在 Dockerfile 中使用 STOPSIGNAL 指令,你可以指定在执行 docker stop命令时发送给主进程的信号。例如,如果你希望使用 SIGINT 信号而不是默认的 SIGTERM ,可以在 Dockerfile 中这样写:
bash
STOPSIGNAL SIGINT
优化手段:
dockerfile 的优化手段:
1.尽可能将多个指令合并为一个指令,减少层数,减小镜像大小
2.将变化频繁的指令放在DockerFile文件的后面,有助于利用cache,加速制作镜像的速度
3.选择合适的父镜像 FROM
4.多阶段构建,减小体积
(三)基于 Alpine 基础镜像制作 Nginx 源码编译镜像
1.整体架构

可以根据实际情况建立文件夹
bash
root@ubuntu10:~ mkdir /data/dockerfile/{os/{alpine,debian,ubuntu},web/{jdk,nginx,tomcat}} -p
root@ubuntu10:~ tree /data/
/data/
└── dockerfile
├── os
│ ├── alpine
│ ├── debian
│ └── ubuntu
└── web
├── jdk
├── nginx
└── tomcat
bash
root@ubuntu10:/data/dockerfile/web/nginx# docker pull alpine:3.20.0
root@ubuntu10:/data/dockerfile/web/nginx# docker tag alpine:3.20.0 alpine:3.20.0-base
编写dockerfile文件
bash
root@ubuntu10:/data/dockerfile/os/alpine# cat Dockerfile
FROM alpine:3.20.0
LABEL author=lty version=0.1
RUN sed -i 's@dl-cdn.alpinelinux.org@mirrors.tuna.tsinghua.edu.cn@' /etc/apk/repositories && \
apk update && \
apk --no-cache add tzdata curl bash && \
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezone
应用可以分目录放置方便管理
bash
root@ubuntu10:/data/dockerfile/web/nginx# cat Dockerfile
FROM alpine:3.20.0-base
ENV NGINX_VERSION=1.24.0
ADD nginx-$NGINX_VERSION.tar.gz /usr/local/src/
RUN sed -i 's@dl-cdn.alpinelinux.org@mirrors.tuna.tsinghua.edu.cn@' /etc/apk/repositories && \
apk update && \
apk --no-cache add tzdata gcc make curl zip unzip net-tools pstree wget libgcc musl-dev libcurl \
musl-utils pcre-dev zlib-dev pcre pcre2 libevent libevent-dev iproute2 && \
addgroup -g 888 -S nginx && adduser -s /sbin/nologin -S -D -u 888 -G nginx nginx && \
cd /usr/local/src/nginx-$NGINX_VERSION && ./configure --prefix=/usr/local/nginx && make && make install && \
ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx && \
chown -R nginx:nginx /usr/local/nginx/ && rm -rf /usr/local/src/nginx-$NGINX_VERSION
USER nginx
CMD ["nginx","-g","daemon off;"]
bash
root@ubuntu10:/data/dockerfile/os/alpine# tree /data/dockerfile/
/data/dockerfile/
├── os
│ ├── alpine
│ │ └── Dockerfile
│ ├── debian
│ └── ubuntu
└── web
├── jdk
├── nginx
│ ├── Dockerfile
│ ├── nginx-1.24.0.tar.gz
└── tomcat
建立镜像并启动容器
bash
docker build -t nginx:1.24.0-alpine-3.20.0-base .
启动容器
docker run -d --name mynginx -p 80:80 nginx:1.24.0-alpine-3.20.0-base

2.为了实现更好的复用可以修改一下nginx的配置
更改nginx的配置文件;把容器里面的配置文件复制出来
bash
root@ubuntu10:/data/dockerfile/web/nginx# docker cp mynginx:/usr/local/nginx/conf/nginx.conf .
Successfully copied 4.61kB to /data/dockerfile/web/nginx/.
root@ubuntu10:/data/dockerfile/web/nginx# ls
CHANGES-1.24 Dockerfile nginx.conf
root@ubuntu10:/data/dockerfile/web/nginx# vim nginx.conf
......
# location / {
# root html;
# index index.html index.htm;
# }
#}
include /usr/local/nginx/conf.d/*.conf; #加上这一条
}
修改Dockerfile文件,把修改的文件放入容器中
bash
root@ubuntu10:/data/dockerfile/web/nginx# vim Dockerfile
FROM alpine:3.20.0-base
ENV NGINX_VERSION=1.24.0
ADD nginx-$NGINX_VERSION.tar.gz /usr/local/src/
RUN apk update && apk --no-cache add tzdata gcc make curl bash zip unzip net-tools pstree wget libgcc musl-dev libcurl \
musl-utils pcre-dev zlib-dev pcre pcre2 libevent libevent-dev iproute2 && \
addgroup -g 888 -S nginx && adduser -s /sbin/nologin -S -D -u 888 -G nginx nginx && \
cd /usr/local/src/nginx-$NGINX_VERSION && ./configure --prefix=/usr/local/nginx && make && make install && \
ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx && \
chown -R nginx:nginx /usr/local/nginx/ && rm -rf /usr/local/src/nginx-$NGINX_VERSION
COPY nginx.conf /usr/local/nginx/conf/nginx.conf #增加这一行
USER nginx
CMD ["nginx","-g","daemon off;"]
验证是否修改成功
bash
root@ubuntu10:/data/dockerfile/web/nginx# docker exec mynginx nginx -T
......
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
include /usr/local/nginx/conf.d/*.conf;
}
......

这样一个基本的nginx镜像就做完了,如果想要有其他的nginx业务就可以直接加一个 *.conf 的文件在里面去
3.例如有一个新的业务web01
bash
root@ubuntu10:/data/dockerfile/web/web01# vim www.lty.org.conf
server{
listen 80;
server_name www.lty.org;
root /data/website;
}
echo lty website in docker > index.html
bash
root@ubuntu10:/data/dockerfile/web/web01# tree /data/dockerfile/
/data/dockerfile/
├── os
│ ├── alpine
│ │ └── Dockerfile
│ ├── debian
│ └── ubuntu
└── web
├── jdk
├── nginx
│ ├── Dockerfile
│ ├── nginx-1.24.0.tar.gz
│ └── nginx.conf
├── tomcat
└── web01
├── Dockerfile
├── index.html #新增的web页面
└── www.lty.org.conf #新增的配置文件
编写一个Dockerfile文件
bash
root@ubuntu10:/data/dockerfile/web/web01# vim Dockerfile
FROM nginx:1.24.0-alpine-3.20.0-base
COPY www.lty.org.conf /user/local/nginx/conf.d/www.lty.org.conf
COPY index.html /data/website/index.html
建立镜像
bash
root@ubuntu10:/data/dockerfile/web/web01# docker build -t web01-nginx:1.24.0-alpine-3.20.0-base .
在Windows上访问
bash
curl -H"host:www.lty.org" 10.0.0.10:88
lty website in docker
4.假如有很多相类似的镜像
bash
root@ubuntu10:/data/dockerfile/web# cp web01 myweb -r
root@ubuntu10:/data/dockerfile/web# ll myweb/
总计 20
drwxr-xr-x 2 root root 4096 1月 20 22:46 ./
drwxr-xr-x 7 root root 4096 1月 20 22:46 ../
-rw-r--r-- 1 root root 142 1月 20 22:46 Dockerfile
-rw-r--r-- 1 root root 22 1月 20 22:46 index.html
-rw-r--r-- 1 root root 69 1月 20 22:46 www.lty.org.conf
可以通过编写 shell 脚本去实现;例如下面的域名和网页内容实现一个变化
方法一:
bash
root@ubuntu10:/data/dockerfile/web/myweb# vim nginx.sh
mkdir -p /usr/local/nginx/conf/conf.d /data/website
cat > /usr/local/nginx/conf/conf.d/www.conf <<EOF
server {
listen ${PORT:-80};
server_name ${SERVER:-www.wang.org};
root /data/website;
}
EOF
echo ${SERVER:-www.wang.org} > /data/website/index.html
nginx -g 'daemon off;'
root@ubuntu10:/data/dockerfile/web/myweb# chmod +x nginx.sh #注意要给它加上执行权限!!!
bash
root@ubuntu10:/data/dockerfile/web/myweb# cat Dockerfile
FROM nginx:1.24.0-alpine-3.20.0-base
#COPY www.lty.org.conf /user/local/nginx/conf.d/www.lty.org.conf
#COPY index.html /data/website/index.html
COPY nginx.sh /usr/local/bin/nginx.sh
CMD ["nginx.sh"]
方法二(引入ENTRYPOINT):
bash
root@ubuntu10:/data/dockerfile/web/myweb# vim nginx.sh
#!/bin/bash
mkdir -p /usr/local/nginx/conf/conf.d /data/website
cat > /usr/local/nginx/conf/conf.d/www.conf <<EOF
server {
listen ${PORT:-80};
server_name ${SERVER:-www.wang.org};
root /data/website;
}
EOF
echo ${SERVER:-www.wang.org} > /data/website/index.html
#nginx -g 'daemon off;' #可以把这个放到dockerfile文件之中
exec "$@" # exec 用指定命令替换当前 Shell 进程;把传递给脚本的所有参数当作一个完整的命令,替换当前脚本进程来执行这个命令。例如:下面的dockerfile本来是输出 nginx.sh nginx -g daemo off;加了一个 exec "$@" 后,就是输出 nginx -g daemo off;
bash
root@ubuntu10:/data/dockerfile/web/myweb# cat Dockerfile
FROM nginx:1.24.0-alpine-3.20.0-base
#COPY www.lty.org.conf /user/local/nginx/conf.d/www.lty.org.conf
#COPY index.html /data/website/index.html
COPY nginx.sh /usr/local/bin/nginx.sh
CMD ["nginx","-g","daemon off;"]
ENTRYPOINT ["nginx.sh"]
建立镜像并运行容器
bash
root@ubuntu10:/data/dockerfile/web/myweb# docker build -t mynginx:1.24.0-alpine-3.20.0-base .
启动容器
root@ubuntu10:/data/dockerfile/web/myweb# docker run -d --name mynginx01 -e SERVER=www.a.com -p 81:80 www-nginx:1.24.0-alpine-3.20.0-base
385fe53cc6f283419ed3b5ceb37183c4be1255e1ca1529c5c1c85f0d72130c7b
root@ubuntu10:/data/dockerfile/web/myweb# docker run -d --name mynginx02 -e SERVER=www.b.com -p 82:80 www-nginx:1.24.0-alpine-3.20.0-base
682dd690669560c261d721c0fdcca49a5c0036efcf06537a5035eb730f12b18e
root@ubuntu10:/data/dockerfile/web/myweb# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
682dd6906695 mynginx:1.24.0-alpine-3.20.0-base "nginx.sh" 8 seconds ago Exited (255) 7 seconds ago mynginx02
385fe53cc6f2 mynginx:1.24.0-alpine-3.20.0-base "nginx.sh" 40 seconds ago Exited (255) 39 seconds ago mynginx01
在Windows上访问测试

bash
root@ubuntu10:/data/dockerfile/web/myweb# tree /data/dockerfile/
/data/dockerfile/
├── os
│ ├── alpine
│ │ └── Dockerfile
│ ├── debian
│ └── ubuntu
└── web
├── jdk
├── myweb
│ ├── Dockerfile
│ ├── index.html
│ ├── nginx.sh
│ └── www.conf
├── nginx
│ ├── Dockerfile
│ ├── nginx-1.24.0.tar.gz
│ └── nginx.conf
├── tomcat
└── web01
├── Dockerfile
├── index.html
└── www.lty.org.conf
(四)多阶段构建
bash
第一次构建,执行编译等,用于生成必要的程序
FROM <image> [AS <name>]
构建过程生成结果文件
第二次构建
FROM <image>
COPY --from=<name>] 前一次构建的路径src 前二次构建的路径dest
COPY --from=0 前一次构建的路径src 前二次构建的路径dest
多阶段构建实现基于Alpine的Nginx的编译安装
bash
root@ubuntu10:/data/dockerfile/web# cp nginx/ nginx-multi -r
root@ubuntu10:/data/dockerfile/web# cd nginx-multi/
root@ubuntu10:/data/dockerfile/web/nginx-multi# ls
Dockerfile nginx-1.24.0.tar.gz nginx.conf
建立Dockerfile文件
bash
root@ubuntu10:/data/dockerfile/web/nginx-multi# vim Dockerfile
ARG VERSION=3.20.0
FROM alpine:$VERSION
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ENV NGINX_VERSION=1.24.0ENV NGINX_DIR=/apps/nginx
ADD nginx-$NGINX_VERSION.tar.gz /usr/local/src
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/' /etc/apk/repositories && \
apk update && apk --no-cache add gcc make libgcc libc-dev libcurl libc-utils pcre-dev zlib-dev libnfs pcre pcre2 net-tools curl pstree wget libevent libevent-dev iproute2 openssl-dev && \
cd /usr/local/src/nginx-$NGINX_VERSION && \
./configure --prefix=${NGINX_DIR} --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module && \
make && make install && \
rm -rf /usr/local/src/nginx-$NGINX_VERSION
COPY nginx.conf ${NGINX_DIR}/conf/nginx.conf
FROM alpine:$VERSION
ENV NGINX_DIR=/apps/nginx
COPY --from=0 ${NGINX_DIR}/ ${NGINX_DIR}/
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/' /etc/apk/repositories \
&& apk update && apk --no-cache add tzdata curl pcre pcre2 \
&& ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& ln -sf ${NGINX_DIR}/sbin/nginx /usr/sbin/nginx \
&& addgroup -g 888 -S nginx \
&& adduser -u 888 -G nginx -D -S -s /sbin/nologin nginx \
&& chown -R nginx:nginx ${NGINX_DIR}/ \
&& ln -sf /dev/stdout ${NGINX_DIR}/logs/access.log \
&& ln -sf /dev/stderr ${NGINX_DIR}/logs/error.log
EXPOSE 80 443
CMD ["nginx","-g","daemon off;"]
六、数据管理
数据的持久化
容器的生命周期短暂
容器的持久化数据不放在容器的专用目录下UpperDir,放在和容器无关的宿主机目录下
1.数据卷使用方法
方式1: 绑定挂载(Bind Mount)
#指定宿主机目录或文件格式:
-v <宿主机绝对路径的目录(文件)或者相对路径的文件>:<容器目录或文件>[:ro]
#将宿主机目录挂载容器目录,两个目录都可自动创建
#注意:如果初始容器中有旧数据,将被宿主机目录覆盖
#注意:如果挂载文件,必须指定文件的相对(以.开头的相对路径)或绝对路径,否则会将目录名或文件名当成命名卷
方式2: 匿名卷
#匿名卷,只指定容器内路径,没有指定宿主机路径信息,宿主机自动生成/var/lib/docker/volumes/<卷ID>/_data目录,并挂载至容器指定路径
#注意:如果初始容器中有旧数据,将被复制到宿主机数据卷目录 -v <容器内路径>
#示例:
docker run --name nginx -v /etc/nginx nginx
方式3: 命名卷
#命名卷将固定的存放在/var/lib/docker/volumes/<卷名>/_data
#注意:如果初始容器中有旧数据,将被复制到宿主机数据卷目录-v <卷名>:<容器目录路径>
#可以通过以下命令事先创建,如可没有事先创建卷名,docker run时也会自动创建卷docker volume create <卷名>
#示例:
docker volume create vol1 #也可以事先不创建
docker run -d -p 80:80 --name nginx01 -v vol1:/usr/share/nginx/html nginx
2.实现 wordpress 持久化
bash
docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=123456 --name mysql -d -v /data/mysql:/var/lib/mysql --restart=always registry.cn-beijing.aliyuncs.com/wangxiaochun/mysql:8.0.29-oracle
docker run -d -p 80:80 --name wordpress -v /data/wordpress:/var/www/html --restart=always registry.cn-beijing.aliyuncs.com/wangxiaochun/wordpress:php8.2-apache
七、Docker 网络管理
成对出现的网卡,一个在容器,一个在宿主机


(一)修改默认docker0网桥的网络配置
方法一:
bash
vim /etc/docker/daemon.json
{
"bip": "192.168.100.1/24",
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"]
}
方法2
bash
vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock--bip=192.168.100.1/24
systemctl daemon-reload
systemctl restart docker.service
(二)Docker 网络连接模式
Docker 的网络支持 5 种网络模式:
none
host
bridge(默认)
container
network-name
1.Bridge网络模式(默认)

bridge网络模式特点:
网络资源隔离: 不同宿主机的容器无法直接通信,各自使用独立网络
无需手动配置: 容器默认自动获取172.17.0.0/16的IP地址,此地址可以修改
可访问外网: 利用宿主机的物理网卡,SNAT连接外网
外部主机无法直接访问容器: 可以通过配置DNAT接受外网的访问
低性能较低: 因为可通过NAT,网络转换带来更的损耗
端口管理繁琐: 每个容器必须手动指定唯一的端口,容器产生端口冲容
2.Host 模式
Host 网络模式特点:
使用参数 --network host 指定
共享宿主机网络
各容器网络无隔离
网络性能无损耗
网络故障排除相对简单
容易产生端口冲突
网络资源无法分别统计
不支持端口映射
3.None 模式
none 模式特点
使用参数 --network none 指定
默认无网络功能,无法和外部通信
无法实现端口映射
适用于测试环境
4.Container 模式
Container 模式特点
使用参数 ---network container:名称或ID 指定
bash第一个容器 docker run -d --name nginx01 nginx:1.24.0 第二个容器 docker run -d --name test01 --network container:nginx01 alpine:3.20.0与宿主机网络空间隔离
空器间共享网络空间,直接使用对方的网络
第一个容器的网络可能是bridge,或none,或者host,而第二个容器模式依赖于第一个容器,它们共享网络(你是啥我是啥)
如果第一个容器停止,将导致无法创建第二个容器
第二个容器可以直接使用127.0.0.1访问第一个容器
适合频繁的容器间的网络通信
默认不支持端口映射,较少使用
5.自定义网络模式
可以支持容器间通信基于容器名直接相互双向通信
创建自定义网络:
#man docker-network-create
docker network create -d <mode> --subnet <CIDR> --gateway <网关> <自定义网络名称>
#注意mode不支持host和none,默认是bridge模式
-d <mode> 可省略,默认为bridge,支持bridge,overlay,macvlan等driver模式
查看自定义网络信息:docker network inspect <自定义网络名称或网络ID>
引用自定义网络:docker run --network <自定义网络名称> <镜像名称>
docker run --net <自定义网络名称> --ip <指定静态IP> <镜像名称>
#注意:静态IP只支持自定义网络模型
#指定自定义网络中的容器的别名
docker run --network <自定义网络名称> --network-alias list <镜像名称>
删除自定义网络:doccker network rm <自定义网络名称或网络ID>
(1)实验
创建自定义网络
bash
root@ubuntu10:~ docker network create -d bridge --subnet 172.27.0.0/16 --gateway 172.27.0.1 test-net


利用自定义的网络创建容器


(2)利用自定义网络实现 Wordpress
建立自定义网络
bash
root@ubuntu10:~ docker network create -d bridge --subnet 172.37.0.0/16 --gateway 172.37.0.100 wordpress-net
bash
建立wordpress容器
root@ubuntu10:~ docker run -d -p 80:80 --network wordpress-net --name wordpress --restart=always registry.cn-beijing.aliyuncs.com/wangxiaochun/wordpress:php8.2-apache
c389a98bbc3aa41e7869b90824c241a78facb9c7558deb230c38b2c738433969
建立mysql数据库
root@ubuntu10:~ docker run --network wordpress-net -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=123456 --name mysql -d --restart=always registry.cn-beijing.aliyuncs.com/wangxiaochun/mysql:8.0.29-oracle
b6c7402bb9505d0a4eb6aaa759c586b3908238fc303f32c4ad1564b278df2ebc

这样就可以直接写容器名方便管理
总体思路:
1.建立自定义网络
2.用自定义网络去建立容器
八、Docker Compose 容器单机编排
(一)部署docker compose
离线安装,直接从github或国内镜像站下载安装对应版本
参看说明: https://github.com/docker/compose/releases
bash
wget https://github.com/docker/compose/releases/download/v5.0.2/docker-compose-linux-x86_64
root@ubuntu10:~ install docker-compose-linux-x86_64 /usr/local/bin/docker-compose
root@ubuntu10:~ ll /usr/local/bin/docker-compose
-rwxr-xr-x 1 root root 31327024 1月 22 16:16 /usr/local/bin/docker-compose*
root@ubuntu10:~ docker compose version
Docker Compose version v5.0.1
(二)docker run 和 docker compose 文件互相转换
利用网站将docker 命令自动生成 Docker Compose
网站地址:https://www.composerize.com/
此网站不支持自定义网络的转换,需要自己写一下;例如:
bash
docker中的语言
docker network create -d bridge --subnet 172.37.0.0/16 --gateway 172.37.0.100 wordpress-net
docker compose语言
networks:
wordpress-net:
ipam:
driver: default
config:
- subnet: 172.27.0.0/16
docker run的语言
bash
建立wordpress容器
root@ubuntu10:~ docker run -d -p 80:80 --network wordpress-net --name wordpress --restart=always registry.cn-beijing.aliyuncs.com/wangxiaochun/wordpress:php8.2-apache
c389a98bbc3aa41e7869b90824c241a78facb9c7558deb230c38b2c738433969
建立mysql数据库
root@ubuntu10:~ docker run --network wordpress-net -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=123456 --name mysql -d --restart=always registry.cn-beijing.aliyuncs.com/wangxiaochun/mysql:8.0.29-oracle
b6c7402bb9505d0a4eb6aaa759c586b3908238fc303f32c4ad1564b278df2ebc
使用网页生成后自己调下格式
bash
name: wordpress
services:
mysql:
networks:
- wordpress-net
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=123456
container_name: mysql
restart: always
image: registry.cn-beijing.aliyuncs.com/wangxiaochun/mysql:8.0.29-oracle
wordpress:
ports:
- 80:80
networks:
- wordpress-net
container_name: wordpress
restart: always
image: registry.cn-beijing.aliyuncs.com/wangxiaochun/wordpress:php8.2-apache
networks:
wordpress-net:
ipam:
driver: default
config:
- subnet: 172.27.0.0/16
接下来就和容器管理差不多了
九、Docker 仓库管理
(一)Docker 之分布式仓库 Harbor
基于角色的访问控制: 用户与Docker镜像仓库通过"项目"进行组织管理,一个用户可以对多个镜像仓库在同一命名空间(project)里有不同的权限
镜像复制: 镜像可在多个Registry实例中复制(同步)。尤其适合于负载均衡,高可用,混合云和多云的场景
图形化用户界面: 用户可以通过浏览器来浏览,检索当前Docker镜像仓库,管理项目和命名空间AD/LDAP 支: Harbor可以集成企业内部已有的AD/LDAP,用于鉴权认证管理
审计管理: 所有针对镜像仓库的操作都可以被记录追溯,用于审计管理
国际化: 已拥有英文、中文、德文、日文和俄文的本地化版本。更多的语言将会添加进来
RESTful API: 提供给管理员对于Harbor更多的操控, 使得与其它管理软件集成变得更容易
部署简单: 提供在线和离线两种安装工具, 也可以安装到vSphere平台(OVA方式)虚拟设备
1.Harbor 组成

2.安装 Harbor
下载地址: https://github.com/vmware/harbor/releases
先安装 docker 和 docker-compose
bash
root@ubuntu12:~ apt update && apt install docker.io docker-compose python3-pip
bash
root@ubuntu12:~ tar xvf harbor-offline-installer-v2.14.2.tgz -C /usr/local/
root@ubuntu12:/usr/local/harbor ls
common.sh harbor.v2.14.2.tar.gz harbor.yml.tmpl install.sh LICENSE prepare
官方要求是一个yml文件,把官方案例改名
root@ubuntu12:/usr/local/harbor cp harbor.yml.tmpl harbor.yml
bash
#只需要修改下面两行
hostname = 10.0.0.12 #修改此行,指向当前主机IP 或 FQDN,建议配置IP
harbor_admin_password = 123456 #修改此行指定harbor登录用户admin的密码,默认用户/密码:admin/Harbor12345
data_volume: /data/harbor #建议修改数据目录路径,使用大容量的高速磁盘,默认为/data
#如果不使用https,还需要将下面行注释掉
#https:
# port: 443
# certificate: /your/certificate/path
# private_key: /your/private/key/path
#可选项
ui_url_protocol = http #默认即可,如果修改为https,需要指定下面证书路径
ssl_cert = /data/cert/server.crt #默认即可,https时,需指定下面证书文件路径
ss_cert_key = /data/cert/server.key #默认即可,https时,需指定下面私钥文件路径
安装docker harbor
bash
root@ubuntu12:/usr/local/harbor ./install.sh

3.修改 docker-compose.yaml文件解决地址冲突
会自动生成一个172.18.0.1地址,如果地址有冲突
bash
vim /usr/local/harbor/docker-compose.yml
networks:
harbor: #添加如下面内容
ipam:
driver: default
config:
- subnet: 172.27.0.0/16
4.可以写一个service文件方便管理
bash
root@ubuntu12:/usr/local/harbor cat /lib/systemd/system/harbor.service
[Unit]
Description=Harbor
After=docker.service systemd-networkd.service systemd-resolved.service
Requires=docker.service
Documentation=http://github.com/vmware/harbor
[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/bin/docker-compose -f /usr/local/harbor/docker-compose.yml up
ExecStop=/usr/bin/docker-compose -f /usr/local/harbor/docker-compose.yml down
[Install]
WantedBy=multi-user.target
5.使用单主机 Harbor
(1)创建用户和项目授权

创建后的用户是没有权限访问的,需要用管理员去给权限

在项目内对用户授权,注意:至少是开发者以上才能上传镜像

(2)项目推送命令

在推送之前需要登录,但是 docker 默认是走的 https 协议,需要改一下 daemon.json 文件
bash
root@ubuntu10:/data/docker-compose/wordpress# cat /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.1panel.live",
"https://docker.1ms.run",
"https://docker.xuanyuan.me"
],
"experimental":true
"insecure-registries": ["10.0.0.12"]
}
root@ubuntu10:/data/docker-compose/wordpress systemctl restart docker.service
登录
bash
root@ubuntu10:/data/docker-compose/wordpress# docker login -u lty -p L\!\@\#$%^l1 10.0.0.12
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/
Login Succeeded
上传镜像
bash
先要打标签
root@ubuntu10:/data/docker-compose/wordpress# docker tag nginx:1.24.0 10.0.0.12/example/nginx:10.0.0.12
推送
root@ubuntu10:/data/docker-compose/wordpress# docker push 10.0.0.12/example/nginx:10.0.0.12
(二)高可用
1.架构,用http通信

上传一些项目到 10.0.0.12 上



(1)在已经有数据的 10.0.0.12 上新建目标


(2)在源harbor上新建复制规则实现到目标harbor的单向复制


注意:首次只能手动执行复制才能实现全量同步,上传镜像会导致只会触发增量同步

实现了单项复制到10.0.0.10 主机上

在 10.0.0.10 主机上再做一次以上的复制过程就可以实现双向复制
这里注意两边建立的账号要一样后面需要做反向代理


(3)搭建nginx做反向代理
用一台新的10.0.0.13
在最开始建立镜像的时候加入了这条属性,所以后面我们把新加的配置放到指定目录下即可
bash
启动容器
docker run -d --name harbor-nginx-1.24.0 -p 85:80 nginx:1.24.0
将nginx.conf容器中的此文件拷出来看一下
docker cp harbor-nginx-1.24.0:/etc/nginx/nginx.conf .
之前修改过
cat /etc/nginx/nginx.conf
......
include /etc/nginx/conf.d/*.conf;
}
nginx 的 conf 文件加入一些属性
bash
root@ubuntu13:~ vim harbor.lty.org.conf
upstream harbor {
server 10.0.0.12:80;
server 10.0.0.10:80;
}
server {
listen 80;
server_name harbor.lty.org;
location / {
proxy_pass http://harbor;
}
}
清理之前创建的容器
docker rm -f harbor-nginx-1.24.0
启动nginx容器,并把文件写入对应目录
root@ubuntu13:~ docker run -d --name harbor-nginx -p 80:80 -v ./harbor.lty.org.conf:/etc/nginx/conf.d/harbor.lty.org.conf nginx:1.24.0
看下加进去了没
bash
root@ubuntu13:~ docker exec harbor-nginx nginx -T
......
# configuration file /etc/nginx/conf.d/harbor.lty.org.conf:
upstream harbor {
server 10.0.0.12:80;
server 10.0.0.10:80;
}
server {
listen 80;
server_name harbor.lty.org;
location / {
proxy_pass http://harbor;
}
}
去10.0.0.11 client 主机上做一下域名解析
bash
root@ubuntu11:~ cat /etc/hosts
......
10.0.0.12 harbor.lty.org
docker 的 json 文件也需要把域名加进去
bash
root@ubuntu11:~ cat /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.1panel.live",
"https://docker.1ms.run",
"https://docker.xuanyuan.me"
],
"experimental":true,
"insecure-registries": ["harbor.lty.org"] #有域名了就可以把后端的服务器地址给删除
}
重启一下
root@ubuntu11:~ systemctl restart docker.service
bash
登录成功
root@ubuntu11:~ docker login -u lty -p L\!\@\#$%^l1 harbor.lty.org
......
Login Succeeded
测试
bash
root@ubuntu11:~ docker tag ubuntu:22.04 harbor.lty.org/example/ubuntu:22.04
root@ubuntu11:~ docker push harbor.lty.org/example/ubuntu
harbor.lty.org/example/ubuntu harbor.lty.org/example/ubuntu:22.04
root@ubuntu11:~ docker push harbor.lty.org/example/ubuntu:22.04
The push refers to repository [harbor.lty.org/example/ubuntu]
fbb9bbbaf4d2: Pushed
22.04: digest: sha256:fbfe6c15492873e10fd854d82a4f9441b9487fa88aa88f574f7da1be091361f5 size: 529
如果遇到413报错可以修改
vim harbor.lty.org.conf
upstream harbor {
server 10.0.0.12:80;
server 10.0.0.10:80;
}
server {
listen 80;
server_name harbor.lty.org;
client_max_body_size 10g; #原因就是nginx默认上传大小是1m,可以改大一些
location / {
proxy_pass http://harbor;
}
}
Windows上做一个域名解析

访问域名

同一个ip地址多次访问可能会报错,可以加一个hash算法的配置
bash
vim harbor.wang.org.conf
upstream harbor {
#ip_hash; 这个就是只看前24位,一样就在一个服务器地址,一般不会用这个
hash $remote_addr; #同一个客户端地址只会访问同一个服务器地址
server 10.0.0.12:80;
server 10.0.0.10:80;
}
2.Harbor 安全 Https 配置
官方说明:https://goharbor.io/docs/2.14.0/install-config/configure-https/
(1)创建证书
创建证书相关数据的目录
bash
root@ubuntu10:~ mkdir -p /data/harbor/certs
root@ubuntu10:~ cd /data/harbor/certs
生成ca的私钥和自签名证书
bash
root@ubuntu10:/data/harbor/certs openssl genrsa -out ca.key 4096
root@ubuntu10:/data/harbor/certs openssl req -x509 -new -nodes -sha512 -days 3650 \
-subj "/C=CN/ST=sichuan/L=sichuan/O=example/OU=Personal/CN=ca.lty.org" \
-key ca.key \
-out ca.crt
生成harbor主机的私钥
bash
root@ubuntu10:/data/harbor/certs openssl genrsa -out harbor.lty.org.key 4096
root@ubuntu10:/data/harbor/certs ls
ca.crt ca.key harbor.lty.org.key
生成harbor主机的证书申请,注意:CN的名称一定是访问harbor的主机域名
bash
root@ubuntu10:/data/harbor/certs openssl req -sha512 -new \
-subj "/C=CN/ST=sichuan/L=sichuan/O=example/OU=Personal/CN=harbor.lty.org" \
-key harbor.lty.org.key \
-out harbor.lty.org.csr
创建x509 v3 扩展文件(新版新增加的要求)
bash
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1=harbor.lty.org #此处必须和和harbor的网站名称一致
DNS.2=lty #可选
DNS.3=lty.org #可选
EOF
给harbor主机颁发证书
bash
openssl x509 -req -sha512 -days 3650 \
-extfile v3.ext \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-in harbor.lty.org.csr \
-out harbor.lty.org.crt
root@ubuntu10:/data/harbor/certs ls
ca.crt ca.key ca.srl harbor.lty.org.crt harbor.lty.org.csr harbor.lty.org.key v3.ext
(2)配置 Harbor 服务器使用证书
bash
root@ubuntu10:/data/harbor/certs vim /usr/local/harbor/harbor.yml
# The IP address or hostname to access admin UI and registry service.
# DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
hostname: harbor.lty.org #修改成域名
# http related config
http:
# port for http, default is 80. If https enabled, this port will redirect to https port
port: 80
# https related config
https:
# https port for harbor, default is 443
port: 443
# The path of cert and key files for nginx
certificate: /data/harbor/certs/harbor.lty.org.crt
private_key: /data/harbor/certs/harbor.lty.org.key
使上面的配置生效
bash
root@ubuntu10:/data/harbor/certs cd /usr/local/harbor/
root@ubuntu10:/usr/local/harbor ls
common common.sh docker-compose.yml harbor.v2.14.2.tar.gz harbor.yml harbor.yml.tmpl install.sh LICENSE prepare
root@ubuntu10:/usr/local/harbor ./prepare
配置中的网络部分会被初始化,改一下
root@ubuntu10:/usr/local/harbor vim docker-compose.yml
......
networks:
harbor:
ipam:
driver: default
config:
- subnet: 172.27.0.0/16
root@ubuntu10:/usr/local/harbor docker-compose down
root@ubuntu10:/usr/local/harbor docker-compose up -d

(3)命令行客户端登录
域名解析改一下
bash
root@ubuntu11:~# cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 ubuntu10
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
10.0.0.11 10.0.0.11
10.0.0.10 harbor.lty.org
把允许 Docker 以HTTP协议访问的配置删除,让他走HTTPS协议
bash
root@ubuntu11:~ cat /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.1panel.live",
"https://docker.1ms.run",
"https://docker.xuanyuan.me"
],
"experimental":true
}
重启并清理缓存
root@ubuntu11:~ systemctl restart docker.service
root@ubuntu11:~ docker logout harbor.lty.org
Removing login credentials for harbor.lty.org
root@ubuntu11:~ docker login harbor.lty.org -u lty -p L\!\@\#$%^l1
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Error response from daemon: Get "https://harbor.lty.org/v2/": dial tcp 10.0.0.10:443: connect: connection refused
#自己颁发的证书互联网不信任,但可以看到已经走https协议了
(4)配置 Docker 客户端使用证书文件
创建和harbor服务器同名的目录
bash
mkdir -pv /etc/docker/certs.d/harbor.lty.org/
root@ubuntu11:~ cd /etc/docker/certs.d/harbor.lty.org/
在harbor主机上把文件推过来
#在docker客户端使用上面的证书文件
#注意:官方介绍需要同时复制harbor.lty.org.key ca.crt,实际不需要
cp harbor.lty.org.cert或harbor.lty.org.crt harbor.lty.org.key ca.crt
/etc/docker/certs.d/harbor.lty.org/
#注意:实际只需要拷贝下面一个文件即可
cp harbor.lty.org.crt /etc/docker/certs.d/harbor.lty.org/
bashroot@ubuntu10:/data/harbor/certs scp /data/harbor/certs/harbor.lty.org.crt 10.0.0.11:/etc/docker/certs.d/harbor.lty.org/
bash
root@ubuntu11:/etc/docker/certs.d/harbor.lty.org docker login harbor.lty.org -u lty -p L\!\@\#$%^l1
Login Succeeded
测试
bash
root@ubuntu11:/etc/docker/certs.d/harbor.lty.org docker pull nginx:1.20.0
root@ubuntu11:/etc/docker/certs.d/harbor.lty.org docker tag nginx:1.20.0 harbor.lty.org/example/nginx:1.20.0
root@ubuntu11:/etc/docker/certs.d/harbor.lty.org docker push harbor.lty.org/example/

还有一种方法
#将私有CA的证书加入到每个docker主机的上信任证书CA列表中
#在Harbor服务器执行
#Ubuntu
cat /data/harbor/certs/ca.crt >> /etc/ssl/certs/ca-certificates.crt
#红帽系统
cat /data/harbor/certs/ca.crt >> /etc/pki/tls/certs/ca-bundle.crt
#将上面的文件复制到所有docker主机覆盖原文件
#并将所有docker主机的docker服务重启生效
systemctl restart docker.service
十、Docker 的资源限制
OOM 优先级机制:
linux会为每个进程计算一个分数,最终将分数最高的kil
评分标准:
/proc/PID/oom_score_adj
#范围为 -1000 到 1000,值越高容易被宿主机 kill掉,如果将该值设置为 -1000 ,则进程永远不会被宿主机 kernel kill
/proc/PID/oom_adj
#该设置参数是为了和旧版本的 Linux 内核兼容的旧接口文件,范围为 -17 到+15 ,会被线性映射到oom_score_adj,取值越高越容易被干掉,如果是 -17 , 则表示不能被 kill, root可读写,
/proc/PID/oom_score
#这个值是系统综合进程的内存消耗量,只读文件,取值范围0 --- 1000,0代表never kill,1000代表aways kill,值越大,进程被选中的概率越大。
#oom_score = 占用消耗内存/总内存 *1000
#内存消耗=常驻内存RSS + 进程页面 +交换内存
#总内存=总的物理内存 +交换分区
#消耗内存越多得分越高,容易被宿主机 kernel 强制杀死
#当内存紧张的时候,内核通过 oom = oom_score + oom_score_adj 计算出分数最高的进程,向其发送关闭信号
(一)Stress-ng 压力测试工具
stress-ng 是一个压力测试工具,可以通过软件仓库进行安装,也提供了docker版本的容器
官方文档: https://wiki.ubuntu.com/Kernel/Reference/stress-ng
1.Stress-ng 安装
bash
docker pull lorel/docker-stress-ng
2.容器的内存限制
bash
root@ubuntu10:~ docker run --name stress01 --rm -m 100m registry.cn-beijing.aliyuncs.com/wangxiaochun/stress-ng
#限制只能用100m以内的内存超过了就会触发oom

3.容器的 CPU 限制
bash
root@ubuntu10:~ docker run --name stress01 --rm --cpus 1 registry.cn-beijing.aliyuncs.com/wangxiaochun/stress-ng --cpu 3
#申请3个cpu,限制只能一个cpu


cpu的亲和性绑定
#一般不建议绑在0号CPU上,因0号CPU一般会较忙
bash
root@ubuntu10:~ docker run --name stress01 --rm --cpuset-cpus 2-3 registry.cn-beijing.aliyuncs.com/wangxiaochun/stress-ng --cpu 4
#绑定到2号和3号cpu

多个容器的CPU利用率比例
bash
root@ubuntu10:~ docker run --name stress01 --rm --cpu-shares 1024 registry.cn-beijing.aliyuncs.com/wangxiaochun/stress-ng --cpu 4
root@ubuntu10:~ docker run --name stress02 --rm --cpu-shares 1024 registry.cn-beijing.aliyuncs.com/wangxiaochun/stress-ng --cpu 4
root@ubuntu10:~ docker run --name stress03 --rm --cpu-shares 2048 registry.cn-beijing.aliyuncs.com/wangxiaochun/stress-ng --cpu 4
