浅谈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的四种网络模式与数据管理的主要内容,如果未能解决你的问题,请参考以下文章