浅谈docker的四种网络模式与数据管理

Posted 28线不知名云架构师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈docker的四种网络模式与数据管理相关的知识,希望对你有一定的参考价值。

前言:当项目大规模使用 Docker 时,容器通信的问题也就产生了。要解决容器通信问题,必须先了解很多关于网络的知识。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker 同样有着很多不完善的地方,网络方面就是 Docker 比较薄弱的部分。因此,我们有必要深入了解 Docker 的网络知识,以满足更高的网络需求。

一、网络模式

安装 Docker 以后,会默认创建三种网络,可以通过 docker network ls 查看。

在学习 Docker 网络之前,我们有必要先来了解一下这几种网络模式都是什么意思

网络模式简介
bridge为每一个容器分配、设置 IP 等,并将容器连接到一个 docker0 虚拟网桥,默认为该模式。
host容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。
none容器有独立的 Network namespace,但并没有对其进行任何网络设置,如分配 veth pair 和网桥连接,IP 等
container新创建的容器不会创建自己的网卡和配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等

1.1、bridge网络模式

在该模式中,Docker 守护进程创建了一个虚拟以太网桥 docker0,新建的容器会自动桥接到这个接口,附加在其上的任何网卡之间都能自动转发数据包。

  默认情况下,守护进程会创建一对对等虚拟设备接口 veth pair,将其中一个接口设置为容器的 eth0 接口(容器的网卡),另一个接口放置在宿主机的命名空间中,以类似 vethxxx 这样的名字命名,从而将宿主机上的所有容器都连接到这个内部网络上。

  比如我运行一个基于 busybox 镜像构建的容器 bbox01,查看 ip addr

busybox 被称为嵌入式 Linux 的瑞士军刀,整合了很多小的 unix 下的通用功能到一个小的可执行文件中。

 然后宿主机通过 ip addr 查看信息如下:

通过以上的比较可以发现,证实了之前所说的:守护进程会创建一对对等虚拟设备接口 veth pair,将其中一个接口设置为容器的 eth0 接口(容器的网卡),另一个接口放置在宿主机的命名空间中,以类似 vethxxx 这样的名字命名。

  同时,守护进程还会从网桥 docker0 的私有地址空间中分配一个 IP 地址和子网给该容器,并设置 docker0 的 IP 地址为容器的默认网关。也可以安装 yum install -y bridge-utils 以后,通过 brctl show 命令查看网桥信息

 对于每个容器的 IP 地址和 Gateway 信息,我们可以通过 docker inspect 容器名称|ID 进行查看,在 NetworkSettings 节点中可以看到详细信息。

我们可以通过 docker network inspect bridge 查看所有 bridge 网络模式下的容器,在 Containers 节点中可以看到容器名称。

 

关于 bridge 网络模式的使用,只需要在创建容器时通过参数 --net bridge 或者 --network bridge 指定即可,当然这也是创建容器默认使用的网络模式,也就是说这个参数是可以省略的。

Bridge 桥接模式的实现步骤主要如下:

  • Docker Daemon 利用 veth pair 技术,在宿主机上创建一对对等虚拟网络接口设备,假设为 veth0 和 veth1。而
    veth pair 技术的特性可以保证无论哪一个 veth 接收到网络报文,都会将报文传输给另一方。
  • Docker Daemon 将 veth0 附加到 Docker Daemon 创建的 docker0 网桥上。保证宿主机的网络报文可以发往 veth0;
  • Docker Daemon 将 veth1 添加到 Docker Container 所属的 namespace 下,并被改名为 eth0。如此一来,宿主机的网络报文若发往 veth0,则立即会被 Container 的 eth0 接收,实现宿主机到 Docker Container 网络的联通性;同时,也保证 Docker Container 单独使用 eth0,实现容器网络环境的隔离性。

1.2、host网络模式

  • host 网络模式需要在创建容器时通过参数 --net host 或者 --network host 指定;
  • 采用 host 网络模式的 Docker Container,可以直接使用宿主机的 IP 地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公有 IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换;
  • host 网络模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。

比如我基于 host 网络模式创建了一个基于 busybox 镜像构建的容器 bbox02,查看 ip addr

 

 然后宿主机通过 ip addr 查看信息如下:

对,你没有看错,返回信息一模一样,我也可以肯定我没有截错图,不信接着往下看。我们可以通过 docker network inspect host 查看所有 host 网络模式下的容器,在 Containers 节点中可以看到容器名称

 

1.3、none网络模式

  • none 网络模式是指禁用网络功能,只有 lo 接口 local 的简写,代表 127.0.0.1,即 localhost 本地环回接口。在创建容器时通过参数 --net none 或者 --network none 指定;
  • none 网络模式即不为 Docker Container 创建任何的网络环境,容器内部就只能使用 loopback 网络设备,不会再有其他的网络资源。可以说 none 模式为 Docke Container 做了极少的网络设定,但是俗话说得好“少即是多”,在没有网络配置的情况下,作为 Docker 开发者,才能在这基础做其他无限多可能的网络定制开发。这也恰巧体现了 Docker 设计理念的开放。

比如我基于 none 网络模式创建了一个基于 busybox 镜像构建的容器 bbox03,查看 ip addr

我们可以通过 docker network inspect none 查看所有 none 网络模式下的容器,在 Containers 节点中可以看到容器名称。

 

1.4、container网络模式

  • Container 网络模式是 Docker 中一种较为特别的网络的模式。在创建容器时通过参数 --net container:已运行的容器名称|ID 或者 --network container:已运行的容器名称|ID 指定;
  • 处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用 localhost 高效快速通信。

Container 网络模式即新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样两个容器除了网络方面相同之外,其他的如文件系统、进程列表等还是隔离的。

  比如我基于容器 bbox01 创建了 container 网络模式的容器 bbox04,查看 ip addr

  容器 bbox01 的 ip addr 信息如下:

 宿主机的 ip addr 信息如下:

 

通过以上测试可以发现,Docker 守护进程只创建了一对对等虚拟设备接口用于连接 bbox01 容器和宿主机,而 bbox04 容器则直接使用了 bbox01 容器的网卡信息。

  这个时候如果将 bbox01 容器停止,会发现 bbox04 容器就只剩下 lo 接口了。

 然后 bbox01 容器重启以后,bbox04 容器也重启一下,就又可以获取到网卡信息了。

 二、自定义网络

#查看网络列表
docker network ls

#查看容器ip
docker run -itd nginx:latest /bin/bash #运行容器
ce0eb6f2ce5c237e2d75d22c2841ff86763d9294be97c8f6bdc9e6311cce8234
docker ps -a #查看容器列表
docker inspect ce0eb6f2ce5c #查看容器信息,在此可以看到容器的ip

 

 2.1、指定分配容器地址

[root@192 ~]# docker run -itd --name nginx-1 --network bridge --ip 172.17.0.10 nginx:latest /bin/bash
docker: Error response from daemon: Conflict. The container name "/nginx-1" is already in use by container "4e9aaf7ca4be7d288b82b0969e8709c9456fbffa80f04cb48bab8a1d16833d03". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.
#开启容器报错
[root@192 ~]# docker ps -a
CONTAINER ID   IMAGE                                                    COMMAND                  CREATED             STATUS                           PORTS                                   NAMES
4e9aaf7ca4be   nginx:latest                                             "/docker-entrypoint.…"   3 minutes ago       Created                                                                  nginx-1
ce0eb6f2ce5c   nginx:latest                                             "/docker-entrypoint.…"   13 minutes ago      Up 13 minutes                    80/tcp                                  elastic_wing
0ee4e0bf35e0   centos                                                   "/sbin/init"             About an hour ago   Up About an hour                                                         test3
bd61aee15323   centos:7                                                 "/usr/bin/bash -c 'w…"   About an hour ago   Up About an hour                                                         elegant_tharp
f3470979d06c   centos:7                                                 "/usr/bin/bash -c ls…"   About an hour ago   Exited (0) About an hour ago                                             charming_mclean
b7ebbe9f86ed   nginx:latest                                             "/docker-entrypoint.…"   About an hour ago   Exited (137) About an hour ago                                           practical_euclid
0e1a125a745f   hello-world                                              "/hello"                 2 hours ago         Exited (0) 2 hours ago                                                   nervous_dijkstra
f55edaa9324d   goharbor/nginx-photon:v1.9.3                             "nginx -g 'daemon of…"   3 days ago          Up 3 days (healthy)              0.0.0.0:80->8080/tcp, :::80->8080/tcp   nginx
b8cf7697435c   goharbor/harbor-jobservice:v1.9.3                        "/harbor/harbor_jobs…"   3 days ago          Up 3 days (healthy)                                                      harbor-jobservice
5bc124360b25   goharbor/harbor-core:v1.9.3                              "/harbor/harbor_core"    3 days ago          Up 3 days (healthy)                                                      harbor-core
d1b0830d24a5   goharbor/harbor-registryctl:v1.9.3                       "/harbor/start.sh"       3 days ago          Up 3 days (healthy)                                                      registryctl
42ff18163705   goharbor/registry-photon:v2.7.1-patch-2819-2553-v1.9.3   "/entrypoint.sh /etc…"   3 days ago          Up 3 days (healthy)              5000/tcp                                registry
e1df062fce2d   goharbor/harbor-db:v1.9.3                                "/docker-entrypoint.…"   3 days ago          Up 3 days (healthy)              5432/tcp                                harbor-db
1ce0178ad138   goharbor/harbor-portal:v1.9.3                            "nginx -g 'daemon of…"   3 days ago          Up 3 days (healthy)              8080/tcp                                harbor-portal
1709cce283ba   goharbor/redis-photon:v1.9.3                             "redis-server /etc/r…"   3 days ago          Up 3 days (healthy)              6379/tcp                                redis
2bd4cbb41d85   goharbor/harbor-log:v1.9.3                               "/bin/sh -c /usr/loc…"   3 days ago          Up 3 days (healthy)              127.0.0.1:1514->10514/tcp               harbor-log
[root@192 ~]#

 2.2、可以通过自定义网络固定ip

[root@192 ~]# docker network create --subnet=172.18.0.0/16 mynetwork  #指定创建一个子网段,使用默认网桥模式
636284b70d9421fb80610c2e92912232e81033b916d1addd776bb832a0434bec

#指定ip
[root@192 ~]# docker run -itd --name nginx-2 --net mynetwork --ip 172.18.0.10 nginx:latest /bin/bash
0c2cfba24948cb948f6b7d1182459261405a311b68114bbbd6c6c62dda5c1222
[root@192 ~]#

 ps:指定容器前,先自定义网络

[root@192 ~]# docker inspect nginx-2

 2.3、暴露端口

[root@192 ~]# docker run -itd -p 555:80 nginx /bin/bash
a403fae4f065f7e8624e6bb4f256b5b098603c0a44a367bf0742e568fdefb6a5

[root@192 ~]# docker exec a403fae4f065 nginx
2021/09/04 18:26:52 [notice] 8#8: using the "epoll" event method
2021/09/04 18:26:52 [notice] 8#8: nginx/1.21.1
2021/09/04 18:26:52 [notice] 8#8: built by gcc 8.3.0 (Debian 8.3.0-6)
2021/09/04 18:26:52 [notice] 8#8: OS: Linux 3.10.0-957.el7.x86_64
2021/09/04 18:26:52 [notice] 8#8: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2021/09/04 18:26:52 [notice] 15#15: start worker processes
2021/09/04 18:26:52 [notice] 15#15: start worker process 16
2021/09/04 18:26:52 [notice] 15#15: start worker process 17
2021/09/04 18:26:52 [notice] 15#15: start worker process 18
2021/09/04 18:26:52 [notice] 15#15: start worker process 19
[root@192 ~]#

[root@192 ~]# docker run -itd -P nginx /bin/bash
a06cc91e8648dba234f8ecb3a089523ff43e4b764bc636ddad12659bf006c708
[root@192 ~]#

 

2.4、 在容器中执行命令

[root@192 ~]# docker create -it centos:7 /bin/bash
[root@192 ~]# docker start f8980b1f0154
f8980b1f0154
[root@192 ~]# docker exec -it f8980b1f0154 /bin/bash
#发现无法执行命令
[root@192 ~]# docker run -itd --name centos-systemd --privileged=true centos:7 /sbin/init #指定特权容器
[root@192 ~]# docker exec -it ff3f87d9d6b6 /bin/bash
[root@ff3f87d9d6b6 /]# yum install -y httpd
[root@ff3f87d9d6b6 /]# systemctl status httpd  
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:httpd(8)
           man:apachectl(8)

三、Docker数据卷

3.1、数据卷

  • 数据卷是一个供容器使用的特殊目录,位于容器中。可将宿主机的目录挂载到数据卷上,对数据卷的修改操作立刻可见,并且更新数据不会影响镜像,从而实现数据在宿主机与容器之间的迁移。数据卷的使用类似于Linux下对目录进行的mount操作。
创建数据卷
docker run -d -v /data1 -v /data2 --name web httpd:centos
挂载主机目录作为数据卷
docker run -d -v /var/www:/data1 --name web-1 httpd:centos

实例:

docker pull centos
docker run -v /var/www:/data1 -v /var/html:/data2 -it --name centos-v4 centos:7 /bin/bash	##宿主机目录/var/www挂载容器中的/data1,/var/html挂载容器中的/data2
cd /data1
touch 1.txt
cd /data2
touch 2.txt
ls /var/www/		##返回宿主机进行查看

 3.2、数据卷容器

  • 如果需要在容器之间共享一些数据,最简单的方法就是使用数据卷容器。数据卷容器是一个普通的容器,专门提供数据卷给其他容器挂载使用。
①:数据卷容器
docker run --name web11 -v /data1 -v /data2 -it centos /bin/bash 	##创建data1卷、data2卷
②:新容器挂载数据卷容器web100
docker run -it --volumes-from web11 --name qq centos /bin/bash	 ##允许一个容器,指定卷来源于web11,新的容器名字qq

3.3、容器互联(使用centos镜像) 

docker run -itd -P --name webb centos /bin/bash 		##创建并运行容器取名web1,端口号自动映射
docker run -itd -P --name web2 --link webb:webb centos /bin/bash	##创建并运行容器取名web2,链接到web1和其通信
	--link:打通隧道
yum -y install net-tools	##各自下载ifconfig的工具
验证:
进web2容器 ping webb

 

 

以上是关于浅谈docker的四种网络模式与数据管理的主要内容,如果未能解决你的问题,请参考以下文章

浅谈docker的四种网络模式与数据管理

docker 的四种网络模式

Docker的四种网络模式和相关网络命令等操作

Docker的四种网络模式和相关网络命令等操作

docker的四种网络模式

Docker的四种网络模式