docker 网络模式和案例分享

近期文章:

Docker 提供了多种网络模式和功能,以便在容器间建立网络通信和连接外部网络

1. 默认网络模式(bridge):Docker 默认使用 bridge 网络模式,创建一个名为 docker0 的虚拟网桥,并为每个容器分配一个 IP 地址。容器间可以通过 IP 地址相互通信

2. 主机模式(host): 使用主机模式时,容器直接使用宿主机的网络,与宿主机共享网络接口。容器的网络配置与宿主机相同,可以通过宿主机的 IP 地址直接访问容器。

3. 容器间通信: Docker 提供了容器间通信的功能,可以通过容器名称或 IP 地址进行通信。例如,可以使用容器名称作为主机名,在容器间建立连接。

4. 端口映射(Port Mapping): Docker 允许将容器内的端口映射到宿主机的端口上,以便容器服务可以通过宿主机 IP 和端口访问。可以使用 -p--publish 参数来指定映射规则。

5. 自定义网络(Custom Networks): Docker 允许创建自定义网络,以便在一个自定义的网络中连接多个容器。自定义网络可以提供更好的隔离和网络管理。可以使用 docker network create 命令创建自定义网络。

6. DNS 解析: Docker 提供了内置的 DNS 服务,容器可以使用容器名称作为主机名进行 DNS 解析。容器可以通过主机名访问其他容器或外部服务

docker 容器的网络基础

docker run创建Docker容器时,可以用–net选项指定容器的网络模式,Docker有以下4种网络模式:

  • bridge模式:使–net =bridge指定,默认设置;
  • host模式:使–net =host指定;
  • none模式:使–net =none指定;
  • container模式:使用–net =container:NAME orID指定。

docker0:

安装docker的时候,会生成一个docker0的虚拟网桥

Linux虚拟网桥的特点:

可以设置ip地址 相当于拥有一个隐藏的虚拟网卡

docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500         inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255         inet6 fe80::42:caff:fe61:36cd  prefixlen 64  scopeid 0x20<link>         ether 02:42:ca:61:36:cd  txqueuelen 0  (Ethernet)         RX packets 0  bytes 0 (0.0 B)         RX errors 0  dropped 0  overruns 0  frame 0         TX packets 8  bytes 656 (656.0 B)         TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

每运行一个docker容器都会生成一个veth设备对,这个veth一个接口在容器里,一个接口在物理机上。

安装网桥管理工具

[root@master ~]# yum install bridge-utils -y

brctl show

可以查看到有一个docker0的网桥设备,下面有很多接口,每个接口都表示一个启动的docker容器,因为我在docker上启动了很多容器,所以interfaces较多

[root@master ~]# brctl show bridge name	bridge id		STP enabled	interfaces cni0		8000.da48c56634e7	no		veth3dde7ccb docker0		8000.0242ca6136cd	no		vetheb9993d

可以给容器起一个代号,这样可以直接以代号访问,避免了容器重启ip变化带来的问题 –link docker run –link=[CONTAINER_NAME]:[ALIAS]

1.启动一个nginx1容器 [root@master data]# docker run --name nginx1 -itd nginx:v1 /bin/bash 255fdeaba30fc46f99b9ca424fb53aceeaced2e494dfd253f221eb9f3a77de05 2.启动一个nginx2容器,--link做链接,那么当我们重新启动nginx2容器时,就算ip变了,也没关系,我们可以在nginx2上ping别名webtest [root@master data]# docker run --name nginx2 -itd --link=nginx1:webtest nginx:v1 /bin/bash 28c45e8729c3bac92d46670e6d6e0647d728713acb2b34d037367a520927526f 3.进入容器 [root@master data]# docker exec -it nginx2 /bin/bash ping nginx1容器的ip别名webtest可以ping通,即使nginx1容器的ip变了也可以通

docker容器的网络模式

docker run创建docker容器时,可以用–net选项指定容器的网络模式,Docker有以下4种网络模式:

  • bridge模式:使–net =bridge指定,默认设置;
  • host模式:使–net =host指定
  • none模式:使–net =none指定;
  • container模式:使用–net =container:NAME orID指定

docker bridge模式

默认选择bridge的情况下,容器启动后会通过DHCP获取一个地址

创建桥接网络

[root@master ~]# docker run --name bridge -it  --privileged=true centos  bash [root@5f384284ef6e /]# ip addr 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 52: eth0@if53: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default     link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff link-netnsid 0     inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0        valid_lft forever preferred_lft forever

案例 1: Web 应用容器

首先,创建一个 Dockerfile,用于构建包含你的 Web 应用的镜像。

FROM nginx:latest COPY ./webapp /usr/share/nginx/html EXPOSE 80

上述 Dockerfile 使用 nginx 镜像作为基础镜像,将 Web 应用文件复制到容器中,并暴露容器的 80 端口

构建镜像并命名为 mywebapp

docker build -t mywebapp .

运行容器,并将容器的 80 端口映射到宿主机的 8080 端口

docker run -d --name mywebapp -p 8080:80 mywebapp

现在可以通过访问 http://宿主机IP:8080 来访问Web 应用

案例 2: 多个容器通信

一个应用,由多个容器组成,需要进行容器间的通信

创建一个自定义网络,用于容器间的通信

docker network create mynetwork

启动 Web 服务器容器,并连接到自定义网络

docker run -d --name webserver --network=mynetwork mywebserver #mywebserver 是包含 Web 服务器的镜像

启动数据库容器,并连接到同一自定义网络

docker run -d --name database --network=mynetwork mydatabase #mydatabase 是包含数据库服务的镜像

现在,Web 服务器容器和数据库容器都连接到同一个自定义网络 mynetwork,它们可以使用容器名称进行通信。例如,在 Web 服务器容器中,可以使用数据库容器的名称 database 来连接数据库

docker host网络模式

Host 网络模式是 Docker 中的一种网络模式,它与默认的 bridge 模式不同。在 Host 网络模式下,容器与宿主机共享网络命名空间,直接使用宿主机的网络接口进行通信,而不是创建一个单独的网络栈

  1. 网络共享: 容器直接使用宿主机的网络接口,与宿主机共享相同的 IP 地址和网络配置。这使得容器可以直接访问宿主机所连接的网络,并且无需进行端口映射。
  2. 网络性能: 由于容器与宿主机共享网络栈,容器中的网络性能通常更高。容器与宿主机之间的通信不需要经过网络桥接层,减少了网络转发的开销
  3. 要使用 Host 网络模式启动容器,可以在 docker run 命令中使用 --net=host 参数
[root@master data]# docker run --name host -it --net=host --privileged=true centos  bash [root@master /]# ip addr 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 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000     link/ether 00:0c:29:65:10:9b brd ff:ff:ff:ff:ff:ff     inet 172.16.40.129/24 brd 172.16.40.255 scope global noprefixroute ens33        valid_lft forever preferred_lft forever     inet6 fe80::df71:a790:6b25:5518/64 scope link noprefixroute        valid_lft forever preferred_lft forever 3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default     link/ether 02:42:ca:61:36:cd brd ff:ff:ff:ff:ff:ff     inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0        valid_lft forever preferred_lft forever     inet6 fe80::42:caff:fe61:36cd/64 scope link        valid_lft forever preferred_lft forever 4: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default     link/ether 32:c1:bc:d7:fe:b5 brd ff:ff:ff:ff:ff:ff     inet 10.244.0.0/32 scope global flannel.1     ......

需要注意以下几点:

  • 在 Host 网络模式下,容器将无法使用宿主机上已占用的端口。因此,在启动容器之前,请确保宿主机上的相应端口未被其他服务占用。
  • Host 网络模式会使容器与宿主机紧密耦合,容器将直接使用宿主机的网络资源。因此,需要谨慎使用 Host 网络模式,以确保安全性和隔离性。
  • 使用 Host 网络模式时,容器的网络配置(例如 IP 地址、子网掩码、网关等)将与宿主机完全相同,无需进行额外的网络配置。

Host 网络模式适用于一些特定的场景,如需要容器直接与宿主机网络进行交互、需要最大限度提高网络性能的情况等。

案例1:容器化的网络监控工具

我现在需要在容器中运行一个网络监控工具,用于监视宿主机的网络连接和流量。使用 Host 网络模式可以让容器直接访问宿主机的网络接口,以实时监控网络流量和连接状态

创建一个 Dockerfile,用于构建包含网络监控工具的镜像。例如,使用 tcpdump 工具进行网络抓包。

FROM ubuntu:latest RUN apt-get update && apt-get install -y tcpdump

构建镜像并命名为 network-monitor

docker build -t network-monitor .

运行容器,并使用 Host 网络模式。

docker run -d --net=host --name network-monitor network-monitor tcpdump -i eth0

现在,网络监控容器将以 Host 网络模式运行,直接访问宿主机的网络接口 eth0。可以在容器中使用 tcpdump 工具来捕获和分析宿主机上的网络流量

docker container模式

Docker网络container模式是指,创建新容器的时候,通过–net container参数,指定其和已经存在的某个容器共享一个 Network Namespace。使它们可以直接使用 localhost 来进行通信,就像在同一台主机上运行的进程一样。容器模式可以在容器之间提供高性能的通信,并且不需要进行端口映射或使用网络地址转换(NAT),如下图所示,右方黄色新创建的container,其网卡共享左边容器。因此就不会拥有自己独立的 IP,而是共享左边容器的 IP 172.17.0.2,端口范围等网络资源,两个容器的进程通过 lo 网卡设备通信

[root@master data]# docker run --name container2 --net=container  -it --privileged=true centos [root@f483c8e3f46c /]# ip addr 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

docker none模式

Docker网络none模式是指创建的容器没有网络地址,只有lo网卡,在无网络模式下,容器没有网络接口,无法与外部网络通信。该模式主要用于一些特殊场景,如只需要运行一个进程的容器或与网络无关的容器。

[root@master data]# docker run -itd  --name none --net=none --privileged=true centos f483c8e3f46c65be442989ab0828ccc6f424f53a71809e49a2fdf2f692b11ff7 [root@master data]# docker exec -it none /bin/bash [root@f483c8e3f46c /]# ip addr #只有本地lo地址 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