本文全面总结了 Docker 容器化技术的核心知识。从基础概念、底层原理、文件系统到容器网络通信,进一步扩展至 Dockerfile 编写、Docker Compose 与 Swarm 编排编排技术,并结合 Zabbix 与 MinIO 演示了实际应用部署。
1. 简介
docker
Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离
Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口
Docker 将应用程序与该程序的依赖,打包在一个文件(image)里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样.
容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。
image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版)
docker 用途
- 简化环境搭建
- 简化运维工作量
- 微服务利器
docker 安装
uname -r 内核版本大于 3.10
1 | ## 先进行卸载 |
快速确认
docker version
换源
cd /etc/docker 目录下找到在daemon.json文件(没有就新建),将下面内容写入(阿里云)1
2
3
4
5
6tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://1hdirfy9.mirror.aliyuncs.com"],
"exec-opts":["native.cgroupdriver=systemd"]
}
EOF
重启daemon
systemctl daemon-reload
重启docker服务
systemctl restart docker
第一个镜像
1 | docker pull [Registry]/[Respository]/[images]:[tag] # 获取镜像操作 |
- docker run : 启动容器
- debian : 使用的镜像名称 (本地如果没有镜像,就在docker hub 进行搜素,并下载最新版)
- echo “hello world” : 执行的命令
1 | docker run -i -t debian /bin/bash |
- -i -t : 附有一个 tty 的交互会话 -i 支持stdin , -t 终端或伪终端
- /bin/bash : 获得一个 bash shell
- 退出 shell, 容器就会停止, Ctrl+ P + Q 退出而不停止
容器生命周期

1 | docker run --name weilai -h docker -it debian /bin/bash # -h 指定hostname --name 指定docker name |
docker run :创建和启动一个新的容器实例,操作对象是镜像,选项较多,如果你要创建和启动一个容器,只能用run;docker exec: 在已运行的容器中,执行命令,操作对象是容器,如果你要进入已运行的容器,并且执行命令,用exec;docker attach: 同样操作的是已运行的容器,可以将本机标准输入(键盘输入)输到容器中,也可以将容器的输出显示在本机的屏幕上,如果你想查看容器运行过程中产生的标准输入输出,用attach;
docker 镜像
docker images : 列出本机所有镜像1
2
3docker images -qa # -a 显示所有镜像(含中间层) -q 只显示镜像id
docker images --digests # 显示镜像的摘要信息
docker images --no-trunc # 显示完整的镜像信息
docker search redis : 搜索 redis 镜像docker pull redis:latest : 拉取 redis:latest 镜像 (TAG 默认为 latest
删除多个镜像:docker rmi -f 镜像名称1:[TAG] 镜像名称2:[TAG]
中间空格隔开
删除全部镜像:docker rmi -f $(docker images -qa)
同样的
强制删除 docker rm -f 容器ID或name
删除多个容器docker rm -f 容器ID1 容器ID2
删除所有容器
docker rm -f $(docker ps -qa)
容器目录挂载
创建容器的时候,将宿主机的目录与容器内的目录进行映射,实现宿主机和容器目录的双向数据自动同步;
相比前面的 cp 更加简单方便
语法
docker run -it -v /宿主机目录:/容器目录 镜像名
多目录挂载docker run -it -v /宿主机目录:/容器目录 -v /宿主机目录2:/容器目录2 镜像名
挂载目录制度docker run -it -v /宿主机目录:/容器目录:ro 镜像名
例如安装redis1
2$ mkdir -p /opt/data/redis
$ docker run -p 6379:6379 --name myredis -v /opt/data/redis/redis.conf:/etc/redis/redis.conf -v /opt/data/redis:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes --requirepass "passwd"
安装 mysql1
docker run -d -p 3306:3306 --name mysql -v /opt/mysql/data:/var/lib/mysql -v /etc/localtime:/etc/localtime -e MYSQL_ROOT_PASSWORD=password mysql:5.7.40
注意
同步多级目录,可能会出现权限不足的提示;
这是因为selinux把权限禁掉了,我们需要添加 –privileged=true 来解决挂载的目录没有权限的问题;
docker 网络模式
docker 默认使用的是 bridge桥接网络模式
1 | ## docker network ls |
自定义网络模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22## docker network create --subnet=172.20.0.0/16 extnetwork
a2c75e5e49ea2bf16380befd73ac19be54e271f4ad1e39549c47290d1b9fa7f3
## ifconfig
br-a2c75e5e49ea: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.20.0.1 netmask 255.255.0.0 broadcast 172.20.255.255
ether 02:42:43:82:72:6e txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:d5ff:fe34:51d4 prefixlen 64 scopeid 0x20<link>
ether 02:42:d5:34:51:d4 txqueuelen 0 (Ethernet)
RX packets 10771 bytes 601704 (587.6 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 10230 bytes 51101359 (48.7 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
...
...
...创建容器并指定ip
--net extnetwork --ip 172.20.0.2
extnetwork 上文指定172.20.0.1 是网关,所以从2 分配
1 | ## docker run -p 8066:8066 -it --net extnetwork --ip 172.20.0.2 debian |
也可以用 docker inspect 容器id 查看信息
1 | ## docker inspect b4246dddf9f5 |
删除网络
docker network rm extnetwork限制cpu 内存等
容器的监控原理其实就是定时读取 Linux 主机上相关的文件并展示给用户。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76root@test:~# docker run --name nginx -m 200M --cpus=0.2 -d nginx
WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.
1c8999af3a3654cb9e053795198f0d1c377fc1080173213a6fdd2179123bcf00
root@test:~# ls -l /sys/fs/cgroup/memory/docker
total 0
drwxr-xr-x 2 root root 0 Oct 23 16:31 1c8999af3a3654cb9e053795198f0d1c377fc1080173213a6fdd2179123bcf00
-rw-r--r-- 1 root root 0 Oct 23 16:31 cgroup.clone_children
--w--w--w- 1 root root 0 Oct 23 16:31 cgroup.event_control
-rw-r--r-- 1 root root 0 Oct 23 16:31 cgroup.procs
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.failcnt
--w------- 1 root root 0 Oct 23 16:31 memory.force_empty
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.kmem.failcnt
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.kmem.limit_in_bytes
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.kmem.max_usage_in_bytes
-r--r--r-- 1 root root 0 Oct 23 16:31 memory.kmem.slabinfo
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.kmem.tcp.failcnt
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.kmem.tcp.limit_in_bytes
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.kmem.tcp.max_usage_in_bytes
-r--r--r-- 1 root root 0 Oct 23 16:31 memory.kmem.tcp.usage_in_bytes
-r--r--r-- 1 root root 0 Oct 23 16:31 memory.kmem.usage_in_bytes
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.limit_in_bytes
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.max_usage_in_bytes
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.move_charge_at_immigrate
-r--r--r-- 1 root root 0 Oct 23 16:31 memory.numa_stat
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.oom_control
---------- 1 root root 0 Oct 23 16:31 memory.pressure_level
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.soft_limit_in_bytes
-r--r--r-- 1 root root 0 Oct 23 16:31 memory.stat
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.swappiness
-r--r--r-- 1 root root 0 Oct 23 16:31 memory.usage_in_bytes
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.use_hierarchy
-rw-r--r-- 1 root root 0 Oct 23 16:31 notify_on_release
-rw-r--r-- 1 root root 0 Oct 23 16:31 tasks
root@test:~# ls -l /sys/fs/cgroup/memory/docker/1c8999af3a3654cb9e053795198f0d1c377fc1080173213a6fdd2179123bcf00
total 0
-rw-r--r-- 1 root root 0 Oct 23 16:32 cgroup.clone_children
--w--w--w- 1 root root 0 Oct 23 16:31 cgroup.event_control
-rw-r--r-- 1 root root 0 Oct 23 16:31 cgroup.procs
-rw-r--r-- 1 root root 0 Oct 23 16:32 memory.failcnt
--w------- 1 root root 0 Oct 23 16:32 memory.force_empty
-rw-r--r-- 1 root root 0 Oct 23 16:32 memory.kmem.failcnt
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.kmem.limit_in_bytes
-rw-r--r-- 1 root root 0 Oct 23 16:32 memory.kmem.max_usage_in_bytes
-r--r--r-- 1 root root 0 Oct 23 16:32 memory.kmem.slabinfo
-rw-r--r-- 1 root root 0 Oct 23 16:32 memory.kmem.tcp.failcnt
-rw-r--r-- 1 root root 0 Oct 23 16:32 memory.kmem.tcp.limit_in_bytes
-rw-r--r-- 1 root root 0 Oct 23 16:32 memory.kmem.tcp.max_usage_in_bytes
-r--r--r-- 1 root root 0 Oct 23 16:32 memory.kmem.tcp.usage_in_bytes
-r--r--r-- 1 root root 0 Oct 23 16:32 memory.kmem.usage_in_bytes
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.limit_in_bytes
-rw-r--r-- 1 root root 0 Oct 23 16:32 memory.max_usage_in_bytes
-rw-r--r-- 1 root root 0 Oct 23 16:32 memory.move_charge_at_immigrate
-r--r--r-- 1 root root 0 Oct 23 16:32 memory.numa_stat
-rw-r--r-- 1 root root 0 Oct 23 16:31 memory.oom_control
---------- 1 root root 0 Oct 23 16:32 memory.pressure_level
-rw-r--r-- 1 root root 0 Oct 23 16:32 memory.soft_limit_in_bytes
-r--r--r-- 1 root root 0 Oct 23 16:32 memory.stat
-rw-r--r-- 1 root root 0 Oct 23 16:32 memory.swappiness
-r--r--r-- 1 root root 0 Oct 23 16:32 memory.usage_in_bytes
-rw-r--r-- 1 root root 0 Oct 23 16:32 memory.use_hierarchy
-rw-r--r-- 1 root root 0 Oct 23 16:32 notify_on_release
-rw-r--r-- 1 root root 0 Oct 23 16:32 tasks
root@test:~# cat /sys/fs/cgroup/memory/docker/1c8999af3a3654cb9e053795198f0d1c377fc1080173213a6fdd2179123bcf00/memory.limit_in_bytes
209715200 # 200M = 200 * 1024 * 1024 B = 209715200 B
memory.usage_in_bytes # 使用值
root@test:~# docker inspect nginx |grep Pid # 查看网络情况
"Pid": 7641,
"PidMode": "",
"PidsLimit": null,
root@test:~# cat /proc/7641/net/dev
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
eth0: 1186 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0
设置代理
dockerd1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mkdir -p /etc/systemd/system/docker.service.d
cat > /etc/systemd/system/docker.service.d/proxy.conf <<EOF
[Service]
Environment="http_proxy=http://user:[email protected]:9870"
Environment="https_proxy=http://user:[email protected]:9870"
Environment="no_proxy=127.0.0.0/8,10.0.0.0/8,100.64.0.0/10,172.16.0.0/12,192.168.0.0/16,ivolces.com,localhost"
EOF
systemctl daemon-reload
systemctl restart docker
systemctl show --property=Environment docker
containerd daemon.json 添加
1 | { |
build
1 | docker build . \ |
2. 基础知识windows10+docker+wsl+ubuntu
准备工作
安装wsl linux
开启Linux子系统,以管理员权限打开 PowerShell
1
2
3
4## 启用虚拟机平台
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform
## 开启Linux子系统
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux开启开发者模式,
WIN + S搜索 开发者设置,打开后选择 开发者模式WIN + S搜索 store, 打开 Microsoft Store(微软应用商店),eg: 搜索 Ubuntu ,选择 Ubuntu 18.04 LST 进行安装- 待安装完成后,从应用中打开 Ubuntu 18.04 LST
优化
换源
打开自动切换到root用户
当前用户目录下 vi .bash_profile 添加以下内容1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16##.bash_profile
## Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
sudo su - root
PATH=$PATH:$HOME/bin
export PATH
修改/etc/sudoers文件
1 | su - root |
安装docker
实际上是在Win10中安装Docker桌面服务,Linux子系统中安装客户端,连接Win10上的Docker服务,进行操作
在Ubuntu子系统中安装Docker1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42## 更新apt包管理列表
sudo apt-get update -y
## 安装依赖包
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
## 加入Docker官方PGP公钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
## 确认指纹
sudo apt-key fingerprint 0EBFCD88
## 将stable(稳定版)Docker加入apt源中
##
## If you want to live on the edge, you can change "stable" below to "test" or
## "nightly". I highly recommend sticking with stable!
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
## 更新apt包管理列表
sudo apt-get update -y
## 安装Docker CE最新版本
sudo apt-get install -y docker-ce
## 允许当前用户访问Docker CLI,不必使用root
sudo usermod -aG docker $USER
## 此时执行 docker version 会提示如下错误:
## Cannot connect to the Docker daemon at unix:///var/run/docker.sock.
## 配置Windows Docker服务地址 (Settings => General => Expose daemon on tcp://localhost:2375 without TLS)
echo "export DOCKER_HOST=localhost:2375" >> ~/.bashrc
## 使配置生效
. ~/.bashrc
powershell其他操作
使用管理员模式,打开PowerShell1
2
3
4
5启动停止 wsl 服务
## 停止子系统服务
net stop LxssManager
## 启动子系统服务
net start LxssManager
备份恢复,导出、导入子系统1
2
3
4## d:\Ubuntu-18.04.tar 导出文件路径
wsl --export Ubuntu-18.04 d:\Ubuntu-18.04.tar
## d:\wsl\u18.04 子系统导入后的安装路径
wsl --import Ubuntu-18.04 d:\wsl\u18.04 d:\Ubuntu-18.04.tar
3. docker原理
容器技术原理
容器,其实是一种特殊的进程而已。容器化后的用户应用,却依然还是一个宿主机上的普通进程,这就意味着这些因为虚拟化而带来的性能损耗都是不存在的
Docker 是利用 Linux 的 Namespace 、Cgroups 和联合文件系统三大机制来保证实现的, 所以它的原理是使用 Namespace 做主机名、网络、PID 等资源的隔离,使用 Cgroups 对进程或者进程组做资源(例如:CPU、内存等)的限制,联合文件系统用于镜像构建和容器运行环境.
一个“容器”,实际上是一个由 Linux Namespace、Linux Cgroups 和 rootfs 三种技术构建出来的进程的隔离环境。
一个正在运行的 Linux 容器,其实可以被“一分为二”地看待:
一组联合挂载在 /var/lib/docker/aufs/mnt 上的 rootfs,这一部分我们称为“容器镜像”(Container Image),是容器的静态视图;
一个由 Namespace+Cgroups 构成的隔离环境,这一部分我们称为“容器运行时”(Container Runtime),是容器的动态视图。
rootfs 里面打包的不只是应用,而是整个操作系统的文件和目录,也就意味着,应用和它运行所需要的所有依赖,都被封装在一起。(所有容器共享宿主机内核)
补
Kata Containers 与 gVisor 实现的方式与 Docker 不同
这两种容器实现的本质,都是给进程分配了一个独立的操作系统内核,从而避免了让容器共享宿主机的内核。这样,容器进程能够看到的攻击面,就从整个宿主机内核变成了一个极小的、独立的、以容器为单位的内核,从而有效解决了容器进程发生“逃逸”或者夺取整个宿主机的控制权的问题。
Kata Containers : 使用的是传统的虚拟化技术,通过虚拟硬件模拟出了一台“小虚拟机”,然后在这个小虚拟机里安装了一个裁剪后的 Linux 内核来实现强隔离。
gVisor 直接用 Go 语言“模拟”出了一个运行在用户态的操作系统内核,然后通过这个模拟的内核来代替容器进程向宿主机发起有限的、可控的系统调用。
Namespace
基于 Linux Namespace 的隔离机制相比于虚拟化技术也有很多不足之处,其中最主要的问题就是:隔离得不彻底。
Namespace 是 Linux 内核的一项功能,该功能对内核资源进行隔离,使得容器中的进程都可以在单独的命名空间中运行,并且只可以访问当前容器命名空间的资源。Namespace 可以隔离进程 ID、主机名、用户 ID、文件名、网络访问和进程间通信等相关资源。
Docker 主要用到以下五种命名空间。
pid namespace:用于隔离进程 ID。
net namespace:隔离网络接口,在虚拟的 net namespace 内用户可以拥有自己独立的 IP、路由、端口等。
mnt namespace:文件系统挂载点隔离。
ipc namespace:信号量,消息队列和共享内存的隔离。
uts namespace:主机名和域名的隔离
Cgroups
Cgroups 是一种 Linux 内核功能,可以限制和隔离进程的资源使用情况(CPU、内存、磁盘 I/O、网络等)。在容器的实现中,Cgroups 通常用来限制容器的 CPU 和内存等资源的使用。
cgroups 限制了固定几种资源的使用不会超限,但是它既不能隔离被共享的硬件比如 L3 cache,也不能有效地防止容器逃逸的问题1
2
3
4
5
6
7
8
9
$ docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/bash
$ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_period_us
100000 ## CPU period
$ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_quota_us
20000 ## 这就意味着这个 Docker 容器,只能使用到 20% 的 CPU 带宽。
cgroup 可以实现资源的限制,但不能保证资源的使用。
限制 cpu 使用1
2
3
4
5docker run -itd --name docker10 --cpuset-cpus 0,1 --cpu-shares 512 centos /bin/bash
##指定 docker10 只能在 cpu0 和 cpu1 上运行,而且 docker10 的使用 cpu 的份额 512
docker run -itd --name docker20 --cpuset-cpus 0,1 --cpu-shares 1024 centos /bin/bash
##指定 docker20 只能在 cpu0 和 cpu1 上运行,而且 docker20 的使用 cpu 的份额 1024,比 dcker10 多一倍
限制内存使用1
2
3
4docker run -it -m 128m centos
cat /sys/fs/cgroup/memory/memory.limit_in_bytes
134217728
限制硬盘速率1
2
3docker run -it -v /var/www/html/:/var/www/html --device /dev/sda:/dev/sda --device-write-bps /dev/sda:2mb centos /bin/bash
dd if=/dev/sda of=/var/www/html/test.out bs=2M count=50 oflag=direct,nonblock # direct:读写数据采用直接 IO 方式,不走缓存。直接从内存写硬盘上。nonblock:读写数据采用非阻塞 IO 方式,优先写 dd 命令的数据
联合文件系统
联合文件系统,又叫 UnionFS,是一种通过创建文件层进程操作的文件系统,因此,联合文件系统非常轻快。Docker 使用联合文件系统为容器提供构建层,使得容器可以实现写时复制以及镜像的分层构建和存储。常用的联合文件系统有 AUFS、Overlay 和 Devicemapper 等。
Docker 在镜像的设计中,引入了层(layer)的概念。也就是说,用户制作镜像的每一步操作,都会生成一个层,也就是一个增量 rootfs。
容器镜像是只读的,如果要修改必须通过 copy-on-write 机制把文件复制到只读层才行。
Docker 文件系统分层从下到上 : 只读层, init层,读写层
Init 层 : 是 Docker 项目单独生成的一个内部层,专门用来存放 /etc/hosts、/etc/resolv.conf 等信息。这些文件本来属于只读镜像的一部分,但实际写入一些指定的值比如 hostname,所以就需要在可读写层对它们进行修改,可是,这些修改往往只对当前的容器有效,我们并不希望执行 docker commit 时,把这些信息连同可读写层一起提交掉. 所以,Docker 做法是,在修改了这些文件之后,以一个单独的层挂载了出来。而用户执行 docker commit 只会提交可读写层,所以是不包含init 层的内容。
我现在有两个目录 A 和 B,它们分别有两个文件:
1 |
|
使用联合挂载的方式,将这两个目录挂载到一个公共的目录 C 上:
1 |
|
对于 AuFS 来说,它最关键的目录结构在 /var/lib/docker 路径下的 diff 目录:/var/lib/docker/aufs/diff/<layer_id>
Volume
Volume 机制,允许你将宿主机上指定的目录或者文件,挂载到容器里面进行读取和修改操作。
Docker 重要组件
containerd : containerd通过 containerd-shim 启动并管理 runC,可以说containerd真正管理了容器的生命周期。
containerd-shim
ctr
docker
docker-init
docker-proxy
dockerd
runc : 是一个用来运行容器的轻量级工具,是真正用来运行容器的。
4. docker文件系统
前言 Docker 卷与持久化数据存储
创建数据卷
1 | [root@imwl-124 ~]# docker volume create myvolume |
查看数据卷
1 | [root@imwl-124 ~]# docker volume ls |
使用数据卷
1 | docker run -d --name=nginx --mount source=myvolume,target=/usr/share/nginx/html nginx |
其中创建 + 使用 等同于
docker run -d --name=nginx-volume -v /usr/share/nginx/html nginx
旧容器删除,数据卷并不会删除
删除数据卷
1 | docker volume rm myvolume |
容器与容器之间数据共享
使用 volumes-from 参数可以在启动新的容器时来挂载已经存在的容器的卷,volumes-from 参数后面跟已经启动的容器名称1
2
3
4
5docker volume create log-vol
docker run --mount source=log-vol,target=/tmp/log --name=log-producer -it busybox
docker run -it --name consumer --volumes-from log-producer busybox
主机与容器之间数据共享
-v HOST_PATH:CONTIANAER_PATH1
docker run -v /data:/usr/local/data -it busybox
原理
1 | [root@imwl-124 ~]# ls -l /var/lib/docker/volumes |
Docker 卷的实现原理是在主机的 /var/lib/docker/volumes 目录下,根据卷的名称创建相应的目录,然后在每个卷的目录下创建 _data 目录,在容器启动时如果使用 --mount 参数,Docker 会把主机上的目录直接映射到容器的指定目录下,实现数据持久化
分类
AUFS: 现在很少使用Devicemapper: 常用在Red Hat或CentOS系统中OverlayFS:Docker目前推荐选择
Devicemapper
Docker 的 Devicemapper 模式有两种:
loop-lvm: 主要用来开发和测试使用direct-lvm: 推荐在生产环境中使用
direct-lvm
当前生产环境 使用的 模式
loop-lvm 仅配置 “storage-driver”: “devicemapper”, 不配置 “storage-opts”1
2
3
4
5
6
7
8
9
10
11
12
13
14[root@test-196 ~]# cat /etc/docker/daemon.json
{
"bip": "172.27.0.1/16",
"fixed-cidr": "172.27.0.0/16",
"insecure-registries": ["127.0.0.1/8"],
"storage-driver": "devicemapper",
"exec-opts": ["native.cgroupdriver=systemd"],
"storage-opts": [
"dm.basesize=20G",
"dm.thinpooldev=/dev/mapper/docker-thinpool",
"dm.use_deferred_removal=true",
"dm.use_deferred_deletion=true"
]
}
查看1
2
3
4
5
6
7
8
9[root@test-196 ~]# docker info |grep Driver
Storage Driver: devicemapper # 使用 devicemapper
Logging Driver: json-file
Cgroup Driver: systemd
[root@test-196 ~]# docker info |grep Pool
Pool Name: docker-thinpool # direct-lvm 模式已经配置成功
Pool Blocksize: 524.3kB
Thin Pool Minimum Free Space: 51GB
Devicemapper 原理
Devicemapper 是一种映射块设备的技术框架, 提供了一种将物理块设备映射到虚拟块设备的机制。
Devicemapper 将主要的工作部分分为 用户空间 和 内核空间
用户空间负责配置具体的设备映射策略与相关的内核空间控制逻辑,例如逻辑设备 dm-a 如何与物理设备 sda 相关联,怎么建立逻辑设备和物理设备的映射关系等。
内核空间则负责用户空间配置的关联关系实现,例如当 IO 请求到达虚拟设备 dm-a 时,内核空间负责接管 IO 请求,然后处理和过滤这些 IO 请求并转发到具体的物理设备 sda 上。
映射设备 通过 映射表 关联到具体的 物理目标设备 。事实上,映射设备不仅可以通过映射表关联到物理目标设备,也可以关联到虚拟目标设备,然后虚拟目标设备再通过映射表关联到物理目标设备。

瘦供给(Thin Provisioning) : 需要多少磁盘空间,存储驱动就帮我们分配多少磁盘空间
Docker 使用了瘦供给的 snapshot 技术, Docker 将镜像和容器的文件存储在瘦供给池(thinpool )中,并将这些内容挂载在 /var/lib/docker/devicemapper/ 目录下。
1 | [root@test-249 devicemapper]# pwd |

这个 Ubuntu 镜像一共有四层,每一层镜像都是下一层的快照,镜像的最底层是基础设备的快照。当容器运行时,容器是基于镜像的快照。Devicemapper 实现镜像分层的根本原理就是快照
快照是数据在某一个时间点的存储状态。快照的主要作用是对数据进行备份,当存储设备发生故障时,可以使用已经备份的快照将数据恢复到某一个时间点,而 Docker 中的数据分层存储也是基于快照实现的。
overlay2
要想使用 overlay2,Docker版本必须高于17.06.02`。
如果你的操作系统是 RHEL 或 CentOS,Linux 内核版本必须使用 3.10.0-514 或者更高版本,其他 Linux 发行版的内核版本必须高于 4.0(例如 Ubuntu 或 Debian),可以使用 uname -a 查看当前系统的内核版本。
overlay2 最好搭配 xfs 文件系统使用,并且使用 xfs 作为底层文件系统时,d_type 必须开启,可以使用以下命令验证 d_type 是否开启:
1 | [imwl@imwl-u ~]$ xfs_info /var/lib/docker | grep ftype |
ftype=1 时,表示 d_type 已经开启。 sudo mkfs.xfs -f -n ftype=1 /path/to/disk
示例
挂载 /var/lib/docker 到 /dev/vdb11
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 500G 0 disk
└─vda1 253:1 0 500G 0 part /
vdb 253:16 0 500G 0 disk
└─vdb1 253:17 0 8G 0 part
$ sudo mkfs.xfs -f -n ftype=1 /dev/vdb1
$ sudo echo "/dev/vdb1 /var/lib/docker xfs defaults,pquota 0 0" >> /etc/fstab
$ sudo mount -a
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 500G 0 disk
└─vda1 253:1 0 500G 0 part /
vdb 253:16 0 500G 0 disk
└─vdb1 253:17 0 8G 0 part /var/lib/docker
$ xfs_info /var/lib/docker | grep ftype
naming =version 2 bsize=4096 ascii-ci=0 ftype=1
使用
修改 /etc/docker/daemon.json1
2
3
4
5
6
7{
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.size=20G",
"overlay2.override_kernel_check=true"
]
}
限制每个容器根目录大小为 20G
重启 docker1
$ sudo systemctl start docker
docker_info 节选
1 |
|
storage Driver 已经变为 overlay2,并且 d_type 也是 true
原理
overlay2 和 AUFS 类似,它将所有目录称之为层(layer),overlay2 的目录是镜像和容器分层的基础,而把这些层统一展现到同一的目录下的过程称为联合挂载(union mount)。overlay2 把目录的下一层叫作 lowerdir,上一层叫作 upperdir,联合挂载后的结果叫作 merged。
overlay2 将镜像层和容器层都放在单独的目录,并且有唯一 ID ,每一层仅存储发生变化的文件,最终使用联合挂载技术将容器层和镜像层的所有文件统一挂载到容器中,使得容器中看到完整的系统文件。
AUFS
配置

1
2
3{
"storage-driver": "aufs"
}
每一个目录在 AUFS 中都叫作分支,而在 Docker 中则称之为层(layer),但最终呈现给用户的则是一个普通单层的文件系统,我们把多层以单一层的方式呈现出来的过程叫作联合挂载。
5. 容器间的通信
docker run 创建 d dr ocker 容器时,可以用 –net 选项指定容器的网络模式, Docker 有以下4 种网络模式:
bridge 模式:使 –net =bridge 指定,默认设置, 容器启动后会通过 DHCP 获取一个地址 eg: 172.20.0.3
host 模式:使 –net=host 指定, 共享宿主机的网络
none 模式:使 –net=none 指定, 只有本地 lo 地址
container 模式:使用 –net=containerNAME orID ,其和已经存在的containerNAME 共享一个 Network Namespace
https://blog.csdn.net/u013355826/article/details/84987233
容器之间通信的主要方式
1.通过容器ip访问
容器重启后,ip会发生变化。通过容器ip访问不是一个好的方案。
2.通过宿主机的ip:port访问
通过宿主机的ip:port访问,只能依靠监听在暴露出的端口的进程来进行有限的通信。
3.通过link建立连接(官方不推荐使用)
运行容器时,指定参数link,使得源容器与被链接的容器可以进行相互通信,并且接受的容器可以获得源容器的一些数据,比如:环境变量。
源容器:mysql
docker run -itd –name test-mysql -e MYSQL_ROOT_PASSWORD=root mysql:5.7
##被链接容器 centos
docker run -itd –name test-centos –link test-mysql:mysql centos /bin/bash
##进入test-centos
docker exec -it test-centos /bin/bash
直接通过 link的名字或者link时候取的别名就能进入:
通过link建立连接的容器,被链接的容器能 ping 通源容器,反过来不行。
在被链接的容器上查看环境变量
被链接容器会继承源容器的环境变量信息。
与/etc/hosts中的主机条目不同,如果重新启动源容器,则不会自动更新存储在环境变量中的IP地址。我们建议使用主机条目 /etc/hosts来解析链接容器的IP地址。
除了环境变量之外,Docker还将源容器的主机条目添加到/etc/hosts文件中。
如果重新启动源容器,/etc/hosts链接容器上的文件将使用源容器的新IP地址自动更新,从而允许链接通信继续。
4.通过 User-defined networks(推荐)
docker network来创建一个桥接网络,在docker run的时候将容器指定到新创建的桥接网络中,这样同一桥接网络中的容器就可以通过互相访问。
创建网络
docker network create test-network
启动容器时,加入创建的网络
docker run -it –network test-network –network-alias mysql -e MYSQL_ROOT_PASSWORD=123 mysql:5.7
启动被链接的容器
docker run -it –network test-network –network-alias centos centos /bin/bash
6. 推送,备份
提交运行的容器成为镜像
生产环境一般使用 dockerfile. commit 的镜像不可控1
2
3
4
5
6
7
8docker run --name imwltest -h docker -dit -e TZ=Asia/Shanghai debian
## docker commit -a='作者' -m='备注' 运行时容器ID 新镜像名称
docker commit -a='imwl' -m='Test' imwltest imwl/test # 默认TAG: latest
docker commit -a='imwl' -m='Test' imwltest imwl/test:0.14
docker export imwltest > imwltest.tar # 导出容器
docker import imwltest.tar imwltest:test # 导入容器
1 | ## docker images |
Docker Hub 账户 imwl1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16docker login
docker push imwl/test:0.14
docker push imwl/test
docker tag flasky:latest imwl/flask:latest
docker push imwl/flask:latest
docker run --name flasky -d -p 8000:5000 imwl/flask:latest # -d 后台运行容器,并返回容器ID -p 端口映射(8000宿主机,5000容器端口)
## -P 随机端口映射
## -e TZ=Asia/Shanghai 指定时区
备份与还原
有些机密性,可以通过docker镜像备份和迁移实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28## docker save -o 备份镜像的名称 源镜像名称:tag版本
docker save -o imwltest.tar imwl/test:0.14
## 当前目录下 会有 imwltest.tar文件
## docker images
REPOSITORY TAG IMAGE ID CREATED
imwl/test 0.14 69c1c6c58124 27 minutes ago
imwl/test latest ad65438d599f 32 minutes ago
## docker rmi imwl/test:0.14
Untagged: imwl/test:0.14
Untagged: imwl/test@sha256:97b496724012eee3df3421edb2ab6edcd6115e42b8060c24ba06b51da466e0dd
Deleted: sha256:69c1c6c58124c56456a22c92a2e2125c9abc744f6acde379f5039779becbcc29
## docker images
REPOSITORY TAG IMAGE ID CREATED
imwl/test latest ad65438d599f 32 minutes ago
### 恢复
## docker load -i imwltest.tar
Loaded image: imwl/test:0.14
## docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
imwl/test 0.14 69c1c6c58124 32 minutes ago 114MB
imwl/test latest ad65438d599f 37 minutes ago 114MB
debian latest a8797652cfd9 2 weeks ago 114MB
私有仓库
Docker私有仓库内部用来存放镜像的仓库,具有更高的保密安全级别
搭建
1 | ## docker pull registry # 拉取私有仓库镜像 |
测试
标记镜像为私有仓库的镜像docker tag imwl/test 207.246.103.127:5000/debiantest
上传镜像到私有仓库docker push 207.246.103.127:5000/debiantest
7. Docker安全
Docker 是基于 Linux 内核的 Namespace 技术实现资源隔离的,所有容器都共享主机的内核
尽管目前 Namespace 已经提供了非常多的资源隔离类型,但是仍然有部分关键内容没有完全隔离。其中包括一些系统的关键性目录(eg: /sys /proc)
安全问题解决
- User namespace : 主要用来做容器内用户和主机的用户隔离
- 保障镜像安全: 私有镜像进行安全检查,拉取镜像使用 https 和受信任的镜像仓库
- 及时升级宿主机内核
- 使用安全加固组件 : selinux , AppArmor(控制用户的访问权限), GRSecurity(只能访问控制,提供内存破坏防御,文件系统增强等多种防御形式)。
- 进行资源限制
- 使用安全容器 (每个容器都运行在一个单独的微型虚拟机中,拥有独立的操作系统和内核)(eg: Kata Container)
- 及时升级 docker 组件
8. DockerFile示例
简介
Dockerfile 是由一系列命令和参数构成的脚本,这些命令应用于操作系统基础镜像并最终创建的一个新镜像;
生产实践中一定优先使用 Dockerfile 的方式构建镜像。
基础镜像体积应该尽量小
尽量减少 Dockerfile 的行数,因为 Dockerfile 的每一条指令都会生成一个镜像层。
Dockerfile 书写原则
单一职责:由于容器的本质是进程,一个容器代表一个进程,因此不同功能的应用应该尽量拆分为不同的容器,每个容器只负责单一业务进程。
提供注释信息:
Dockerfile也是一种代码,我们应该保持良好的代码编写习惯,晦涩难懂的代码尽量添加注释,让协作者可以一目了然地知道每一行代码的作用,并且方便扩展和使用。保持容器最小化:应该避免安装无用的软件包,可以加快容器构建速度,而且可以避免镜像体积过大。
合理选择基础镜 :容器的核心是应用,因此只要基础镜像能够满足应用的运行环境即可
使用
.dockerignore文件 : 使用.dockerignore在构建时,忽略一些不需要参与构建的文件,从而提升构建效率。尽量使用构建缓存 :
Docker构建过程中,每一条Dockerfile指令都会提交为一个镜像层,下一条指令都是基于上一条指令构建的。如果构建时发现要构建的镜像层的父镜像层已经存在,并且下一条命令使用了相同的指令,即可命中构建缓存。
- 正确设置时区: 从
Docker Hub拉取的官方操作系统镜像大多数都是UTC时间 , 也可以运行时指定-e TZ=Asia/Shanghai
1 | ## Debian |
- 使用国内软件源加快镜像构建速度: 最好的方式是换源
- 最小化镜像层数
常用命令
FROM image:tag : 使用的基础镜像构建MAINTAINER user_info : 声明镜像维护者信息LABEL value : 镜像描述元信息 (可以多条)ENV key value : 设置环境变量 (可以多条)RUN command : 构建镜像时需要运行的命令 (可以多条)WORKDIR path_dir : 设置终端默认登录进来的工作目录EXPOSE port : 当前容器对外暴露出的端口ADD source_dir/file dest_dir/file : 宿主机内文件复制到容器,压缩文件会解压,也可以获取远程文件COPY source_dir/file dest_dir/file : 宿主机内文件复制到容器,不过压缩文件不解压VOLUME : 创建一个 可以从本机或其他容器挂载的挂载点,一般用来存放数据库和需要保存的数据CMD : 指定容器启动时要运行的命令,多个CMD,最后一个生效 CMD ENTRYPOINT : 指定容器启动时要运行的命令,最后一个才有用ONBUILD : 为子镜像服务
示例
简单实例:父镜像 Dockerfile:1
2
3
4
5
6FROM centos
ONBUILD RUN yum -y install vim
CMD /bin/bash
子镜像简单点:
FROM parent
Dockerfile
1 | FROM centos |
多阶构建
多阶段构建可以通过一个 Dockerfile 很方便地构建出体积更小的镜像,只需要编写 Dockerfile 文件即可,无须借助外部脚本文件
1 | ## 编译代码 |
与上面的效果一样1
2
3
4
5
6
7
8
9
10
11
12
13
14FROM golang:1.13 AS builder # 使用 AS 指令将这个阶段命名为 builder
WORKDIR /go/src/github.com/wilhelmguo/multi-stage-demo/
COPY main.go .
RUN CGO_ENABLED=0 GOOS=linux go build -o http-server .
FROM alpine:latest
WORKDIR /root/
## 可以使用 --from=builder,使得 Dockerfile 更加清晰可读
COPY --from=builder /go/src/github.com/wilhelmguo/multi-stage-demo/http-server .
## COPY --from=nginx:latest /etc/nginx/nginx.conf /etc/local/nginx.conf # 拷贝 nginx 官方镜像的配置文件到我们自己的镜像中时
CMD ["./http-server"]
在执行 docker build 命令时添加 target 参数,可以将构建阶段停止在指定阶段1
docker build --target builder -t http-server:latest .
补充说明
cmd 与 ENTRYPOINT
CMD 和 ENTRYPOINT 的基本使用格式分为两种:
第一种为 CMD/ENTRYPOINT["command" , "param"] 。这种格式是使用 Linux 的 exec 实现的, 一般称为 exec 模式,这种书写格式为CMD/ENTRYPOINT 后面跟 json 数组,也是 Docker 推荐的使用格式。
另外一种格式为 CMD/ENTRYPOINT command param ,这种格式是基于 shell 实现的, 通常称为 shell 模式。当使用 shell 模式时,Docker 会以 /bin/sh -c command 的方式执行命令.
Dockerfile 中如果使用了 ENTRYPOINT 指令,启动 Docker 容器时需要使用 --entrypoint 参数才能覆盖 Dockerfile 中的 ENTRYPOINT 指令 ,而使用 CMD 设置的命令则可以被 docker run 后面的参数直接覆盖。
ENTRYPOINT 指令可以结合 CMD 指令使用,也可以单独使用,而 CMD 指令只能单独使用
9. docker-compose浅尝
简介
Docker Compose 是 Docker 官方的单机多容器管理系统,它本质是一个 Python 脚本,它通过解析用户编写的 yaml 文件,调用 Docker API 实现动态的创建和管理多个容器。
因为 目前项目上 使用的是 harbor 作为 k8s 镜像仓库,用的 docker-compose 所以了解一下.
安装
eg: 版本 1.28.6
1 | sudo curl -L "https://github.com/docker/compose/releases/download/1.28.6/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose |
测试
步骤1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30[root@imwl-175 ~]# mkdir docker-compose-test
[root@imwl-175 ~]# cd docker-compose-test/
[root@imwl-175 docker-compose-test]# touch docker-compose.yml
[root@imwl-175 docker-compose-test]# cat docker-compose.yml
version: '3'
services:
mysql:
image: mysql:5.7
volumes:
- mysql_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: mywordpress
MYSQL_USER: mywordpress
MYSQL_PASSWORD: mywordpress
wordpress:
depends_on:
- mysql # 依赖 mysql
image: wordpress:php7.4
ports:
- "8080:80"
restart: always
environment:
WORDPRESS_DB_HOST: mysql:3306
WORDPRESS_DB_USER: mywordpress
WORDPRESS_DB_PASSWORD: mywordpress
WORDPRESS_DB_NAME: mywordpress
volumes:
mysql_data: {}
Docker Compose 首先会为我们启动一个 MySQL 数据库,按照 MySQL 服务中声明的环境变量来设置 MySQL 数据库的用户名和密码。然后等待 MySQL 数据库启动后,再启动 WordPress 服务。WordPress 服务启动后,我们就可以通过 http://localhost:8080
1 | docker-compose up -d # 后台运行 |
查看 信息
1 | [root@imwl-175 docker-compose-test]# docker ps |
访问

10. docker-swarm浅尝
1.12 版本以后自带
管理节点: 管理节点负责接受用户的请求,用户的请求中包含用户定义的容器运行状态描述,然后 Swarm 负责调度和管理容器,并且努力达到用户所期望的状态。(ratf 奇数节点)
工作节点: 工作节点运行执行器(Executor)负责执行具体的容器管理任务(Task),例如容器的启动、停止、删除等操作。
1 | docker swarm init (单网卡) |
其他节点加入
1 | docker swarm join --token SWMTKN-1-2q8i254edy5ibu3lzu78skyhw73qb3yad5hotnkiacc5ngj5je-2ndzf9f12nk370myw1ommxskm 66.42.99.175:2377 |
####
使用 docker-compose 的yaml 文件 ,加一个字段1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29version: '3'
services:
mysql:
image: mysql:5.7
volumes:
- mysql_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: mywordpress
MYSQL_USER: mywordpress
MYSQL_PASSWORD: mywordpress
wordpress:
depends_on:
- mysql # 依赖 mysql
image: wordpress:php7.4
deploy: # 添加字段
mode: replicated
replicas: 2
ports:
- "8080:80"
restart: always
environment:
WORDPRESS_DB_HOST: mysql:3306
WORDPRESS_DB_USER: mywordpress
WORDPRESS_DB_PASSWORD: mywordpress
WORDPRESS_DB_NAME: mywordpress
volumes:
mysql_data: {}
验证
1 | [root@imwl-175 docker-compose-test]# docker stack deploy -c docker-compose.yml wordpress |
11. docker-buildx浅尝
安装
下载 Buildx 插件1
2
3mkdir -p ~/.docker/cli-plugins
curl -sSL https://github.com/docker/buildx/releases/download/v0.14.1/buildx-v0.14.1.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx
chmod +x ~/.docker/cli-plugins/docker-buildx
验证1
docker buildx version
启用 BuildKit1
export DOCKER_BUILDKIT=1
使用 Buildx 构建镜像
1 | docker buildx create --use |
构建多平台镜像
1 | ## 安装 QEMU |
测试
Dockerfile1
2FROM python:3.9.19-alpine
RUN pip3 install kubernetes==29.0.0
构建1
docker buildx build --platform linux/amd64,linux/arm64 -t imwl/py-kubernetes:29.0.0 --push .
查看

12. dockerZabbix使用
服务端使用 docker-compose
1 | version: '2' |
使用 agent2
1 |
|
13. minio搭建及基础使用
环境信息
4 节点,每个节点 4块盘,挂载目录 /mnt/minio{1..4}1
2
3
4
5
6192.168.2.144 minio1
192.168.2.145 minio2
192.168.2.146 minio3
192.168.2.147 minio4
192.168.2.143 registry.harbor.com # 使用 harbor 对接 minio
每台机器上均安装了 docker 和 docker-compose
安装 minio
因为要垮节点,使用 host 网络
docker-compose.yml 所有节点相同
192.168.2.144:8998 可以写成 minio1:8998, 我图方便没有去各个节点修改 /etc/hosts
所有节点均相同1
2
3
4
5
6
7
8
9
10
11
12
13
14
15services:
minio:
image: quay.io/minio/minio:latest
network_mode: "host"
volumes:
- /mnt/minio1:/minio1
- /mnt/minio2:/minio2
- /mnt/minio3:/minio3
- /mnt/minio4:/minio4
environment:
MINIO_ROOT_USER: "minio"
MINIO_ROOT_PASSWORD: "minioadmin"
MINIO_OPTS: "--console-address :9001"
MINIO_PORT: "8998"
command: server --address ":8998" --console-address ":9001" http://192.168.2.144:8998/minio{1...4} http://192.168.2.145:8998/minio{1...4} http://192.168.2.146:8998/minio{1...4} http://192.168.2.147:8998/minio{1...4}
docker-compose -d 启动
使用 nginx 代理
192.168.2.143 机器上1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20upstream minio{
server 192.168.2.144:8998;
server 192.168.2.145:8998;
server 192.168.2.146:8998;
server 192.168.2.147:8998;
}
server {
listen 9000;
server_name minio;
location / {
proxy_pass http://minio;
proxy_set_header Host $http_host;
client_max_body_size 1000m;
}
}
测试
192.168.2.143 上测试
下载 mc, 加入到 PATH 中,并添加 minio-server host1
2
3
4
5wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
mv mc /usr/local/bin/
mc config host add minio-server http://192.168.2.143:8998 minio minioadmin
创建桶 harbor
1 | mc mb minio-server/harbor |
对接
1 | data_volume: /data |
启动后推送查看
1 | mc tree minio-server/harbor |
下载整个 bucket
1 | mc mirror minio-server/harbor ./local-harbor |
上传到新的 bucket test
1 | root@ubuntu:~/# mc mb minio-server/test |
其他 操作基本与 linux 下类似
网页
查看

使用 velero minio 备份k8s
先创建认证文件 credentials-velero
1 | [default] |
安装1
2
3
4
5
6
7
8
9./velero install \
--image velero/velero:v1.15.0 \
--provider aws \
--bucket velero \
--namespace velero \
--plugins velero/velero-plugin-for-aws:main \
--secret-file ./credentials-velero \
--use-volume-snapshots=false \
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://10.68.219.99:9000
简单备份
1 | velero backup create backupk8s |

连接公有云的oss
连接 oracle cloud 对象存储


mc 连接
1 | ## us-phoenix-1 为所在区域,按需修改 |
python 简单测试1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31import boto3
from botocore.client import Config
def init_s3(end_point, access_key, secret_key, region_name):
return boto3.client(
's3',
aws_access_key_id=access_key,
aws_secret_access_key=secret_key,
use_ssl=True,
region_name=region_name,
endpoint_url=end_point,
config=Config(s3={"addressing_style": "path"})
)
## 示例调用
region_name = 'us-phoenix-1'
ns='xxxxxx'
s3_endpoint = f"https://{ns}.compat.objectstorage.{region_name}.oraclecloud.com"
s3_access_key = "xxxxxxx"
s3_secret_key = "xxxxxxxxxx"
s3 = init_s3(s3_endpoint, s3_access_key, s3_secret_key, region_name)
try:
# 列出所有存储桶
response = s3.list_buckets()
for bucket in response.get('Buckets', []):
print(f"Bucket Name: {bucket['Name']}")
except Exception as e:
print(f"Error: {e}")
运行1
2
3$ python client.py
Bucket Name: bucket-imwl
Bucket Name: bucket-public
连接 阿里云
遇到的问题
1 | AccessDenied |
一般使用
1 | mc alias set aliyunoss https://oss-cn-hongkong.aliyuncs.com <AccessKey> <SecretKey> --api S3v4 |
连接火山引擎
当前无法使用 mc
https://www.volcengine.com/docs/6349/1288493
1 | 问题描述 |
使用 s3cmd, 需要做如下修改
cn-shanghai 是区域
1 | host_base = tos-s3-cn-shanghai.volces.com |