使用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 却没能启动,难道启动的容器总会比自己定义所启动的容器少一个,这个问题有待于进一步解决。