前言
当然,Docker
在运维 的工作中也是不可或缺的!
之前其实已经写了一篇Docker
了,但是已经全忘了。害!
该篇的目的是为了了解Docker
基本操作,并且会用Docker
。
参考文献
Docker
架构

Docker daemon
理解成Docker
服务。
Docker
是一个Client - Server
的结构系统,Docker
的守护进程(Docker daemon
)运行在主机上,通过Socket
从客户端访问。

-H fd://
:Docker
默认通过Unix
套接字(/var/run/docker.sock
)通信。--containerd=/run/containerd/containerd.sock
:使用containerd
作为容器运行时。
不知道大家是否学过MySQL
,连接到MySQL
怎么做?
服务器 进程和客户端 进程都运行在同一台操作系统为类Unix
的机器上的话,可以使用Unix
域套接字文件来进行进程间通信。
不同进程间 通过套接字文件通信。
Docker Client
客户端,怎么理解呢?小黑框输入命令等待服务端响应。

Docker_HOST
服务端,接收命令,做出反应。- 镜像
images
理解成类 ,容器Containers
就是对象。
安装Docker
CentOS8 CentOS9
都能用。

为什么是Docker Engine
,在Docker Engine
包含着docker daemon
和 docker CLI
。
bash
dnf -y install dnf-plugins-core
dnf config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
dnf makecache
docker-ce
docker引擎(ce
社区版,ee
企业版)docker-ce-cli
docker引擎命令行程序container.io
docker的运行环境docker-buildx-plugin
构建镜像的插件工具docker-compose
做批量工具一次性都安装
bash
#启动docker
systemctl start docker
#判断是否安装成功,查看是否有版本。
docker version
docker run hello-world
启动不起来?
bash
#关闭防火墙
#一句话总结一下,如果关闭防火墙,就相当于对外暴露所有端口
systemctl stop firewalld.service
systemctl disable firewalld.service
#配置镜像源
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<EOF
{ #修改镜像源
"registry-mirrors": [
"https://docker.1ms.run",
"https://hub.rat.dev",
"https://docker.1panel.live"
]
}
EOF
#重启后台进程
sudo systemctl daemon-reload
#重启docker
sudo systemctl restart docker

查看安装的镜像
bash
[root@CentOS8 /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest 74cc54e27dc4 5 weeks ago 10.1kB
卸载Docker
bash
#卸载依赖
sudo dnf remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
#删除资源,资源一般都在lib目录下
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
Namespace
命名空间 是Linux
核心在 2.4
版本后逐渐引入的一项用于运行隔离的模块。
Linux
内核的命名空间 ,就是能够将计算机资源 进行切割划分,形成各自独立的空间。
Linux
的 PID Namespace
是资源隔离的核心机制之一。通过它,系统可以创建一个独立的进程运行环境,其中的进程编号(PID
)会从1
开始重新计数,就像在一个全新的操作系统中运行一样。
容器内的进程 无法感知宿主机 或其他容器 的进程(例如容器内的 PID 44
进程,在宿主机中可能显示为 PID 1543
)。
Control Groups
资源控制组 的作用就是控制计算机资源 的。通过 CGroups
,可以指定任意一个隔离环境对任意资源的占用值或占用率,这对于很多分布式使用场景来说是非常有用的功能。
Run
的流程和Docker
原理

镜像
bash
#显示docker的版本
docker version
#显示docker的系统信息
docker info
#万能命令
docker 命令 --help
[root@CentOS8 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest 74cc54e27dc4 5 weeks ago 10.1kB
REPOSITORY
:镜像的仓库源。TAG
:镜像的标签(说白了就是版本)。IMAGE ID
:镜像的ID
CREATED
:镜像的创建时间SIZE
:镜像的大小
bash
-a, --all #列出所有镜像
-q, --quiet #只显示镜像的ID
#列出所有的docker镜像ID
[root@CentOS8 ~]# docker images -aq
74cc54e27dc4
拉取镜像,也就是下载镜像。
bash
[root@CentOS8 ~]# docker pull mysql
Using default tag: latest #latest 代表着最新版
latest: Pulling from library/mysql
43759093d4f6: Pull complete # 分层下载,docker images的核心 联合文件系统
d255dceb9ed5: Pull complete
23d22e42ea50: Pull complete
431b106548a3: Pull complete
2be0d473cadf: Pull complete
f56a22f949f9: Pull complete
277ab5f6ddde: Pull complete
df1ba1ac457a: Pull complete
cc9646b08259: Pull complete
893b018337e2: Pull complete
Digest: sha256:146682692a3aa409eae7b7dc6a30f637c6cb49b6ca901c2cd160becc81127d3b #签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真实地址
docker pull mysql == docker pull docker.io/library/mysql:latest
#指定版本下载
[root@CentOS8 ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
20e4dcae4c69: Pull complete
1c56c3d4ce74: Pull complete
e9f03a1c24ce: Pull complete
68c3898c2015: Pull complete
6b95a940e7b6: Pull complete
90986bb8de6e: Pull complete
ae71319cb779: Pull complete
ffc89e9dfd88: Pull complete
43d05e938198: Pull complete
064b2d298fba: Pull complete
df9a4d85569b: Pull complete
Digest: sha256:4bc6bc963e6d8443453676cae56536f4b8156d78bae03c0145cbe47c2aad73bb
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
删除镜像
bash
#删除单个镜像
docker rmi mysql:5.7
#删除多个镜像
docker rmi 镜像名 镜像名 镜像名
#删除所有docker镜像
docker rmi -f $(docker images -aq)
容器
bash
docker pull centos
新建容器并启动
bash
docker run [可选参数] image
#参数说明
--name="Name" 容器名字 tomcat01 tomcat02,用来区分容器。
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 --p 8080:8080
-P 随机指定端口
启动并进入容器
bash
docker run -it centos /bin/bash
#容器内和容器外是不是很相似
#容器内就是centos环境,基础版本,很多命令都是不完善的。
[root@886344be63b1 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
列出所有运行的容器
bash
docker ps
docker ps -aq
退出容器
bash
exit #直接容器停止并退出
ctrl + P + Q #容器不停止退出
删除容器
bash
docker rm 容器ID # 删除指定容器,不能删除正在运行的容器,如果要强制删除rm -f
docker rm -f $(docker ps -aq) # 删除所有容器
后台启动容器
bash
#命令 docker run -d 镜像名
docker run -d centos
docker ps
,发现centos
停止了。
docker
容器使用后台运行,就必须要有一个前台进程,docker
发现没有应用,就会自动停止。
bash
#前台运行状态
ping baidu.com
#后台运行
nohup ping baidu.com &
此时停止前台运行容器,发现容器就停止了!
docker
容器使用后台运行,就必须要有一个前台进程,docker
发现没有应用,就会自动停止。
再看这句话,此时我没有任何一个窗口被前台进程所占用是否是理解错问题呢?
Nginx
在容器中通常以"daemon off
"方式运行,强制它保持在前台,这样主进程 不会退出,容器持续运行。
bash
#主进程:
root 1288 1 0 22:28 ? 00:00:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
进入当前正在运行的容器
bash
docker exec -it 容器id /bin/bash
那么centos
容器我们退出了它就关闭了,如果再次进入呢?
bash
[root@CentOS8 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1df6775e71d5 centos "/bin/bash" 14 minutes ago Exited (127) 2 seconds ago hardcore_nash
[root@CentOS8 ~]# docker start 1df6775e71d5
1df6775e71d5
#两种方式:
docker attach 1df6775e71d5
docker exec -it 1df6775e71d5 /bin/bash
从容器拷贝文件到主机上
bash
docker cp 容器id:容器内路径 目的主机路径
docker run -it centos /bin/bash
[root@e2f90d4ed867 /]# cd /home/
[root@e2f90d4ed867 home]# touch test.txt
[root@e2f90d4ed867 home]# exit
[root@CentOS8 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e2f90d4ed867 centos "/bin/bash" About a minute ago Exited (0) 20 seconds ago bold_cerf
docker cp e2f90d4ed867:/home/test.txt /home
cd /home
ls
test.txt
日志,元数据,进程
查看日志 (重点)
bash
docker logs -f 容器名
查看容器中进程信息ps
bash
# 命令 dockers top 容器id
docker top 容器id
元数据 (重点)
bash
docker inspect 容器名
部署Nginx
bash
docker pull nginx
docker run -d --name nginx01 -p 3344:80 nginx
-p
通过主机上的端口3344
可以访问容器内80
。
端口暴露

部署Tomcat
bash
docker run -it --rm tomcat:9.0
退出,会发现容器没了。
ctrl + C

bash
#会发现没有tomcat容器了
docker ps -a
bash
docker images
docker run -d -p 3355:8080 --name tomcat01 tomcat

bash
# 发现问题:
# Linux命令少了
# 没有webapps,阿里云镜像的原因,默认最小的镜像,所有不必要的都剔除掉。
# 保证最小可运行的环境
docker exec -it tomcat01 /bin/bash
ls
webapps
cd webapps
ls
pwd
/usr/local/tomcat
cp -rf webapps.dist/* webapps
再查看网站信息

部署ES + Kibana
es
是elasticsearch6
搜索引擎,kibana
是它的可视化操作界面
bash
#es 暴露端口多,耗内存。
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:8.0.0
#查看CPU的状态
docker stats 容器名

bash
可以连接上
[root@CentOS8 home]# curl -v localhost:9300
* Rebuilt URL to: localhost:9300/
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9300 (#0)
> GET / HTTP/1.1
> Host: localhost:9300
> User-Agent: curl/7.61.1
> Accept: */*
>
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server

bash
#这个是JVM的知识
-ES_JAVA_OPT="-Xms64m -Xmx512m"
# 运行容器(包含数据持久化和安全配置)
docker run -d \
--name elasticsearch \
-p 9200:9200 \
-p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
elasticsearch:8.0.0

bash
[root@CentOS8 ~]# curl -v localhost:9300
* Rebuilt URL to: localhost:9300/
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9300 (#0)
> GET / HTTP/1.1
> Host: localhost:9300
> User-Agent: curl/7.61.1
> Accept: */*
>
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server
联合文件系统
镜像到底是什么?
镜像是一种轻量级,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
所有的应用,直接打包docker
镜像,就可以直接跑起来。
如何得到镜像:
- 从远程仓库下载
- 朋友拷贝给你
- 自己制作一个镜像
DockerFile
先介绍一下Git
控制版本
- 第一步(层):安装了
centos
。 - 第二步(层):安装了
docker
。 - 第三步(层):安装了
jdk
。
UnionFS
(联合文件系统 ),它支持文件系统 的修改作为一次提交来一层层的叠加。
我们对一个项目的修改,只需要管增加的部分,增加的部分则是一层。

dockers
的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS
。
bootfs
:系统启动需要引导加载,主要包含bootloader
和kernel bootloader
主要是引导加载kernel
,Linux
刚启动会加载bootfs
。
- 点火装置 (
bootloader和kernel bootloader
):负责检查设备 是否正常,然后点燃引擎; - 火箭主体 (
kernel内核
):相当于火箭的核心部分,启动后就能带电脑飞起来。
黑屏 -> 加载 -> 开机进入系统
无论是什么镜像,bootfs
是公用的!
Docker
容器直接复用宿主机的内核 ,所以不用内核相关 的,启动快占用少。
roofs
在bootfs
之上,包含典型的Linux
系统中的/dev /proc /bin /etc
等标准目录和文件。rootfs
就是各种不同的操作系统发行版,比如Ubuntu
、Centos
等等。
Docker
镜像都是只读 ,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层就是通常说的容器层 ,容器之下的都叫镜像层。

写时复制
容器 修改的/etc/passwd
是修改的是容器层 ,镜像层 是只读 的这就是写时复制特性
也就是镜像层 里面的东西是不会变的变得只是你添加的东西所以你需要-v
利用卷组保留数据。
写时复制 (CoW
) 是一种资源管理策略 ,其核心逻辑是:在数据未被修改 时,允许多个引用共享同一份原始数据 ;当任一引用尝试修改数据时,系统才会为该引用创建独立的数据副本 。此机制通过延迟复制 操作,显著优化了资源利用率 和性能。
容器数据卷
如果数据在容器中,那么删除容器,数据会丢失!需求!数据可以持久化
MySQL
,容器删除了,删库跑路!需求:MySQL数据可以存储在本地!
容器之间有一个数据共享的技术,Docker
容器中产生的数据,同步到本地!
这就是卷技术 !目录的挂载,将容器内的目录,挂载到Linux
上面!
总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的!
bash
docker run -it -v 主机目录:容器内目录
# 测试
docker run -it -v /home/test:/home centos /bin/bash

bash
docker ps -a
docker inspect 1df6775e71d5

其实这怎么形容呢?是否看过JOJO
的"恋人"那一集。
也就是我操作/home
目录下的东西,/home/test
目录也会跟着改变。
比如在/home
目录下增加一个文件,/home/test
也会增加一个同样的文件。
具名和匿名挂载
bash
# 匿名挂载
-v 容器内路径 不指定主机目录
docker run -d -P --name nginx01 -v /etc/nginx nginx
[root@CentOS8 ~]# docker volume ls
DRIVER VOLUME NAME
local 0338f9c041b34701c5ea638938801bdf2fd3261f9d6e11924528f5dcdd4ddfb2 #没有取名字为匿名卷
#具名挂载
#通过 -v 卷名:容器内路径
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
[root@CentOS8 ~]# docker volume ls
DRIVER VOLUME NAME
local juming-nginx #这里就有名字了
[root@CentOS8 ~]# docker volume inspect juming-nginx
[
{
"CreatedAt": "2025-03-04T16:51:22+08:00",
"Driver": "local",
"Labels": null,
#此处为主机目录的地址
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
所有的
docker
容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxx/
。
bash
# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载。
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载
扩展:
bash
# 通过 -v 容器内路径:ro rw 改变读写权限
ro readonly #只读
rw readwrite #可读可写
# 一旦这个设置了容器权限,容器对挂载出来的内容就有限定了。相对于容器来说
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
#这个目录只能从外部改变了,不能从内部改变了。
# ro 只要看到 ro 就说明这个路径只能通过宿主机操作,容器内部无法操作。
ro /etc/nginx
测试一下
bash
docker run -it -v /home/test:/home:ro centos /bin/bash
[root@fcd193845507 home]# touch a.txt
touch: cannot touch 'a.txt': Read-only file system

MySQL
部署
这位大佬写的非常详细
Docker部署MySQL 8.3.0(保姆级图文教程)
bash
docker pull mysql:8.3.0
[root@CentOS8 ~]# docker images mysql:8.3.0
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 8.3.0 6f343283ab56 11 months ago 632MB
mkdir -p /home/mysql/{conf,data,log}

bash
cd /home/mysql/conf
vi my.cnf
[client]
#设置客户端默认字符集utf8mb4
default-character-set=utf8mb4
[mysql]
#设置服务器默认字符集为utf8mb4
default-character-set=utf8mb4
[mysqld]
default_authentication_plugin=mysql_native_password
#配置服务器的服务号,具备日后需要集群做准备
server-id = 1
#开启MySQL数据库的二进制日志,用于记录用户对数据库的操作SQL语句,具备日后需要集群做准备
log-bin=mysql-bin
#设置清理超过30天的日志,以免日志堆积造过多成服务器内存爆满。2592000秒等于30天的秒数
binlog_expire_logs_seconds = 2592000
#解决MySQL8.0版本GROUP BY问题
sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
#允许最大的连接数
max_connections=1000
# 禁用符号链接以防止各种安全风险
symbolic-links=0
# 设置东八区时区
default-time_zone = '+8:00'
启动容器
bash
#\代表换行
#--privileged=true表示赋予容器权限修改宿主文件权利
#--restart=always表示容器退出时总是重启
#-e 是配置环境,MYSQL_ROOT_PASSWORD=a12bCd3_W45pUq6表示设置mysql的root用户密码
#-d表示后台运行
#可以多个-v 挂载日志、数据、配置文件。
docker run \
-p 3306:3306 \
--restart=always \
--name mysql \
--privileged=true \
-v /home/mysql/log:/var/log/mysql \
-v /home/mysql/data:/var/lib/mysql \
-v /home/mysql/conf/my.cnf:/etc/mysql/my.cnf \
-e MYSQL_ROOT_PASSWORD=password\
-d mysql:8.3.0
再开一个窗口
[root@CentOS8 conf]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d837a375948f mysql:8.3.0 "docker-entrypoint.s..." 4 seconds ago Up 3 seconds 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql
[root@CentOS8 conf]# docker exec -it d837a375948f /bin/bash
mysql -uroot -ppassword
use mysql;
mysql> select user,host from user;
+------------------+-----------+
| user | host |
+------------------+-----------+
| root | % |
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+-----------+
5 rows in set (0.00 sec)
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
flush privileges;

Docker
网络

bash
#-d 后台运行
#-P 端口随机
#-name 指定名字
#运行tomcat镜像,生成容器。
docker run -d -P --name tomcat01 tomcat
进入镜像
bash
#进入容器内部
docker exec -it tomcat01 /bin/bash
cd /etc
#可见操作系统版本是Ubuntu
root@d9b71213acb7:/etc# cat os-release
PRETTY_NAME="Ubuntu 24.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.1 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo
#让系统去官网检查所有软件的最新版本信息。
apt update
#安装一个叫 iproute2 的软件包,这个包里全是管理网络的神器。
apt install iproute2
bash
#不进入容器也能查看到容器信息
#发现容器启动的时候都会得到一个eth0@if5 ip地址,Docker分配的。
docker exec -it tomcat01 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
Linux
是否能ping
通容器内部 ?
能,因为一个容器 就是一个进程。
bash
ping 172.17.0.2
Linux
可以ping
通docker
容器内部。
docker0
的ip
为172.17.0.1
,容器内eho@if5
的ip
为172.17.0.2
。
在同一个网段 ,是可以相互ping
通的,docker0
就是虚拟交换机 。
桥接模式,使用的技术是veth-pair
技术。
启动了一个容器过后又多了一个网卡。

再运行一个容器
bash
[root@CentOS7 ~]# docker run -d -P --name tomcat02 tomcat
d5f3197160516df059bcd2e2cb3bf079daded118b31c5c073968db05eafb5760

bash
docker exec -it tomcat02 /bin/bash
cd /etc
root@d9b71213acb7:/etc# cat os-release
PRETTY_NAME="Ubuntu 24.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.1 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo
apt update
apt install iproute2
bash
[root@CentOS7 ~]# docker exec -it tomcat02 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
容器 带来的网卡 ,都是一对对 的
veth-pair
就是一对的虚拟设备接口 ,成对出现的,一端连着协议 ,一端彼此相连。
veth-pair
充当一个桥梁,让Linux
可以和容器通信,连接各种虚拟网络设备。
veth-pair
就像是给容器 和宿主机 之间"牵了一根网线"。这根"网线 "有两个头,一个插在容器 的"网络插座 "(协议栈 )上,另一个插在宿主机 的"网络插座 "上。只要数据 从容器 这头塞进去,宿主机 那头就能直接收到;反过来宿主机 发数据,容器也能收到。
那么tomcat01
和tomcat02
是否能ping
通呢?
bash
docker exec -it tomcat02 /bin/bash
apt update
apt install iputils-ping

容器和容器之间是可以互相
ping
通的。
Docker
网络模型图

所有的容器不指定网络的情况下,都是docker0
路由的,docker
会给容器分配一个默认可用IP
Docker
中的所有的网络接口都是虚拟的,虚拟的转发效率高!
删除容器以后,网络就没了!
小结一下
veth-pair
技术:
每个Docker
容器启动时,会创建一对虚拟网卡(veth-pair
),其中一端在容器内命名为eth0
,另一端连接到宿主机的docker0
网桥(名称类似veth*
)。这对设备通过Linux
内核协议栈直接联通,实现容器与宿主机之间的数据传输
docker0
网桥的作用:
docker0
是Docker
默认创建的虚拟网桥,工作在二层(类似物理交换机),负责为容器分配IP(如172.17.0.0/16
子网)并管理容器间的通信。
容器间通信时,数据通过docker0
直接转发,无需经过宿主机物理网卡。
容器到宿主机的路径 :
容器内部流量通过eth0
→veth-pair
→docker0
网桥,再由宿主机内核的路由和NAT
规则处理:
NAT
转换:
当容器访问外网时,宿主机通过iptables
的MASQUERADE
规则将容器IP(如172.17.0.2
)转换为宿主机的物理网卡IP
(如192.168.1.100
)。
物理网卡转发 :
转换后的流量通过宿主机的物理网卡(如eth0
或ens33
)发送至外部网络 。
外网到容器的路径 :
若需从外网访问容器(如通过端口映射),Docker
会通过iptables
的DNAT
规则将宿主机物理网卡上的指定端口流量转发到容器IP和端口
自定义网络
bash
docker network --help
#查看所有的docker网络
docker network ls
网络模式
bridge
:桥接(默认)
none
:不配置网络
host
:主机模式(和宿主机共享网络)
container
:容器内网络连通!
测试
/16
子网:
网络前缀占 16
位,主机部分占 16
位,可容纳 65,534
台设备,适合大型网络(如企业内网)。
/24
子网:
网络前缀占 24
位,主机部分占 8
位,仅支持 254
台设备,适合小型网络(如家庭、小型办公室)。
bash
#清空容器
docker rm -f $(docker ps -aq)
#默认--net bridge 这就是docker01
docker run -d -P --name tomcat01 --net bridge tomcat
#docker0特点,默认,域名不能访问。
#创建自定义网络
#subnet 是子网 gateway 网关
docker network create --driver bridge --subnet 10.1.0.0/16 --gateway 10.1.0.1 mynet

bash
docker network inspect mynet

bash
docker run -d -P --name tomcat-net-01 --net mynet tomcat
docker run -d -P --name tomcat-net-02 --net mynet tomcat
docker network inspect mynet

自定义网络的好处:
bash
docker exec -it tomcat-net-01 /bin/bash
apt update
apt install iputils-ping
docker exec -it tomcat-net-02 /bin/bash
apt update
apt install iputils-ping
docker exec -it tomcat-net-01 ping 10.1.0.3
docker exec -it tomcat-net-01 ping tomcat-net-02

自定义网络docker都已经维护好了对应的关系。
单独启动的两个容器不在同一个网络命名空间,DNS
无法解析名称,启动时将他们加到同一个网络通过DNS
解析容器名就可以直接通信。
网络连通
bash
docker run -d -P --name tomcat-01 tomcat
docker run -d -P --name tomcat-02 tomcat
红色的是不可能直接能通信的
那么我们的目的就是为了将容器连接到网络上
bash
docker exec -it tomcat-01 /bin/bash
apt update
apt install iputils-ping
#容器连接网络
docker network connect mynet tomcat-01
docker network inspect mynet

一个容器两个
IP
地址,直接解决这个问题,比如阿里云服务器一个公网一个内网,都可以连接到服务器。

假设跨网络操作,就需要docker network connect
连通!
Redis
集群部署

创建网络
bash
docker network create redis --subnet 172.38.0.0/16
docker network ls
NETWORK ID NAME DRIVER SCOPE
a96bd4671a05 redis bridge local
docker network inspect redis
#循环创建六个节点
for port in $(seq 1 6); \
do \
mkdir -p ./mydata/redis/node-${port}/conf
touch ./mydata/redis/node-${port}/conf/redis.conf
#配置Redis配置文件
cat << EOF >./mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled 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
[root@CentOS8 ~]# cd ./mydata/redis/
[root@CentOS8 redis]# ll
total 0
drwxr-xr-x. 3 root root 18 Mar 4 16:15 node-1
drwxr-xr-x. 3 root root 18 Mar 4 16:15 node-2
drwxr-xr-x. 3 root root 18 Mar 4 16:15 node-3
drwxr-xr-x. 3 root root 18 Mar 4 16:15 node-4
drwxr-xr-x. 3 root root 18 Mar 4 16:15 node-5
drwxr-xr-x. 3 root root 18 Mar 4 16:15 node-6
启动Redis
容器
bash
# redis:5.0.9-alpine3.11 镜像名称
# redis-server /etc/redis/redis.conf 启动 Redis 服务并加载自定义配置的核心指令。
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /root/mydata/redis/node-1/data:/data \
-v /root/mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /root/mydata/redis/node-2/data:/data \
-v /root/mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /root/mydata/redis/node-3/data:/data \
-v /root/mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /root/mydata/redis/node-4/data:/data \
-v /root/mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /root/mydata/redis/node-5/data:/data \
-v /root/mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /root/mydata/redis/node-6/data:/data \
-v /root/mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

进入容器
bash
docker exec -it redis-1 /bin/sh
创建集群
bash
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

bash
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
成功!

总结
所有结论都需要反复测试!如果有错误欢迎指正!一起努力!
如果喜欢的话,请点个赞吧就算鼓励我一下。