Docker固定Container IP

举报
SHQ5785 发表于 2022/06/27 09:30:43 2022/06/27
【摘要】 ​使用pipework工具。前提:每个Container所做的工作现在还很少,可以不用save、commit。为了便于通信,自定义一个网桥(192.168.1.180/24),使之IP与宿主主机IP在同一网段内。bridge模式bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网...


使用pipework工具。

前提:每个Container所做的工作现在还很少,可以不用save、commit。

为了便于通信,自定义一个网桥(192.168.1.180/24),使之IP与宿主主机IP在同一网段内。

bridge模式

bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。下面着重介绍一下此模式。

bridge模式的拓扑

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

接下来就要为容器分配IP了,Docker会从RFC1918所定义的私有IP网段中,选择一个和宿主机不同的IP地址和子网分配给docker0,连接到docker0的容器就从这个子网中选择一个未占用的IP使用。

如一般Docker会使用172.17.0.0/16这个网段,并将172.17.42.1/16分配给docker0网桥(在主机上使用ifconfig命令是可以看到docker0的,可以认为它是网桥的管理接口,在宿主机上作为一块虚拟网卡使用)。

单机环境下的网络拓扑如下,主机地址为10.10.101.105/24。

为了使本地网络中的机器和Docker容器更方便的通信,我们经常会有将Docker容器配置到和主机同一网段的需求。这个需求其实很容易实现,我们只要将Docker容器和主机的网卡桥接起来,再给Docker容器配上IP就可以了。

#安装pipework

wget https://github.com/jpetazzo/pipework/archive/master.zip #下载 pipework

unzip master.zip            #解压

cp pipework-master/pipework  /usr/bin/   #拷贝pipework到 /usr/bin/下

chmod +x /usr/bin/pipework    #赋予该命令执行权限

自定义一个网桥:

brctl addbr br0

ifconfig br0 192.168.1.188 netmask 255.255.255.0

编辑/etc/defautl/docker.io文件,追加以下内容,指定使用的网桥:

DOCKER_OPTS="-b=br0"

再次启动docker:

service docker.io start

Contianer未绑定IP之前,其IP地址果然会改变。

注:veth设备是成双成对出现的,一端是容器内部命名eth0,一端是加入到网桥并命名的veth17f560a(通常命名为veth*),他们组成了一个数据传输通道,一端进一端出,veth设备连接了两个网络设备并实现了数据通信。

Pipework有个缺点就是给容器指定完固定IP,如果容器重启,那么固定IP会消失,还需要重新指定,容器量大时可写个脚本来完成。

思路:利用jsvc创建服务,在linux启动时自动创建指定IP的网桥br0,然后利用pipework工具为容器c1-c4添加新的网卡(前提:容器c1-c4均已处以启动态),将其连接到新创建的br0网桥上,以此创建指定IP的容器。

Jsvc方式见博客“分布式进阶(五)之JSVC配置”

其中的一个问题是:如何在Ubuntu下java代码中调用shell脚本。

/**

* 运行shell脚本

* @param shell 需要运行的shell脚本

*/

public static void execShell(String shell){

try {

Runtime rt = Runtime.getRuntime();

rt.exec(shell);

} catch (Exception e) {

e.printStackTrace();

}

}

还有一个方法就是在linux启动时直接运行shell脚本:

只需编辑/etc/init.d/rc.local文件,在最后加上你的脚本即可。

比如:我已经编写了一个脚本shell.sh,存放在/home/mars704/Desktop/ 下面

在终端输入 gedit /etc/init.d/rc.local编辑文件,在结尾出加入:

/home/mars704/Desktop/sh.sh 即可开机自动加载脚本

原理:

首先,linux随机启动的服务程序都在/etc/init.d这个文件夹里,里面的文件全部都是脚本文件(脚本程序简单的说就是把要运行的程序写到一个文件里让系统能够按顺序执行,类似windows下的autorun.dat文件),

另外在/etc这个文件夹里还有诸如名为rc1.d, rc2.d一直到rc6.d的文件夹,这些都是linux不同的runlevel,我们一般进入的X windows多用户的运行级别是第5级,也就是rc5.d,

在这个文件夹下的脚本文件就是运行第5级时要随机启动的服务程序。需要注意的是,在每个rc (1-6).d文件夹下的文件其实都是/etc/init.d文件夹下的文件的一个软连接(类似windows中的快捷方式)

,也就是说,在 /etc/init.d文件夹下是全部的服务程序,而每个rc(1-6).d只链接它自己启动需要的相应的服务程序!

要启动scim(某一程序),我们首先要知道scim程序在哪里,用locate命令可以找到,scim在/usr/bin/scim这里,其中usr表示是属于用户的,bin在linux里表示可以执行的程序。

这样,我就可以编写一个脚本程序,把它放到/etc/init.d里,然后在rc5.d里做一个相应的软链接就可以了。

ln -s a b 中的 a 就是源文件,b是链接文件名,其作用是当进入b目录,实际上是链接进入了a目录

这个脚本其实很简单,就两行:

#!/bin/bash

/usr/bin/scim

第一行是声明用什么终端运行这个脚本,第二行就是要运行的命令。

还需要注意的一点是,在rc5.d里,每个链接的名字都是以S或者K开头的,S开头的表示是系统启动是要随机启动的,K开头的是不随机启动的。这样,你就可以知道,如果我要哪个服务随机启动,

就把它名字第一个字母K改成S就可以了,当然,把S改成K后,这个服务就不能随机启动了。因此,我这个链接 还要起名为SXXX,这样系统才能让它随机启动。

在RH下,rc.local是默认启动的最后一个脚本文件,所以,

如果你想要随机启动,还有一种方法就是在rc.local的尾部加入/usr/bin/scim,这样就可以了。

四个节点配置好了固定IP,节点间的架构图如下:

图一

注:Docker启动时会在主机上自动创建一个docker0虚拟网桥,实际上是一个linux网桥,可以理解为一个软件交换机。它会在挂在其上的接口之间进行转发。

同时,Docker会随机分配一个本地未占用的私有网段(在RFC1918中定义)中的一个地址给docker0接口。此后启动的容器内的网口也会自动分配一个同一网段的地址。

图二

注:图二是自己所写有关配置自定义网桥,给container添加固定IP的shell脚本

图三

注:图三是Linux重启后所起到的效果。

疑惑:配置脚本中明明定制了四个启动容器,结果却只启动了三个。经检查,启动的三个容器其IP地址均已固定。

图四

注:在Ubuntu命令行输入以上命令时提示如上信息。错误原因及解决措施见博客"分布式进阶(十一) 常见错误汇总"

图五

注:抱着试试看的心态,自己又运行了一个容器,结果奇迹了,前面的915容器启动了,而新启动的容器aef却没能启动,难道启动的容器总会比自己定义所启动的容器少一个,这个问题有待于进一步解决。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。