Docker进阶与容器编排实践-第二章

一、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服务,返回默认页面表示成功。

相关推荐
“码”力全开1 小时前
深入解构企业级 AI 视频管理平台:基于 Docker 的异构计算架构,支持 GB28181/RTSP 多协议接入与全面源码交付
人工智能·docker·音视频
爱喝水的鱼丶1 小时前
SAP-ABAP:SAP多表连接视图实战:内连接/外连接配置逻辑与性能优化技巧
运维·开发语言·学习·性能优化·sap·abap
cgsthtm1 小时前
Jenkins添加用户和角色并分配相应Job权限
运维·jenkins·jenkins用户·jenkins角色·jenkins权限·jenkins job
mnasd1 小时前
Gitlab + Jenkins 实现 CICD
运维·gitlab·jenkins
難釋懷1 小时前
Nginx测试工具charles
运维·nginx·php
云飞云共享云桌面1 小时前
东莞制造业研发降本方案:1 台云主机承载 10 人 SolidWorks,钣金操作秒响应
linux·运维·服务器·安全·电脑
Mark White1 小时前
一次 Ubuntu 内核升级翻车的运维记录:从 Kernel Panic 到锁定 6.14 内核
运维·ubuntu
修炼室2 小时前
告别天天变动的随机端口!基于 Tailscale 子网路由(Subnet Router)外网原生直连学院服务器及安装踩坑指南
运维·服务器
sbjdhjd2 小时前
企业级 Tomcat (上):WEB 技术栈 + 架构演进 + 生产级安装部署
linux·运维·云原生·开源·tomcat·云计算·负载均衡