前面介绍docker镜像的秘密这篇知识点的时候,https://blog.csdn.net/dudadudadd/article/details/128200522
,提到了docker容器也有属于自己的IP的概念,默认的Docker容器是采用的是bridge网络模式。并且提到了一嘴自定义网卡配置,本来是打算不写这篇博文,让大家自己去查的,因为命令中有一个CIDR值要有点网络基础,要不然配不明白。
到最近机缘巧合之下,和朋友说起这个事情,灵光一闪想到原理虽然复杂,但是可以只说表象就够用了,所以决定补充一篇docker容器自定义网卡配置让其他设备可以直接访问容器。
首先我们要知道,docker容器的网络配置自带了三种模式,除了默认的bridge模式之外,还有其他的,我们可以用命令查看当前docker有几种网络模式。
[root@hdp3 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
e8e4f692235d bridge bridge local
4d563e307658 host host local
7bfee5177ee6 none null local
上面的查询主要是为了让大家有docker网络模式这个概念。我们自定义网络,不用自带的,因为自带的bridge
,相当于VMware的NAT,可出于某种不可描述的原因,导致它和不指定网络模式创建的容器中的bridge模式存在DNS有无的差异,就是说上面通过命令查出来的bridge网络模式是有DNS的,而你不指定网络模式创建的容器中所使用的bridge网络模式是没有DNS功能的,这点就很诡异。host
模式,很少使用,它是指容器完全没有自己的网络配置,直接使用宿主机的网卡,这种网络模式如果你只是使用容器做IP映射可以用一用,其他更灵活的使用方式根本不考虑这种网络模式。最后一个nono
是预留的空网络无法使用。
而我们自定义网络模式的时候用的是macvlan模块(DRIVER)
,这是docker后期版本中提出的一种新型的网络模块,可以提供更加灵活的网络。
配置的时候,你需要先运行下面的命令,创建一个网络模式。注意网络策略用宿主机的。注意,从实现上来说,完全可以使用自定义网络模式,配置其他网段,但是那样就和bridge一样的效果了,没有再自定义的意义
docker network create clu --driver macvlan --subnet=192.168.88.0/24 --gateway=192.168.88.2 -o macvlan_mode=bridge -o parent=ens33
clu
:这个是你的网络模式名字,你可以自定义
--driver macvlan
:使用macvlan网络模块
--gateway
:该网络模式使用的网关
-o
:是详情配置,上面命令是指基于bridge模式,并继承宿主机的网卡,ens33是你宿主机的网卡名
--subnet
:是最特别的一个配置,它的值要求是CIDR格式,最后我再说怎么写这个配置
当你创建好了网络模式,你就可以查询到了
[root@hdp3 ~] docker network ls
NETWORK ID NAME DRIVER SCOPE
e8e4f692235d bridge bridge local
2cd5c6656669 clu macvlan local
4d563e307658 host host local
7bfee5177ee6 none null local
当你创建容器的时候你要使用如下命令
docker run -it --net clu --ip 192.168.88.191 centos:7.8.2003
--net
:指定网络模式
--ip
:是给容器一个IP,其实可以在不指定用随机的,还可以在创建网络模式的时候用–ip-range参数限制随机的ip范围,但是正式使用都是静态IP
上面这种命令创建容器之后,该容器就和你的宿主机所在同一网段,并且可以被其他的设备直接发现,比如我在本地Windows上ping一下
但是一般情况docker容器是没有系统命令使用权限的,而一般配置了这样的网络模式后,就会同样的有使用systemctl
等系统命令的需求延伸出来,这种时候你就要用特权模式创建容器,注意特权模式如果不用守护进程方式启动,则会出现阻塞进程的情况,到之后只能ctrl+c了,但容器很可能会被关闭。
docker run -d --net clu --ip 192.168.88.190 --privileged=true centos:7.8.2003 /usr/sbin/init
以特权模式启动的容器,连接时必须指定登录口,如/bin/bash
docker exec -it f063be0bd990 /bin/bash
多数情况下当你的容器和宿主机在同一网段,可以被其他设备发现,并且以特权模式启动之后,很大概率就会又有一个需求延伸出来,就是脱离宿主机,直接SSH连接,这个时候你就需要在容器里面做下面的操作
首先在容器里面运行命令,生成一条用户登录信息,这里直接用root了,并且根据提示输入这个用户的密码认证
[root@f063be0bd990 /] passwd # add root
Changing password for user root.
New password:
BAD PASSWORD: The password is shorter than 8 characters
Retype new password:
passwd: all authentication tokens updated successfully.
随后安装SSH
yum install -y openssh-* initscripts
最后如果你有需要可以改ssh的配置文件/etc/ssh/sshd_config
,或者使用默认不做更改,随后包ssh启动,启动的时候只能直接调用命令,service
在新版本的docker中是不让使用的及时你用的是特权容器,因为docker的官方核心思想就是用后即焚的东西,所以官方也不推荐在容器里在装服务
[root@test01 /] /etc/init.d/sshd start
Starting sshd (via systemctl): [ OK ]
[root@test01 /] /etc/init.d/sshd status
● sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2022-12-10 09:25:10 UTC; 20s ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 368 (sshd)
CGroup: /system.slice/docker-2441cd39fce5d3de267a18ff2076c970eb7e61505db88c4bcf9b72e9ab5b17e0.scope/system.slice/sshd.service
└─368 /usr/sbin/sshd -D
‣ 368 /usr/sbin/sshd -D
Dec 10 09:25:10 test01 systemd[1]: Starting OpenSSH server daemon...
Dec 10 09:25:10 test01 sshd[368]: Server listening on 0.0.0.0 port 22.
Dec 10 09:25:10 test01 sshd[368]: Server listening on :: port 22.
Dec 10 09:25:10 test01 systemd[1]: Started OpenSSH server daemon.
此时你就可以用你的连接工具直接连接了,我之所以叫test01,是因为我把容器的主机名也改了,看的更像一个单独的系统
如果你看着容器的默认主机名不顺眼,这个也可以改,你需要关闭容器、关闭 docker 服务!!!!一定要关闭
,之后进入容器在宿主机上的配置文件中,就在你本地docker仓库的containers文件夹下,根据容器id进入对应的文件夹找到,搜索含有你要修改的容器id的配置文件
[root@hdp3 2441cd39fce5d3de267a18ff2076c970eb7e61505db88c4bcf9b72e9ab5b17e0]# pwd
/opt/docker/containers/2441cd39fce5d3de267a18ff2076c970eb7e61505db88c4bcf9b72e9ab5b17e0
[root@hdp3 2441cd39fce5d3de267a18ff2076c970eb7e61505db88c4bcf9b72e9ab5b17e0]# ll
总用量 32
-rw-r----- 1 root root 0 12月 10 16:55 2441cd39fce5d3de267a18ff2076c970eb7e61505db88c4bcf9b72e9ab5b17e0-json.log
drwx------ 2 root root 4096 12月 10 16:55 checkpoints
-rw------- 1 root root 2959 12月 10 16:59 config.v2.json
-rw-r--r-- 1 root root 1201 12月 10 16:59 hostconfig.json
-rw-r--r-- 1 root root 13 12月 10 16:55 hostname
-rw-r--r-- 1 root root 150 12月 10 16:59 hosts
drwx------ 3 root root 4096 12月 10 16:55 mounts
-rw-r--r-- 1 root root 53 12月 10 16:55 resolv.conf
-rw-r--r-- 1 root root 71 12月 10 16:55 resolv.conf.hash
随后你要修改两个文件分别是config.v2.json、hostname
中的容器id对应的值,比如本例中要修改的容器id是2441cd39fce5
,则就要去找配置文件中的内容做修改
config.v2.json
hostname
最后重启docker服务和容器,进入容器你就会发现主机名成功修改
[root@hdp3 2441cd39fce5d3de267a18ff2076c970eb7e61505db88c4bcf9b72e9ab5b17e0] docker exec -it 2441cd39fce5 /bin/bash
[root@test01 /]#
最后我们说一下创建网络模式时的CIDR取值问题。
CIDR的格式是IP/网络ID
,前面的IP你可以看做是一个配合网关表示网络IP段的表达式,重点是网络ID,这个ID是让人迷糊的罪魁祸首。如果你使用的网络是IPV4的时候,它最大有效值是32
,它的作用是用来表示网络策略所用的IP类型。
传统的意义上,网络IPV4类型分为三类ABC,总共是四组二进制,但用十进制展示的数字来表示,而A类网络的默认起始掩码是255.0.0.0
,B类默认起始是255.255.0.0
,C类默认起始是255.255.255.0
。翻译成二进制来看,也就是说,整个传统网络IPV4策略中,从a到c类的子网默认掩码的范围是11111111.00000000.00000000.00000000
到11111111.11111111.11111111.11111111
而这里面,所以网络ID其实是你所处网段所用掩码翻译成二进制后,有几个1。当然这只是为了让大家明白这里用到的网络ID是什么,真正的要说了解网络掩码的原理,是一个很复杂庞大的东西,大家如非需要,则没必要了解太深。
所以我上面因为我用的是vmware虚拟机,用的是192的一个c类地址,所以我的子网掩码应该是255.255.255.0,换算成CIDR网络ID就是24