【网络运维】Docker网络:基础与实战

Docker网络:基础与实战

Docker网络是容器化技术中至关重要的组成部分,它决定了容器之间以及容器与外部世界的通信方式。本章将系统性地介绍Docker原生网络类型、自定义网络的创建方法、容器间通信的三种方式,以及容器内外网络流量的处理机制。通过实际操作演示,帮助读者深入理解Docker网络的工作原理。


Docker原生网络类型

Docker安装时会自动创建三种默认网络,可通过docker network ls命令查看:

bash 复制代码
[root@docker ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
a1b809382f0d   bridge    bridge    local
6ad21ed9ea1f   host      host      local
4e31521b27c6   none      null      local

1. none网络

  • 驱动类型:null
  • 特点:容器只有lo回环接口,完全隔离,无法与外界通信
  • 适用场景:安全性要求高、无需联网的容器(如密码生成器)
  • 创建方式docker run -it --network=none busybox
bash 复制代码
[root@docker ~]# docker run -it --network=none busybox
/ #
/ # ifconfig
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ #
/ # hostname
4027da12afaf

2. host网络

  • 特点:容器共享宿主机网络命名空间,网络配置与宿主机完全相同
  • 优点:网络性能最佳,无需NAT转换
  • 缺点:存在端口冲突风险
  • 适用场景:对网络性能要求高的应用;需要直接配置宿主机网络的场景
bash 复制代码
[root@docker ~]# docker run -it --network=host busybox      #容器网络与宿主机相同
/ #
/ # ip l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
    link/ether 00:0c:29:33:15:f6 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue
    link/ether 02:42:02:fd:82:b3 brd ff:ff:ff:ff:ff:ff
/ #
/ # hostname                               #容器主机与宿主机相同
docker
/ #

Bridge网络详解

1. 默认bridge网络

Docker安装时创建名为docker0的Linux网桥,未指定网络的容器默认连接到此网桥。

网络拓扑结构

复制代码
容器eth0 <--veth pair--> docker0网桥 <--> 宿主机网络


验证实验

bash 复制代码
# 安装桥接工具
[root@docker ~]# yum install -y bridge-utils

# 查看初始网桥状态
[root@docker ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.02420be905a5       no

# 创建容器后再次查看
[root@docker ~]# docker run -itd --name busybox1 busybox
[root@docker ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.02420be905a5       no              vethddb2744

2. veth pair原理

veth pair是一对虚拟网卡,像被虚拟网线连接:

  • 一端在容器内(如eth0@if25
  • 另一端在宿主机并连接到网桥(如vethddb2744
bash 复制代码
# 容器内查看网卡
24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0

# 宿主机查看对应网卡
25: vethddb2744@if24: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP

3. 网络配置信息

bash 复制代码
[root@docker ~]# docker network inspect bridge
[
    {
        "Name": "bridge",
        "IPAM": {
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        }
    }
]

# 验证网关
[root@docker ~]# ip a | grep docker0
3: docker0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state UP
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0

自定义容器网络

1. 创建自定义bridge网络

bash 复制代码
# 创建默认配置的网络
[root@docker ~]# docker network create --driver bridge my_net

# 创建指定子网和网关的网络
[root@docker ~]# docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my_net2

2. 查看网络结构

bash 复制代码
[root@docker ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
br-89f7bc11b602         8000.0242194d039e       no      # my_net
br-ec761bc51778         8000.02427fa54b88       no      # my_net2
docker0         8000.02420be905a5       no              vethddb2744

3. 指定静态IP

注意 :只有使用--subnet创建的网络才能指定静态IP

bash 复制代码
[root@docker ~]# docker run -it --network=my_net2 --ip 172.22.16.8 --name busybox3 busybox

# 验证IP配置
30: eth0@if31: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:16:10:08 brd ff:ff:ff:ff:ff:ff
    inet 172.22.16.8/24 brd 172.22.16.255 scope global eth0

容器间连通性分析

1. 同一网络内的通信

bash 复制代码
# busybox2 ping busybox3(同属my_net2)
[root@docker ~]# docker exec -it busybox2 sh
/ # ping -c 3 172.22.16.8
PING 172.22.16.8 (172.22.16.8): 56 data bytes
64 bytes from 172.22.16.8: seq=0 ttl=64 time=0.197 ms

2. 不同网络间的隔离

默认情况下,不同bridge网络的容器无法通信:

bash 复制代码
# busybox2(my_net2)ping busybox1(docker0)
[root@docker ~]# docker exec -it busybox2 sh
/ # ping -c 3 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
--- 172.17.0.2 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss

隔离原因:iptables规则DROP不同网桥间的流量

bash 复制代码
-A DOCKER-ISOLATION-STAGE-2 -o br-ec761bc51778 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP

3. 跨网络通信解决方案

为容器添加多块网卡实现跨网络通信:

bash 复制代码
# 为busybox1添加my_net2网卡
[root@docker ~]# docker network connect my_net2 busybox1

# 验证新增网卡
32: eth1@if33: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:16:10:03 brd ff:ff:ff:ff:ff:ff
    inet 172.22.16.3/24 brd 172.22.16.255 scope global eth1

# 现在可以跨网络通信
/ # ping -c 3 172.22.16.3
64 bytes from 172.22.16.3: seq=0 ttl=64 time=0.199 ms

容器通信的三种方式

1. IP通信

要求容器有属于同一网络的网卡,可通过--networkdocker network connect实现。

2. Docker DNS Server

  • Docker 1.10+版本内置DNS服务器
  • 通过容器名直接通信
  • 限制:仅限user-defined网络
bash 复制代码
# 使用容器名通信
[root@docker ~]# docker exec -it bbox2 sh
/ # ping -c 3 bbox1
PING bbox1 (172.22.16.2): 56 data bytes
64 bytes from 172.22.16.2: seq=0 ttl=64 time=0.177 ms

# 默认bridge网络不支持DNS
/ # ping -c 3 bbox3
ping: bad address 'bbox3'

3. Joined容器

共享网络栈,通过127.0.0.1通信

bash 复制代码
# 创建joined容器
[root@docker ~]# docker run -it --network container:web1 busybox

# 验证网络配置(与web1完全相同)
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0

# 通过localhost访问服务
/ # wget 127.0.0.1
Connecting to 127.0.0.1 (127.0.0.1:80)

适用场景

  • Web服务器与应用服务器间的本地通信
  • 网络监控容器监控其他容器的流量

容器与外部世界通信

1. 容器访问外部世界

默认通过NAT实现:

bash 复制代码
# docker host测试外网访问
[root@docker ~]# ping -c 3 www.baidu.com
PING www.baidu.com (223.109.82.6) 56(84) bytes of data.
64 bytes from 223.109.82.6 (223.109.82.6): icmp_seq=1 ttl=128 time=67.8 ms
64 bytes from 223.109.82.6 (223.109.82.6): icmp_seq=2 ttl=128 time=13.0 ms
64 bytes from 223.109.82.6 (223.109.82.6): icmp_seq=3 ttl=128 time=12.5 ms

--- www.baidu.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 12.454/31.074/67.754/25.937 ms

# 容器内测试外网访问
[root@docker ~]# docker run -it --name test1 busybox
/ # ping -c 3 www.baidu.com
PING www.baidu.com (223.109.82.6): 56 data bytes
64 bytes from 223.109.82.6: seq=0 ttl=127 time=21.240 ms

NAT转换过程

bash 复制代码
# 查看NAT规则
[root@docker ~]# iptables -t nat -S
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

# tcpdump验证地址转换
# docker0接口:源地址为容器IP
15:23:42.854951 IP 172.17.0.2 > 223.109.82.41: ICMP echo request

# ens160接口:源地址变为宿主机IP
15:25:41.886472 IP 192.168.108.30 > 223.109.82.41: ICMP echo request

数据流路径

  1. 容器发送:172.17.0.2 → www.baidu.com
  2. docker0接收并交给NAT处理
  3. NAT转换:192.168.108.30 → www.baidu.com
  4. 通过宿主机网卡发送到外网

2. 外部世界访问容器

通过端口映射实现:

bash 复制代码
# 动态端口映射
[root@docker ~]# docker run -d -p 80 httpd
[root@docker ~]# docker ps
PORTS
0.0.0.0:32768->80/tcp

# 指定端口映射
[root@docker ~]# docker run -d -p 8080:80 httpd
[root@docker ~]# curl 192.168.108.30:8080
<html><body><h1>It works!</h1></body></html>

实现机制:docker-proxy进程监听宿主端口并转发到容器

bash 复制代码
# 查看docker-proxy进程
[root@docker ~]# ps aux | grep docker-proxy
root     12345  0.0  0.1 123456  7890 ?        Sl   10:00   0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8080 -container-ip 172.17.0.3 -container-port 80

实战:Tomcat容器部署

1. 拉取并运行Tomcat

bash 复制代码
# 搜索Tomcat镜像
[root@docker ~]# docker search tomcat

# 拉取镜像
[root@docker ~]# docker pull tomcat

# 运行容器
[root@docker ~]# docker run -itd -p 8080:8080 tomcat
92d78922526ba2a54ef63c48d2fec80b10997027de93457a4e2d56d7ea7448e2

访问tomcat首页

首页报错,应用目录出现问题。

2. 解决Web应用目录问题

bash 复制代码
# 进入容器
[root@docker ~]# docker exec -it 92d bash

# 查看目录结构(webapps为空)
root@92d78922526b:/usr/local/tomcat# ls webapps

# 修复:用webapps.dist替换webapps
root@92d78922526b:/usr/local/tomcat# rm -r webapps
root@92d78922526b:/usr/local/tomcat# mv webapps.dist webapps

3. 访问验证

通过http://宿主机IP:8080访问Tomcat管理界面

总结

本文系统探讨了Docker网络的核心概念:

  1. 网络类型:none、host、bridge三种原生网络各有适用场景
  2. 网络创建:支持自定义bridge网络,可指定子网、网关和静态IP
  3. 容器通信:IP、DNS、joined容器三种方式满足不同需求
  4. 内外互通:通过NAT实现容器访问外网,通过端口映射实现外部访问容器
  5. 实战应用:Tomcat部署展示了网络配置的实际应用

理解Docker网络机制对于构建稳定、高效的容器化应用至关重要。在实际应用中,应根据具体需求选择合适的网络模型,平衡性能、安全性和灵活性。

相关推荐
加藤不太惠2 小时前
docker简单了解使用
运维·docker·容器
Lisonseekpan2 小时前
RBAC 基于角色的访问控制模型详解与实践指南
java·服务器·网络·后端·spring·log4j
嵌入式学习和实践2 小时前
Linux/Windows 系统架构查看、安装包选择指南(嵌入式开发场景适配)
linux·windows·系统架构
小安运维日记2 小时前
RHCA - DO374 | Day09:自定义内容集和执行环境
linux·运维·服务器·系统架构·ansible·改行学it
开发者导航2 小时前
【开发者导航】完全开源免费且可自托管的私有云盘
网络·开源
<e^πi+1=0>2 小时前
Docker部署Lighthouse CI Server总结
ci/cd·docker·容器
网安INF2 小时前
典型网络攻击分析:ARP欺骗与TCP劫持
网络·网络协议·tcp/ip·安全·网络安全
VekiSon2 小时前
Linux网络编程——网络数据封装与 HTTP 协议
网络·网络协议·http
TAEHENGV2 小时前
提醒历史模块 Cordova 与 OpenHarmony 混合开发实战
运维·服务器