Docker
Docker的概念
共享主机内核,轻量,隔离且高效,不想虚拟机需要完整的操作系统
上层是多个容器,每个容器独立运行一个应用
中间是Docker,负责管理这些容器
底层是主机操作系统HostOS和基础设施,为容器提供硬件和系统支持

容器核心理念
应用和环境被打包成不可变镜像
每次部署都使用相同的镜像
配置通过环境变量或配置文件注入
问题修复通过重新构建镜像而非修改运行中的容器
Docker的核心理念
镜像(Image)
镜像知识一个只读模块,包含运行应用所需内容:代码、运行、库文件、环境变量和配置文件
特点:
分层存储:镜像由多个层组成,每一层代表一次修改
只读性:镜像本身只读,不能直接修改
可复用:同一个镜像可创建多个容器
版本管理:通过tag进行版本管理
容器(Container)
容器时镜像运行的实例,是一个轻量级,可移植性的执行环境
隔离性:每个容器都有自己文件系统、网络和进程空间
临时性:容器可以被创建、启动、停止、删除
可写层:容器在镜像基础上添加一个可写层
进程级:容器内通常运行一个主进程
仓库(Repository)
仓库和存储和分发镜像的地方,可以包含一个镜像的多个版本
公共仓库:Docker Hub,任何人都可以使用
私有仓库:企业内部搭建,用于存储私有镜像
官方仓库:软件官方维护的镜像仓库
Docker与虚拟机的区别
架构区别

场景对比
|---|-------------|-------------------|
| | 虚拟机使用场景 | 容器使用场景 |
| | 需要完全隔离的环境 | 微服务架构 |
| | 运行不同操作系统的应用 | CI/CD流水线 |
| | 需要硬件级别的安全隔离 | 应用快速部署和扩展,开发环境标准化 |
Docker的架构组件

Docker Client
功能:
用户与Docker交互的主要方式
接收用户命令并发送Docker Daemon
可以远程Docker Daemon通信
Docker Daemon
Docker的核心服务进程
管理镜像、容器、网络和存储卷
监听Docker API请求并处理
Docker Registry
存储和分发Docker镜像
提供镜像的版本管理
支持公有和私有仓库
使用整体流程

Docker常用命令
镜像命令
bash
# 例出所有镜像
[root@node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 3 years ago 13.3kB
centos latest 5d0da3dc9764 3 years ago 231MB
#例如所有镜像id
[root@node1 ~]# docker images -aq
feb5d9fea6a5
5d0da3dc9764
#下载MySQL镜像
[root@node1 ~]# docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete # 分层下载docker image的核心联合文件索引
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
688ba7d5c01a: Pull complete
00e060b6d11d: Pull complete
1c04857f594f: Pull complete
4d7cfa90e6ea: Pull complete
e0431212d27d: Pull complete
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 # 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真实地址
# 删除镜像命令
[root@node1 ~]# docker rmi -f $(docker images -aq) #删除所有镜像
容器命令
新建容器启动
bash
docker run [可选参数] image
# 参数说明
--name="Name" 容器名字
-d 后台方式运行
-it 使用快捷交互方式运行,进入容器查看内容
-p 指定容器端口 -p 8080:8080 (主机端口:容器端口)
-P 随机指定端口
# 启动并进入容器
[root@node1 ~]# docker run -it centos /bin/bash
# 退出容器命令
[root@fc56051b6477 /]# exit #退出即停止
exit
Ctr + P +Q #容器退出但不会停止
# 例出当前正在运行的容器
[root@node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 删除容器
[root@node1 ~]# docker rm 容器id
# 批量删除容器
[root@node1 ~]# docker rm -f `docker ps -aq`
启动和停止容器操作
bash
docker start 容器id
docker restart 容器id
docker stop 容器id
docker kill 容器id
查看容器进程信息
bash
docker top 容器id
# 查看镜像详细数据
docker inspect 容器id
[
{
"Id": "fc56051b6477f2db3b796126127823658c3fcf9bf95c646ca904ffa5f43b59ee",
"Created": "2025-07-28T02:50:06.533466786Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "exited",
"Running": false,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 0,
"ExitCode": 0,
"Error": "",
"StartedAt": "2025-07-28T02:50:06.870607508Z",
"FinishedAt": "2025-07-28T02:51:17.154604984Z"
},
"Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
"ResolvConfPath": "/var/lib/docker/containers/fc56051b6477f2db3b796126127823658c3fcf9bf95c646ca904ffa5f43b59ee/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/fc56051b6477f2db3b796126127823658c3fcf9bf95c646ca904ffa5f43b59ee/hostname",
"HostsPath": "/var/lib/docker/containers/fc56051b6477f2db3b796126127823658c3fcf9bf95c646ca904ffa5f43b59ee/hosts",
"LogPath": "/var/lib/docker/containers/fc56051b6477f2db3b796126127823658c3fcf9bf95c646ca904ffa5f43b59ee/fc56051b6477f2db3b796126127823658c3fcf9bf95c646ca904ffa5f43b59ee-json.log",
"Name": "/silly_mclean",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "bridge",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"ConsoleSize": [
35,
175
],
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "host",
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": [],
"BlkioDeviceWriteBps": [],
"BlkioDeviceReadIOps": [],
"BlkioDeviceWriteIOps": [],
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": [],
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware",
"/sys/devices/virtual/powercap"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/aa5451ca535227500eb778bf36c500db3d1f01f9ecfb0279cd1199ad8eb9fdbd-init/diff:/var/lib/docker/overlay2/d30db0dc5cce265d7c9d91dd409290eb73f490f968c329e0094a6670f2643e9a/diff",
"MergedDir": "/var/lib/docker/overlay2/aa5451ca535227500eb778bf36c500db3d1f01f9ecfb0279cd1199ad8eb9fdbd/merged",
"UpperDir": "/var/lib/docker/overlay2/aa5451ca535227500eb778bf36c500db3d1f01f9ecfb0279cd1199ad8eb9fdbd/diff",
"WorkDir": "/var/lib/docker/overlay2/aa5451ca535227500eb778bf36c500db3d1f01f9ecfb0279cd1199ad8eb9fdbd/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "fc56051b6477",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20210915",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "fc190f97102d538f89d0c337450ae64043e1b0787e4b306b5fc4ac32b08f49e3",
"SandboxKey": "/var/run/docker/netns/fc190f97102d",
"Ports": {},
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "",
"Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "",
"IPPrefixLen": 0,
"IPv6Gateway": "",
"MacAddress": "",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"MacAddress": "",
"NetworkID": "2812d36c28f0fd892fb5124a66324466c92176c1b5274a84898dbf0504d139d6",
"EndpointID": "",
"Gateway": "",
"IPAddress": "",
"IPPrefixLen": 0,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"DriverOpts": null,
"DNSNames": null
}
}
}
}
]
进入当前正在运行的容器
bash
# 方式一
docker exec -it 容器id /bin/bash
方式二
docker attach -it 容器id
# 区别,方式一进入容器后开启一个新的终端,可在里面操作,退出后容器也不会停止
# 方式二进入正在执行的终端后,不会启动新的进程。生产环境不建议使用
部署启动tomcat
bash
[root@node1 ~]# docker pull tomcat
Using default tag: latest
latest: Pulling from library/tomcat
0e29546d541c: Pull complete
9b829c73b52b: Pull complete
cb5b7ae36172: Pull complete
6494e4811622: Pull complete
668f6fcc5fa5: Pull complete
dc120c3e0290: Pull complete
8f7c0eebb7b1: Pull complete
77b694f83996: Pull complete
0f611256ec3a: Pull complete
4f25def12f23: Pull complete
Digest: sha256:9dee185c3b161cdfede1f5e35e8b56ebc9de88ed3a79526939701f3537a52324
Status: Downloaded newer image for tomcat:latest
docker.io/library/tomcat:latest
[root@node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 3 years ago 141MB
tomcat latest fb5657adc892 3 years ago 680MB
mysql latest 3218b38490ce 3 years ago 516MB
hello-world latest feb5d9fea6a5 3 years ago 13.3kB
centos latest 5d0da3dc9764 3 years ago 231MB
[root@node1 ~]# docker run -d -p 3355:8080 --name tomcat01 tomcat
8f9ed2d2a12e4a4e7d5b28d8d88b8caf6dfe099a32c74e9ab775e30bfeffdce2
部署es+kibana
bash
# 自动拉取镜像并下载然后启动elasticsearch
[root@node1 ~]# docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch
# 限制内存大小启动
[root@node1 ~]# docker run -d --name es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="Xms64m -Xmx512m" elasticsearch
# 查看占用的CPU状态
[root@node1 ~]# docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
8f9ed2d2a12e tomcat01 0.10% 50.1MiB / 1.715GiB 2.85% 656B / 0B 0B / 0B 18
# 访问服务器地址加9200端口即可
commit镜像
bash
docker commit 提交容器成为一个新的副本
docker commit -m="提交信息描述" -a="作者" 容器id 目标镜像名:[TAG]
# 1,进入tomcat容器,然后将webapps.dist下文件拷贝到webapps里面
# 2,将自己操作过的容器镜像通过commit提交为一个镜像,我们以后就使用修改过的镜像即可
root@8f9ed2d2a12e:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@8f9ed2d2a12e:/usr/local/tomcat# cd webapps
root@8f9ed2d2a12e:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
# 将操作过的容器通过commit提交为一个镜像,使用修改过的镜像即可,用镜像查看命令看是否提交成功
[root@node1 ~]# docker commit -a="Tian" -m="add webapps app" 8f9ed2d2a12e tomcat02:1.0
[root@node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat02 1.0 76b40495db7f 2 weeks ago 684MB
nginx latest 605c77e624dd 3 years ago 141MB
tomcat latest fb5657adc892 3 years ago 680MB
mysql latest 3218b38490ce 3 years ago 516MB
hello-world latest feb5d9fea6a5 3 years ago 13.3kB
centos latest 5d0da3dc9764 3 years ago 231MB
elasticsearch latest 5acf0e8da90b 6 years ago 486MB
容器数据卷
数据卷介绍
容器持久化同步操作,容器间也可以数据共享
使用数据卷
bash
1,方式一
docker run -it -v 主机目录:容器目录
# 测试文件同步,使用数据卷挂载
[root@node1 ~]# docker run -it -v /home/ceshi:/home centos /bin/bash
# 虚拟机中查看容器详情
[root@node1 ~]# docker inspect 64a2718f6a19
"Mounts": [
{
"Type": "bind",
"Source": "/home/ceshi", # 主机地址
"Destination": "/home", # docker容器内的地址
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
# 容器内容创建文件后,主机中也会同步
[root@64a2718f6a19 home]# touch 1.text
[root@64a2718f6a19 home]# ls
1.text
数据库数据持久化
bash
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
--name 容器名字
[root@node1 ~]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql
然后用本地的mysql连接到服务器创建的mysql就可以实现数据持久化
具名挂载和匿名挂载
bash
# 匿名挂载
[root@node1 ~]# docker run -d -P nginx01 -v /etc/nginx nginx
# 查看所有的volume的情况
[root@node1 ~]# docker volume ls
DRIVER VOLUME NAME
local 5f3f53d2389544f4c93cedec84b769563b1b01e7b5220f4e34fa339f54321b85
local 7948c0be61687d167efa25ec7113d82bd3cde4a640dab8e845d295362c62227f
local 41534caaabfced3bc4a68a6935d2be9c8c80bc64d536094bfef97f82a42ce30b
# 具名挂载
[root@node1 ~]# docker run -d -P --name nginx02 -v detail-nginx:/etc/nginx nginx
[root@node1 ~]# docker volume ls
DRIVER VOLUME NAME
local 5f3f53d2389544f4c93cedec84b769563b1b01e7b5220f4e34fa339f54321b85
local 7948c0be61687d167efa25ec7113d82bd3cde4a640dab8e845d295362c62227f
local 41534caaabfced3bc4a68a6935d2be9c8c80bc64d536094bfef97f82a42ce30b
local detail-nginx
默认挂载路径在/var/lib/volumes/***下
2,方式二
# 编写dockerfile文件内容
[root@node1 docker-test]# vim dockerfile1
[root@node1 docker-test]# cat dockerfile1
FROM centos
VOLUME ["volume01", "volume02"]
CMD echo "---end---"
CMD /bin/bash
# 构建镜像
[root@node1 docker-test]# docker build -f dockerfile1 -t tian/centos .
[root@node1 docker-test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tian/centos latest 2771b5374df0 3 years ago 231MB
# 启动自己容器镜像
[root@node1 docker-test]# docker run -it 2771b5374df0 /bin/bash
# 可以查看到自己挂载的volume1和volume2
[root@cdd6785e8626 /]# ls -l
drwxr-xr-x 20 root root 4096 Sep 15 2021 var
drwxr-xr-x 2 root root 4096 Aug 13 07:38 volume01
drwxr-xr-x 2 root root 4096 Aug 13 07:38 volume02
数据卷容器
bash
# 容器数据间之间继承
docker run -it --name 子容器 --volumes-from 父容器 镜像名
# 启动docker01容器
[root@node1 ~]# docker run -it --name docker01 tian/centos
# 启动docker02并继承docker01数据卷
[root@node1 ~]# docker run -it --name docker02 --volumes-from docker01 tian/centos
# 在docker01中创建docker01文件,docker02容器中也会有
[root@82922241b4a1 /]# cd volume01
[root@82922241b4a1 volume01]# ls
[root@82922241b4a1 volume01]# touch docker01.txt
# docker02中查看
[root@eb45c1458930 volume01]# ls
docker01.txt
结论:容器之间配置信息传递,数据卷容器的生命周期一直持续到没有容器使用为止
一旦持久化到本地,则本地数据不会删除
Dockerfile
概念
是用来构建docker镜像的文件,命令参数脚本
构建步骤
1,编写dockerfile文件
2,docker build构建成一个镜像
3,docker run 运行镜像
4,docker push发布镜像(DockerHub、阿里云镜像仓库等)
指令
bash
FROM:指定基础镜像
MAINTAINER:镜像名+邮箱,知道镜像作者
RUN:在镜像中执行命令
ADD/COPY:添加内容(ADD可以自动解压,url等COPY只能复制本地文件,一般用COPY)
WORKDIR:镜像的工作目录
VOLUME:挂载的目录
CMD:指定容器启动时默认执行的命令,只有最后一个会生效,会被docker run命令参数覆盖
ENTRYPOINT:指定容器启动时默认执行的命令,可以追加命令
EXPOSE:暴露容器端口
ENV:设置环境变量
发布自己镜像
1,注册自己账号
2,在服务器提交自己镜像
bash
# 登录dockerhub账号
[root@node1 ~]# docker login -u
# 镜像发布
[root@node1 ~]# docker tag 82922241b4a1 tian/mytomcat:1.0
[root@node1 ~]# docker push tian/mytomcat:1.0
阿里云镜像发布
1,登录阿里云
2,找到容器服务
3,创建命名空间
4,创建后参考阿里云官方文档

bash
1,[root@node1 ~]# docker login -阿里云镜像名
2,[root@node1 ~]# docker push tian/mytomcat:1.0
Docker网络
bash
# 产看容器网络
[root@node1 ~]# docker exec -it tomcat01 ip addr
# ping容器网络
[root@node1 ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.1) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.054 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.042 ms
原理
1,每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0。默认是桥接模式,使用技术是veth-pair技术
2,veth-pair技术。是一对虚拟设备接口,成对出现,一端连接协议,一端彼此相连。每当创建一个容器后,会发现会成对网卡会成对。如63和62
bash
[root@node1 ~]# ip addr
63: veth97ae6d5@if62: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether c2:32:12:50:67:19 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::c032:12ff:fe50:6719/64 scope link
3,容器之间可以进行通信
bash
[root@node1 ~]# docker exec -it tomcat02 ping 172.17.0.2
网络模型
所有容器在不指定网络情况下,都是docker0路由的,docker会给我们容器分配默认的可用ip。docker所有网络接口都是虚拟的,虚拟的转发效率高。
自定义网络
docker网络模式
bash
# bridge为桥接模式
# none 不配置网络
# host 和宿主机共享网络
[root@node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
2812d36c28f0 bridge bridge local
dc2de3ca0a28 host host local
b2881497f8dc none null local
# 自定义网络
# --driver bridge 模式
# --subnet 192.168.0.0/16 子网掩码
# --gateway 192.168.0.1 网关
[root@node1 ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
8b893895d220e75481baa19bdc299edf7ce08bb8c9694840a2b9d042b9575f18
[root@node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
8b893895d220 mynet bridge local
# 启动容器
[root@node1 ~]# docker run -d -P --name tomcat-net01 --net mynet tomcat
fee2e32bf773af3959d14cbbd8ce8370d55938210863acd5b873bc370d487155
[root@node1 ~]# docker run -d -P --name tomcat-net02 --net mynet tomcat
4ca35984edef567b95ffd457d1aba87fd0d75695b9ee34fdff7fe33e49dc5e2a
# 查看该网络中自己容器
[root@node1 ~]# docker network inspect mynet
"4ca35984edef567b95ffd457d1aba87fd0d75695b9ee34fdff7fe33e49dc5e2a": {
"Name": "tomcat-net02",
"EndpointID": "ec8ac64a0e798fb7cec075cf2132ea14a75b9e1f89d2504666cd1b1bbc6087e1",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"fee2e32bf773af3959d14cbbd8ce8370d55938210863acd5b873bc370d487155": {
"Name": "tomcat-net01",
"EndpointID": "185603b16ae9e9fbcfd7f51c50186bd87ef38c597fb538efa7d3d5b7790ac553",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
# 容器1可以ping容器2的网络,修复了docker0网络中不能ping容器名的bug
[root@node1 ~]# docker exec -it tomcat-net01 ping tomcat-net02
网络连接
bash
# 创建网络与tomcat01连接
# 一个容器两个ip地址
[root@node1 ~]# docker network connect mynet tomcat01
部署Redis集群
bash
1,# 创建Redis集群网络
[root@node1 ~]# docker network create redis --subnet 172.38.0.0/16
204e78bce60280e035f11d4531f5dfea2a60a62fcc0f87b95198836250baac58
[root@node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
2812d36c28f0 bridge bridge local
dc2de3ca0a28 host host local
204e78bce602 redis bridge local
2,# shell脚本,创建六个docker容器
[root@node1 ~]# for port in $(seq 1 6);\
> do \
> mkdir -p /mydata/redis/node-${port}/conf
> touch /mydata/redis/node-${port}/conf/redis.conf
> cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
> port 6379
> bind 0.0.0.0
> cluster-enable yes
> cluster-config-file nodes.conf
> cluster-node-timeout 5000
> cluster-announce-ip 172.38.0.1${port}
> cluster-announce-port 6379
> cluster-announce-bus-port 16379
> appendonly yes
> EOF
> done
#说明
# cluster-enable yes 启用Redis集群模式
# cluster-config-file nodes.conf 指定用于保存集群节点配置的文件名
# cluster-node-timeout 5000 节点超时时间,超过次响应时间则认为该节点失效
# cluster-announce-ip 172.38.0.1${port} ip地址
# cluster-announce-port 6379 端口
# cluster-announce-bus-port 16379 集群总线端口
# appendonly yes 启用AOF作为持久化方式
3,# 启动所有redis节点
# 循环启动6个Redis容器节点
for port in $(seq 1 6);
do
docker run -d -p 637${port}:6379 -p 1637${port}:16379 \
--name redis-${port} \
--net redis \
--ip 172.38.0.1${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
redis:6.2.6 redis-server /etc/redis/redis.conf
done
# 查看启动的容器
docker ps | grep redis
4, # 创建集群
[root@node1 ~]# docker exec it redis-6379 env REDISCLI_AUTH==1234 redis-cli --cluster create \
172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 \
172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 \
--cluster-replicas 1 \
--cluster-yes
5,验证集群状态
[root@node1 ~]# docker exec -it redis-6379 redis-cli -h 172.38.0.11 -p 6379 -a "1234" cluster nodes
Docker Compose
安装
1,下载安装
bash
curl -L https://get.daocloud.io/docker/compose/releases/download/v2.4.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
2,赋予执行权限
bash
sudo chmod +x /usr/local/bin/docker-compose
3,查看版本
bash
docker-compose --version
实战
docker compose启动Wordpress
bash
1,创建一个docker-compose.yaml文件
2,yaml文件内容
name:myblog
version :'3'
services:
mysql:
container_name: mysql
image: mysql:8.0
build:
context:./mysql
ports:
-"3306:3306"
volumes:
-mysql-data:/var/lib/mysql
-./app/myconf:/etc/mysql/conf.d
environment:
MYSQL_DATABASE:'root'
MYSQL_ROOT_PASSWORD:'123456'
restart: always
networls:
-blog
Wordpress:
image: wordpress
ports:
-"8080:80"
environment:
WORDPRESS_DB_HOST:mysql
WORDPRESS_DB_USER:root
WORDPRESS_DB_PASSWORD:'123456'
WORDPRESS_DB_NAME:wordpress
volumes:
- wordpress:/var/www/html
restart:always
networks:
- blog
depends_on:
-mysql
volumes:
mysql-data:
wordpress:
network:
blog:
3,使用docker-compose up创建启动即可
yaml文件详情
bash
1,version
指定本 yml 依从的 compose 哪个版本制定的。
2,build
指定为构建镜像上下文路径
3,command
覆盖容器启动的默认命令。
4,container_name
指定自定义容器名称,而不是生成的默认名称。
5,depends_on
设置依赖关系
例如
web:
build: .
depends_on:
- db
- redis
docker-compose up :以依赖性顺序启动服务。在以下示例中,先启动 db 和 redis ,才会启动 web
6,deploy
指定与服务的部署和运行有关的配置。只在 swarm 模式下才会有用。
7,environment
添加环境变量。您可以使用数组或字典、任何布尔值,布尔值需要用引号引起来,以确保 YML 解析器不会将其转换为 True 或 False
8,networks
配置容器连接的网络,引用顶级 networks 下的条目
9,restart
no:是默认的重启策略,在任何情况下都不会重启容器。
always:容器总是重新启动
10,volumes
将主机的数据卷或者文件挂载到容器里。
Docker Swarm
概念
swarm manager:负责整个集群的管理工作包括集群配置、服务管理等所有集群有关工作
work node:主要负责运行相应的服务来执行任务
示例图:

命令
bash
[root@localhost ~]# docker swarm --help
Usage: docker swarm COMMAND
Manage Swarm
Commands:
ca Display and rotate the root CA
init Initialize a swarm
join Join a swarm as a node and/or manager
join-token Manage join tokens
leave Leave the swarm
unlock Unlock swarm
unlock-key Manage the unlock key
update Update the swarm
Run 'docker swarm COMMAND --help' for more information on a command.
# 初始化命令
[root@localhost ~]# docker swarm init --help
Usage: docker swarm init [OPTIONS]
Initialize a swarm
Options:
--advertise-addr string Advertised address (format: <ip|interface>[:port])
--autolock Enable manager autolocking (requiring an unlock key to start a stopped manager)
--availability string Availability of the node ("active"|"pause"|"drain") (default "active")
--cert-expiry duration Validity period for node certificates (ns|us|ms|s|m|h) (default 2160h0m0s)
--data-path-addr string Address or interface to use for data path traffic (format: <ip|interface>)
--data-path-port uint32 Port number to use for data path traffic (1024 - 49151). If no value is set or is set to 0, the default port (4789) is used.
--default-addr-pool ipNetSlice default address pool in CIDR format (default [])
--default-addr-pool-mask-length uint32 default address pool subnet mask length (default 24)
--dispatcher-heartbeat duration Dispatcher heartbeat period (ns|us|ms|s|m|h) (default 5s)
--external-ca external-ca Specifications of one or more certificate signing endpoints
--force-new-cluster Force create a new cluster from current state
--listen-addr node-addr Listen address (format: <ip|interface>[:port]) (default 0.0.0.0:2377)
--max-snapshots uint Number of additional Raft snapshots to retain
--snapshot-interval uint Number of log entries between Raft snapshots (default 10000)
--task-history-limit int Task history retention limit (default 5)
Raft协议
保证大多数节点存活才可以(至少>2)
bash
1,初始化swarm集群,生成主节点
[root@localhost ~]# docker swarm init --advertise-addr 192.168.0.250
Swarm initialized: current node (xa4tcvtx0ss80pu7zsy975xf1) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-2nz7pe5u74to8kkyqam343fa1ldkwbui5o5ang480nxcl55wvq-2o0qo4iazn44s0h4akqo00su5 192.168.0.250:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
2,添加节点令牌并加入节点
# 管理节点令牌
docker swarm join-token manager
# 工作节点令牌
docker swarm join-token worker
[root@localhost ~]# docker swarm join --token SWMTKN-1-2nz7pe5u74to8kkyqam343fa1ldkwbui5o5ang480nxcl55wvq-2o0qo4iazn44s0h4akqo00su5 192.168.0.250:2377
This node joined a swarm as a worker.
3,启动两个manager节点和两个worker节点, 查看当前节点状态
[root@localhost ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
4detbmr2ziwikj91j9x6lsbhs localhost.localdomain Ready Active 19.03.13
7j34gp7d1xrijkwxy2nprmp89 localhost.localdomain Ready Active Reachable 19.03.13
tgvu8ep05zohd6x5h7ab9n8c6 localhost.localdomain Ready Active 19.03.13
xa4tcvtx0ss80pu7zsy975xf1 * localhost.localdomain Ready Active Leader 19.03.13
4,将主节点1停止测试
[root@localhost ~]# systemctl stop docker
Warning: Stopping docker.service, but it can still be activated by:
docker.socket
5,在给一个manager节点查看状态(剩余一个主节点, 集群不能工作)
[root@localhost ~]# docker node ls
Error response from daemon: rpc error: code = DeadlineExceeded desc = context deadline exceeded
[root@localhost ~]# docker node ls
Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.
6,重新启动主节点1, 重新查看节点状态
[root@localhost ~]# systemctl start docker
[root@localhost ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
4detbmr2ziwikj91j9x6lsbhs localhost.localdomain Ready Active 19.03.13
7j34gp7d1xrijkwxy2nprmp89 localhost.localdomain Ready Active Leader 19.03.13
tgvu8ep05zohd6x5h7ab9n8c6 localhost.localdomain Ready Active 19.03.13
xa4tcvtx0ss80pu7zsy975xf1 * localhost.localdomain Ready Active
7,把其中一个worker离开集群
[root@localhost ~]# docker swarm leave
Node left the swarm.
[root@localhost ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
4detbmr2ziwikj91j9x6lsbhs localhost.localdomain Ready Active 19.03.13
7j34gp7d1xrijkwxy2nprmp89 localhost.localdomain Ready Active Leader 19.03.13
tgvu8ep05zohd6x5h7ab9n8c6 localhost.localdomain Down Active 19.03.13
xa4tcvtx0ss80pu7zsy975xf1 * localhost.localdomain Ready Active Reachable 19.03.13
8,重新作为manager加入集群
[root@localhost ~]# docker swarm join --token SWMTKN-1-2nz7pe5u74to8kkyqam343fa1ldkwbui5o5ang480nxcl55wvq-boj74lujjljzvyvtlprh0fqpa 192.168.0.250:2377
This node joined a swarm as a manager.
[root@localhost ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
4detbmr2ziwikj91j9x6lsbhs localhost.localdomain Ready Active 19.03.13
7j34gp7d1xrijkwxy2nprmp89 localhost.localdomain Ready Active Leader 19.03.13
msrkboug93zfzmf1s3koxtyx0 localhost.localdomain Ready Active Reachable 19.03.13
tgvu8ep05zohd6x5h7ab9n8c6 localhost.localdomain Down Active 19.03.13
xa4tcvtx0ss80pu7zsy975xf1 * localhost.localdomain Ready Active Reachable 19.03.13
9, 再次停止一个主节点, 查看状态 (剩余两个主节点, 集群正常工作)
[root@localhost ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
4detbmr2ziwikj91j9x6lsbhs localhost.localdomain Ready Active 19.03.13
7j34gp7d1xrijkwxy2nprmp89 * localhost.localdomain Ready Active Leader 19.03.13
msrkboug93zfzmf1s3koxtyx0 localhost.localdomain Ready Active Reachable 19.03.13
tgvu8ep05zohd6x5h7ab9n8c6 localhost.localdomain Down Active 19.03.13
xa4tcvtx0ss80pu7zsy975xf1 localhost.localdomain Ready Active Unreachable 19.03.13
弹性扩缩容
单机: 启动一个项目: docker-compose up
集群: swarm, docker service(服务启动,具备扩缩容器,滚动更新)
灰度发布:金丝雀发布(滚动发布)
bash
1,创建nginx服务
[root@localhost ~]# docker service create -p 8888:80 --name mynginx nginx
pqn9zyf0dvrrxwh8mwo66hwth
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
2,扩容增加3个服务
[root@localhost ~]# docker service update --replicas 3 mynginx
mynginx
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
verify: Service converged
3,打开浏览器访问其中一台机器 (集群中任意节点都可以访问服务)
4,回滚容器(减少)
[root@localhost ~]# docker service update --replicas 1 mynginx
mynginx
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
# 查看状态
[root@localhost ~]# docker service ps mynginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
tjr17l8ryj6e mynginx.1 nginx:latest localhost.localdomain Running Running 18 minutes ago
5,scale命令扩缩容 (等于update)
[root@localhost ~]# docker service scale mynginx=5
mynginx scaled to 5
overall progress: 5 out of 5 tasks
1/5: running [==================================================>]
2/5: running [==================================================>]
3/5: running [==================================================>]
4/5: running [==================================================>]
5/5: running [==================================================>]
verify: Service converged
实战
bash
1,创建swarm集群管理节点,该节点为manager
[root@node1 ~]# docker-machine create -d virtualbox swarm-manager
2,初始化swarm集群,进行初始化这台机器,就是集群的管理节点
[root@node1 ~]# docker-machine ssh swarm-manager
[root@node1 ~]# docker swarm init --addvertise-addr 172.38.1.1
3,创建swarm集群工作节点,该节点为worker
[root@node1 ~]# docker-machine create -d virtualbox swarm-work1
[root@node1 ~]# docker-machine create -d virtualbox swarm-work2
[root@node1 ~]# docker-machine ssh worker1
docker@swarm-worker1:~$ docker swarm join --token SWMTKN-1-4oogo9qziq768dma0uh3j0z0m5twlm10iynvz7ixza96k6jh9p-ajkb6w7qd06y1e33yrgko64sk 172.38.1.2:2377
4,查看集群信息
[root@node1 ~]# docker info
5,部署服务到集群中,创建一个hello的服务在工作节点上
docker@swarm-manager:~$ docker service create --replicas 1 --name helloalpine ping docker.com
6,查看helloworld服务运行在哪个节点上
docker@swarm-manager:~$ docker service ps helloworld
7,扩展集群服务,爱你过helloworld服务扩展到两个节点
docker@swarm-manager:~$ docker service scale helloworld=2
8,删除服务
docker@swarm-manager:~$ docker service rm helloworld
9,创建一个 3.0.6 版本的 redis
docker@swarm-manager:~$ docker service create --replicas 1 --name redis --update-delay 10s redis:3.0.6
10,滚动升级 redis
docker@swarm-manager:~$ docker service update --image redis:3.0.7 redis