docker网络和模式

发布于:2024-04-25 ⋅ 阅读:(18) ⋅ 点赞:(0)

        Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container-Ip 直接通信。

        Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法直接通过 Container-IP 访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即 docker run 创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。

docker run -d --name test1 -P nginx                    #随机映射端口(从32768开始)

docker run -d --name test2 -p 43000:80 nginx        #指定映射端口

docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                   NAMES
9d3c04f57a68   nginx     "/docker-entrypoint.…"   4 seconds ago    Up 3 seconds    0.0.0.0:43000->80/tcp   test2
b04895f870e5   nginx     "/docker-entrypoint.…"   17 seconds ago   Up 15 seconds   0.0.0.0:49170->80/tcp   test1

浏览器访问:http://192.168.80.10:43000    、http://192.168.80.10:49170

#查看容器的输出和日志信息
docker logs 容器的ID/名称

安装Docker时,它会自动创建三个网络,Bridge (创建容器默认连接到此网络)、None 、Host

#查看docker网络列表
docker network ls

docker network list    

使用docker run 创建Docker容器时,可以 --net 或 --network 选项指定容器的网络模式

Host模式:使用--net=host 指定。
None模式:使用--net=none 指定。
Container模式:使用--net=container:NAME_ _or_ ID指定。
Bridge模式:使用--net=bridge 指定,默认设置,可省略。

二、docker的五种网络模式

2.1 host模式

容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口范围。

        如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的 NetworkNamespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

        使用host模式的容器可以直接使用宿主机的Ip地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是dockerhost 上已经使用的端口就不能再用了,网络的隔离性不好

        解决了IP地址不固定的情况,相当于Vmware中的桥接模式,与宿主机在同一个网络中,但没有独

Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。

一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、iptable规则等都与其他的Network Namespace隔离。

一个Docker容器一般会分配一个独立的Network Namespace。 但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace, 而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡、配置自己的IP等,而是使用宿主机的IP和端口。

启动软件#使用docker run创建Docker容器时,可以用 --net 或 --network 选项指定容器的网络模式
●host模式:使用 --net=host 指定。
●none模式:使用 --net=none 指定。
●container模式:使用 --net=container:NAME_or_ID 指定。
●bridge模式:使用 --net=bridge 指定,默认设置,可省略。

2.2 container模式

创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围。

        创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围(端口不能一致),只有一个容器有自己的网卡,出去还是docker 0进行通讯(有点像各个服务放在同一个宿主机上面这种情况)

        这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace(网络命名空间),而不是和宿主机共享。同样两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

2.3 node模式

该模式关闭了容器的网络功能。自闭

        使用none模式,Docker容器拥有自己的Network Namespace,但是并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息,需要我们自己为Docker容器添加网卡、配置IP等。

        这种网络模式下容器只有lo回环网络,没有其他网卡。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性,可以安全的储存数据,不会被攻击,可以用来当个仓库。

docker run -itd --name test1 centos:7 /bin/bash            #--name 选项可以给容器创建一个自定义名称

docker ps -a
CONTAINER ID   IMAGE      COMMAND       CREATED      STATUS       PORTS     NAMES
3ed82355f811   centos:7   "/bin/bash"   5 days ago   Up 6 hours             test1

docker inspect -f '{{.State.Pid}}' 3ed82355f811            #查看容器进程号
25945

ls -l /proc/25495/ns                    #查看容器的进程、网络、文件系统等命名空间编号
lrwxrwxrwx 1 root root 0 1月   7 11:29 ipc -> ipc:[4026532572]
lrwxrwxrwx 1 root root 0 1月   7 11:29 mnt -> mnt:[4026532569]
lrwxrwxrwx 1 root root 0 1月   7 11:27 net -> net:[4026532575]
lrwxrwxrwx 1 root root 0 1月   7 11:29 pid -> pid:[4026532573]
lrwxrwxrwx 1 root root 0 1月   7 12:22 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 1月   7 11:29 uts -> uts:[4026532570]

docker run -itd --name test2 --net=container:3ed82355f811 centos:7 /bin/bash
docker ps -a
CONTAINER ID   IMAGE      COMMAND       CREATED          STATUS          PORTS     NAMES
ff96bc43dd27   centos:7   "/bin/bash"   48 seconds ago   Up 46 seconds             test2
3ed82355f811   centos:7   "/bin/bash"   58 minutes ago   Up 58 minutes             test1

docker inspect -f '{{.State.Pid}}' ff96bc43dd27
27123

ls -l /proc/27123/ns            #查看可以发现两个容器的 net namespace 编号相同
lrwxrwxrwx 1 root root 0 1月   7 12:27 ipc -> ipc:[4026532692]
lrwxrwxrwx 1 root root 0 1月   7 12:27 mnt -> mnt:[4026532690]
lrwxrwxrwx 1 root root 0 1月   7 12:27 net -> net:[4026532575]
lrwxrwxrwx 1 root root 0 1月   7 12:27 pid -> pid:[4026532693]
lrwxrwxrwx 1 root root 0 1月   7 12:27 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 1月   7 12:27 uts -> uts:[4026532691]

Docker 使用的六种不同的 namespaces:

  1. PID Namespace:每个容器都有自己独立的进程空间,使得容器内的进程看起来像在一个独立的系统中运行一样。

  2. Network Namespace:每个容器有自己独立的网络命名空间,使得容器可以拥有自己的网络接口、IP 地址、路由表等网络资源。

  3. Mount Namespace:每个容器有自己独立的挂载点视图,使得容器可以拥有自己的文件系统挂载点,而不受宿主机的影响。

  4. UTS Namespace:用于隔离主机名和域名,使得每个容器可以有自己独立的主机名和域名。

  5. IPC Namespace:用于隔离进程间通信资源,使得容器内的进程无法直接访问其他容器的 IPC 资源。

  6. User Namespace:用于隔离用户和用户组的映射,使得容器内的特权用户在容器外部被映射为非特权用户,增强容器的安全性。

2.4 bridge模式(默认)

        默认为该模式,此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及iptables nat 表配置与宿主机通信。

        此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及iptables nat表配置与宿主之间的关联

        当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。

        从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以veth xxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。

        bridge模式是docker的默认网络模式,不写–net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看

2.5 自定义网络模式

2.5.1 查看网络模式列表  docker inspect  容器ID

先自定义网络,再使用指定IP运行docker

docker network ls

2.5.2 查看容器信息  docker inspect  容器ID

配置 环境 网关 挂载 cmd信息

docker inspect  容器ID

2.5.3 指定分配ip地址

创建自定义网络zhunet

docker network create --subnet=172.18.0.0/16 cphnet

自定义网络后,指定IP运行容器

1、#此处需run一个容器test02,指定网络IP运行容器test02
docker run -itd --name test02 --net zhunet --ip 172.18.0.2 nginx:latest /bin/bash
 
2、查看容器的IP地址信息
docker inspect test02 |grep IPAddress

三、暴露端口(冲突)

两个端口一样的情况下,暴露出去会导致地址冲突,所有需要docker0上需要做一个端口映射,通过ens33暴露出去,端口不同就可以

-p 自定义端口 ( 宿主机端口:容器内端口 )

-P 随机端口 (-P 49153起始 49153到65535)

3.1、 -p 自定义端口8081

自定义端口8081创建并运行容器testnginx

docker run -itd --name testnginx -p 8081:80 nginx:latest /bin/bash

进入容器并开启nginx

docker exec -it testnginx /bin/bash
nginx 

web测试

3.2 -P随机端口

创建并运行容器testnginx02

docker run -itd --name testnginx02 -P nginx:latest /bin/bash

四、脚本在容器中运行

4.1 把脚本传入一个已经运行的容器

#使用cp命令复制进去容器
docker cp start.sh cenos_v1:/opt
#使用cp命令从容器复制出来
docker cp cenos_v1:/opt/start.sh ./

4.2、如何对已经运行的容器添加或者修改端口
docker中假设运行一个业务容器,需要暴露三个端口,启动后发现少加了一个端口,如何动态添加端口? 

首先,我们可以修改/var/lib/docker/containers/containers_id中两个文件

① hostconfig.json 中的 portbinding:{} 修改端口或添加端口

②修改 config.v2.json 文件,修改对应的 Ports{} 来添加/修改端口

最后,重启守护进程。

五、总结

5.1 进入容器没有systemctl命令怎么解决

docker run -itd  --name cenos_v1 --privileged=true centos:7 /sbin/init
docker exec -it cenos_v1 /bin/bash

5.2 docker网络模式有哪些?分别提供哪些功能?

我这边了解到的有四种,Host container none bridge

Host :与宿主机共享网络名称空间/网络协议栈
Container:多个容器之间共享一个network namespaces
None :自闭空间
bridge:默认模式通过Veth对连接容器与docker0网桥,网桥分配给容器IP,同时**docker 0**作为“局域网”内容器的网关,最后和宿主机网卡进行通讯