一、Docker网络配置与容器通信
掌握Docker网络类型(桥接网络、host网络、none网络),自定义网络的优势,容器通信的核心原理
桥接网络
桥接网络在宿主机和容器之间形成一个虚拟桥接。该网络上的容器可以相互通信,但与未来使用该网络桥接的容器不能通信有隔离。每个容器都会获得一个独一无二的IP地址,通过与宿主机的桥接,不仅可以相互交互还可与本地网络(LAN)和Internet互联。然而,它们不会以物理设备的i形式出现在LAN上。这是默认的网络方式。
主机网络(HOST网络)
使用主机网络模式的容器使用与宿主机相同的网络设置,不会被隔离,它们没有单独的IP地址。相反,它们使用的任何端口都直接链接到主机网络。由于应用程序容器使用端口8080,因此不需要端口映射,因为在这种情况下,容器使用主机端口。这种模式下同一个端口只能同时被一个容器服务绑定。
none网络
该网络关闭了容器的网络功能,仅有独自的网络空间(一个空架子),并且该模式不会给容器分配任何网络资源,包括虚拟网卡、路由、防火墙、IP、网关、端口等。我们一般很少使用到这种模式。
容器网络(container网络)
容器网络和主机网络很类似,它是桥接和主机网络的合体,优先以桥接方式启动第一个容器,后面的所有容器启动时,均指定网络模式为container,它们均共享第一个容器的网络资源,除了网络资源,其他资源,容器彼此之间依然是相互隔离的。这种模式下,第一个容器服务挂掉,后面依赖它的容器都会暂停服务。
自定义网络
该模式更为灵活,可以通过-d指定自定义的网络模式的类型,可以是桥接或者overlay,其中overlay功能更为强大,可以指定多个subnet子网网段。该模式下在容器之间可以使用别名相互通信,这一点很方便。
核心原理
Docker为每个容器创建一个独立的网络空间,网络命名空间(Network Namespace),相当于每个容器有自己的IP地址,网卡,路由表,防火墙规则,但本质上不同容器之间默认是"网络隔离"的,就像不同的主机。
虚拟网卡对(veth pair)是成对出现的虚拟网卡,可以理解为"一根虚拟网线",一端在容器内,一端在宿主机,一端发送数据会在另一端接收到,它实现了容器↔宿主机的数据传输。
Docker默认会创建一个docker0网桥(Linux Bridge),它类似一个虚拟交换机,所有容器的veth另一端都会连接到这个网桥上。它让多个容器连接到同一个"局域网",容器之间可以通过IP直接通信。
Docker使用iptables+NAT(地址转换)来控制流量,当容器访问外网时使用NAT(SNAT)把容器IP转换为宿主机IP,当外部访问容器时使用端口映射(DNAT),访问宿主机会转发到容器相应的端口。
总的来说就是利用Linux网络命名空间隔离网络环境,通过veth pair连接容器与宿主机,再借助Linux Bridge实现容器互联,结合iptables完成流量转发与NAT。
默认网络操作:查看Docker默认网络,启动容器并查看其所属网络,验证默认网络下容器通过IP通信
默认网络通信(通过IP)
第一章中我们已经创建好了目录,接下来先执行
bash
cd ~/docker_experiment/lesson15
进入专属目录。

然后执行以下命令:
bash
docker network ls
docker run -d --name net1 nginx:latest
docker run -d --name net2 nginx:latest
NET1_IP=$(docker inspect net1 -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}')
docker exec net2 ping -c 2 $NET1_IP
其中ls列出Docker中所有的网络。默认会看到三个网络:bridge(默认桥接)、host(主机网络)、none(无网络),先初步了解当前Docker的网络环境。
接下来启动第一个nginx容器net1和第二个容器net2,未指定网络,默认来连接到bridge网络。
NET1_IP作为一个变量,存储使用docker inspect和Go模板语法提取容器net1在默认网络中的IP地址,用于后续通过IP访问测试。
exec在net2容器内通过ip地址ping容器net1,测试是否连通,该命令验证了在默认bridge网络中,容器可以通过IP地址相互通信(但无法通过容器名通信,因为默认网络不支持DNS自动解析容器名)。这一步会失败,因为nginx:latest镜像中没有ping命令,所以后续我使用debian:12作为客户端来测试通信。

我们可以看到除了ping以外其他均执行成功了,为了能够成功通信,我更改debian作为容器,之所以选择它是因为它可以安装iputils-ping包来使用ping命令,具体命令如下:
bash
docker run -d --name debian-client --network bridge debian:12 sleep infinity
docker exec debian-client apt-get update && docker exec debian-client apt-get install -y iputils-ping
docker exec debian-client ping -c 2 $NET1_IP
在后台启动一个Debian 12容器作为测试客户端,显示连接到bridge网络,并且通过sleep infinity让它一直运行。
然后通过apt-get更新并安装ping工具。
最后和之前一样ping容器net1,这次就成功了。


自定义桥接网络:创建自定义桥接网络(my-bridge),启动两个nginx容器加入该网络,验证容器通过容器名通信
自定义桥接网络(通过容器名通信)
bash
docker network create my-bridge
docker run -d --name app1 --network my-bridge nginx:latest
docker run -d --name app2 --network my-bridge nginx:latest
# 使用一个带 ping 的容器测试
docker run -d --name test --network my-bridge debian:12 sleep infinity
docker exec test apt-get update && docker exec test apt-get install -y iputils-ping
docker exec test ping -c 2 app1
通过docker network创建一个自定义的桥接网络,名为my-bridge。自定义网络与默认bridge网络的主要区别:自带内嵌DNS,容器之间可以通过容器名直接通信。
启动app1和app2两个容器,都连接到my-bridge网络。
使用debian 12启动容器test也连接到my-bridge网络,用于发送ping测试。
bash
docker exec test apt-get update && docker exec test apt-get install -y iputils-ping
docker exec test ping -c 2 app1
然后我们为test容器更新并安装ping
在test容器内,直接使用容器名app1进行ping,成功返回响应的话就能够验证在自定义桥接网络中,容器可以通过容器名进行通信,无需知道IP地址。这是因为自定义网络提供了自动DNS解析功能。


其他网络模式:练习host网络模式的容器启动,了解其特点;将容器加入多个网络,验证多网络通信效果
host网络模式
bash
docker run -d --name host-nginx --network host nginx:latest
curl http://localhost # 如果 80 端口未被占用,会显示 nginx 欢迎页
使用host网络模式启动nginx容器,该模式下,容器不会获得独立的网络命名空间,而是直接使用宿主机的网络栈。这样做容器内的端口会直接暴露在宿主机上,但网络性能良好(无需NAT转换),但是容器与宿主机之间没有网络隔离可能存在端口冲突。
curl访问宿主机的localhost80端口,由于容器使用了host网络,nginx直接在宿主机上监听80端口,因此可以访问到nginx的欢迎页,验证了host网络模式下,容器与宿主机共用网络。

容器加入多个网络
bash
docker network create netA
docker network create netB
docker run -d --name multi --network netA nginx:latest
docker network connect netB multi
# 启动两个测试容器分别连 netA 和 netB
docker run -d --name testA --network netA debian:12 sleep infinity
docker run -d --name testB --network netB debian:12 sleep infinity
# 安装 ping 并测试
docker exec testA apt-get update && docker exec testA apt-get install -y iputils-ping
docker exec testB apt-get update && docker exec testB apt-get install -y iputils-ping
docker exec testA ping multi
docker exec testB ping multi
首先创建两个自定义桥接网络netA和netB。
启动容器multi连接到netA网络。
connect netB multi将已运行的multi容器再连接到netB网络,一个容器可以同时属于多个网络。这样容器multi就同时拥有了两个网络中的IP地址,能够与两个网络中的其他容器通信。
通过debian启动testA和testB两个容器进行测试,一个连接netA,另一个连接netB。
为这两个测试容器更新并安装ping工具。
最后exec进行测试,成功的话就验证了一个容器可以同时加入多个网络,并能被每个网络中的其他容器通过容器名访问到。



清理网络
bash
docker stop net1 net2 app1 app2 host-nginx multi testA testB debian-client
docker rm net1 net2 app1 app2 host-nginx multi testA testB debian-client
docker network rm my-bridge netA netB

最后一个失败是因为还有其他容器在连接,删除自定义网络必修在没有容器连接时才会成功。
二、Docker Compose安装与基础编排
掌握Docker Compose的作用、核心优势,docker-compose.yml配置文件的结构与核心配置项。
作用
Docker Compose是一个用于定义和运行多容器Docker应用的工具。定义多容器应用(通过YAML文件),管理容器之间的关系(依赖、网络),一键启动/停止整个应用,统一管理环境配置。
核心优势
一键化部署,所有服务自动启动,不需要逐个docker run,不需要手动创建网络。声明式配置,所有配置写在docker-compose.yml中,配置即代码,具备可复现,可版本控制,易于迁移。自动网络管理,会自动创建网络,不用关心IP地址。服务依赖管理自动控制启动顺序。环境隔离,不同项目之间各自独立,网络隔离,容器隔离,端口管理。
结构与核心配置项
基本结构
html
version: "3.8"
services:
service1:
...
service2:
...
networks:
...
volumes:
...
services是核心配置项,定义所有容器服务。首先,image 和build用于指定镜像来源,其中 image表示直接使用已有镜像(如nginx),而build表示基于当前目录的 Dockerfile 构建镜像。container_name用于指定容器名称(可选)。ports用于端口映射(如"8080:80"),实现宿主机与容器之间的访问。volumes用于数据卷挂载(如./data:/var/lib/mysql),实现数据持久化。environment用于设置环境变量(如数据库密码),以配置容器运行参数。depends_on用于声明服务依赖关系,从而控制启动顺序,但不保证服务完全可用。networks用于指定容器所加入的网络,实现容器间通信。restart用于定义重启策略(如always),保证容器异常退出后自动重启。command用于覆盖容器默认启动命令。expose用于声明容器内部端口,仅供容器之间访问,不会暴露到宿主机。
Docker Compose安装:通过curl命令下载并安装Docker Compose,赋予执行权限,验证安装成功
安装Docker Compose
先执行
bash
cd ~/docker_experiment/lesson16
进入目录。

接着执行
bash
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose --version
curl从GitHub下载Docker Compose二进制文件到/usr/local/bin/docker-compose。-L跟随重定向(GitHub 会重定向到实际下载链接),(uname -s)-(uname -m)自动识别操作系统(Linux/Darwin)和架构(x86_64/aarch64),下载对应版本,-o指定输出文件路径。
chomd赋予该文件可执行权限,使其可以直接作为命令运行。
docker-compose验证安装是否成功,输出版本信息。

配置文件编写:编写docker-compose.yml文件,编排nginx+mysql容器,配置端口映射、数据卷、环境变量、容器依赖。
编写 docker-compose.yml
bash
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- web-data:/usr/share/nginx/html
depends_on:
- db
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: mydb
ports:
- "3306:3306"
volumes:
- db-data:/var/lib/mysql
volumes:
web-data:
db-data:
version: '3.8'指定 Compose 文件格式的版本。3.x 版本支持 swarm 模式,兼容性好。
services定义要编排的容器(称为"服务")。这里定义了两个服务:wb(nginx)和db(mysql)。
web服务配置depenfs_on: - db容器依赖,会先启动db再启动web。image: nginx:latest使用官方最新版 nginx 镜像。ports: - "8080:80"端口映射,宿主机 8080 → 容器内 80。volumes: - web-data:/usr/share/nginx/html使用命名卷web-data挂载到容器的 nginx 默认网页目录,实现数据持久化。
db服务配置image: mysql:5.7使用 MySQL 5.7 官方镜像。environment设置环境变量,MySQL 容器会读取这些变量进行初始化。MYSQL_ROOT_PASSWORD: root123设置 root 用户密码为root123。MYSQL_DATABASE: mydb启动时自动创建一个名为mydb的数据库。ports: -"3306:3306"将宿主机的 3306 端口映射到容器的 3306 端口(允许宿主机或其他主机连接 MySQL)。volumes: - db-data:/var/lib/mysql使用命名卷db-data挂载到 MySQL 数据目录,保证数据库文件持久化。
顶级volumes声明web-data和db-data定义两个命名卷,Docker Compose 会自动创建它们(前缀为项目名_卷名)。

容器编排启动:执行docker-compose up -d 命令启动容器,查看容器运行状态与自动创建的数据卷
启动编排
bash
docker-compose up -d
docker-compose ps
docker volume ls | grep lesson16
curl http://localhost:8080
up会根据docker-compose.yml启动所有服务,首次运行时会拉取镜像(如果本地没有),然后创建网络(默认会创建以lesson16_default命名的桥接网络),创建卷,启动容器。容器名称默认为项目名_服务名_序号,如lesson16_web_1和lesso16_db_1。
ps显示当前Compose项目中所有容器的状态(运行、退出、端口映射等)。
ls会列出所有Docker卷,grep会过滤出包含lesso16的卷。Compose会自动创建名为lesson16_web-data和lesson16_db-data的卷。验证了Compose自动管理命名卷,无需手动docker volume create。
curl访问nginx服务,返回默认页面表示成功。

