将 LAN IP 地址分配给与主机 IP 地址不同的 Docker 容器

Posted

技术标签:

【中文标题】将 LAN IP 地址分配给与主机 IP 地址不同的 Docker 容器【英文标题】:Assign LAN IP address to Docker container different from host's IP address 【发布时间】:2016-04-15 08:52:32 【问题描述】:

不熟悉 Unix 网络,添加虚拟接口等,现在正在尝试学习。我们正在尝试对我们的应用程序进行 docker 化。 我的要求是:将 ip 分配给可从外部应用程序/浏览器访问的 docker 容器。

容器ip基本上应该可以从同一网络中的不同计算机ping通。我不想使用端口转发。

    我想访问 docker 容器,就像我们使用 ip 访问 VM 一样 address.[ 没有端口映射,-p 标志。如果我运行任何服务器,如 Apache 或 Tomcat 在容器内,它应该可以使用容器 ip 和 港口。例如:http://container_ip:8443] 这在 docker 中可行吗?

    在我的 Unix 机器 (RHEL 7.1) 上运行 ifconfig 会显示 docker0、ens、lo 和 veth 接口。没有eth0。对此有点困惑。

【问题讨论】:

【参考方案1】:

我很难获得该功能,我将分享我的经验以及我为获得您需要的功能所做的工作。

简短的回答:

您需要创建您自己的网桥,将主机的物理网络接口连接到该网桥,并连接每个容器的虚拟接口,使其表现得像您的普通桥接虚拟机一样网络,然后让容器在启动时选择自己的IP地址。

详细答案:

创建持久网桥

Bridge,是一个设备(在我们的例子中是虚拟设备),其行为类似于网络交换机(主要在网络第 2 层上运行),即它可以连接两个或多个网络接口开启如果它们具有相同的子网,则使用相同的局域网 (LAN)

您将创建新的持久性网桥br0(它将在系统启动时自动启动),将您的物理网络接口添加到其中(在我的情况下是eth0)。请注意,将您的接口添加到网桥后,该接口不再需要 IP 地址,因为网桥将获得 IP 地址并可以代替您的接口使用,即您可以使用网桥进行通信 就好像它是您的物理接口一样,它将输入/输出数据包转发到正确的目的地。您无需为网桥分配任何硬件(MAC 地址),它会自动获取第一个添加接口的 MAC。

警告:强烈建议不要远程执行这些步骤,除非您可以物理访问您的服务器!如果您不小心,您可能会失去与服务器的连接。

安装网桥管理实用程序:

sudo apt install bridge-utils

如果没有bridge-utils 包,系统将无法创建网桥。

要创建持久性桥接,请编辑interfaces 文件:

sudo vim /etc/network/interfaces

将以下配置添加到文件末尾(根据您的需要调整它们):

auto br0
iface br0 inet static
    bridge_ports eth0
    address 192.168.1.10
    netmask 255.255.255.0
    broadcast 192.168.1.255
    gateway 192.168.1.1

现在移除 Docker 的默认网桥 docker0,因为我们不需要它:

sudo systemctl stop docker
sudo ip link set dev docker0 down
sudo brctl delbr docker0

编辑 Docker 的服务启动脚本以使用您的网桥 (br0) 而不是 Docker 的默认网桥 (docker0),并传递一些重要的网桥参数:

Ubuntu:

sudo vim /etc/systemd/multi-user.target.wants/docker.service

使文件看起来像这样:

[Service]

ExecStart=/usr/bin/dockerd -H fd:// --bridge=br0 --fixed-cidr=192.168.1.32/27 --default-gateway=192.168.1.1

现在告诉系统该文件的更改:

sudo systemctl daemon-reload

重启系统:

sudo reboot

现在检查你的桥,它应该在那里!

ip addr

现在像下面这样创建你的容器,这将为你的容器提供一个固定 IP

  docker run --name myContainer \
  -it --restart always --memory 100M \
  --network bridge --cap-add NET_ADMIN \
  --hostname client1.noureldin.local \
  --add-host "client1.noureldin.local client1":192.168.1.123 \
  mnoureldin/general-purpose:latest /bin/bash -c " \
  ip addr flush dev eth0; \
  ip addr add 192.168.1.123/24 brd + dev eth0; \
  ip route add default via 192.168.1.1 dev eth0; \
  /bin/bash"

与您的网络要求相关的重要部分是:

  --network bridge --cap-add NET_ADMIN \
  ip addr flush dev eth0; \
  ip addr add 192.168.1.123/24 brd + dev eth0; \
  ip route add default via 192.168.1.1 dev eth0; \

当然要确保您在容器中安装了iproute2 net-tools iputils-ping 软件包,以便能够执行常见的网络命令(通过ip 命令提供固定IP)。

第一次运行容器时,您可能不会注意到 IP 地址有任何变化,因为您的容器可能没有 iproute2 包(即没有 ip 命令),只需安装提到的包,然后重新启动容器,一切都应该完全如你所愿!

希望对您有所帮助。

【讨论】:

【参考方案2】:

我目前首选的方法是使用 macvlan 或 ipvlan Docker 网络驱动程序。我更喜欢 macvlan,因为每个容器都可以有自己的 MAC 地址,但是像 VMware 这样的东西不喜欢为单个虚拟化网卡设置多个 Mac 地址,并且无法正确路由流量。

设置非常简单。首先,您需要确定几件事。

主网络的子网。本示例使用 10.0.0.0/24 网络的网关。以 10.0.0.1 为例 用于分配 ips 的 IP 范围(如果需要,可以在执行 Docker 运行时静态分配此范围之外的 ips)。在本例中,我将使用 10.0.0.128/25。你需要一大块 ip 来让 Docker 管理,所以你需要确保这些 ip 在你的网络上没有被使用。 要用于流量的设备的名称。例如,我将使用 eth0 您要创建的新 Docker 网络的名称。以“我的网”为例。

接下来创建一个新的 Docker 网络,如下所示:

docker network create -d macvlan —-subnet 10.0.0.0/24 --ip-range 10.0.0.128/25 —-gateway 10.0.0.1 -o parent=eth0 mynet

现在当你启动容器时使用

docker run —-network mynet .....

有关更多信息,请参阅 docker 文档:https://docs.docker.com/engine/userguide/networking/get-started-macvlan

对这种方法的一个警告是 macvlan/ipvlan 似乎不能很好地与 Docker for Mac 一起使用。它创建的 HyperKit 虚拟机有点像一个黑盒子。 macvlan/ipvlan 方法需要一个更可控的网络,而 Docker for Mac 没有给你。如果您尝试使用 Docker for Mac 来执行此操作,那么我建议您设置一个 Docker Machine。如何做到这一点的文档在这里:https://docs.docker.com/machine/get-started/。

在这种情况下,除非您喜欢在 Mac 上设置路由规则,否则您应该让 docker 机器使用一个桥接接口,然后 macvlan/ipvlan 网络可以连接到该接口。根据我的经验,不需要通过 MacOS 主机进行 NAT 的第二个 NIC,但您可能会发现其他情况。

【讨论】:

以上是关于将 LAN IP 地址分配给与主机 IP 地址不同的 Docker 容器的主要内容,如果未能解决你的问题,请参考以下文章

路由器管理

为LAN链接配置的IP地址需要使用自动IP地址?

通过路由器的IP映射来解决,两个不同IP地址的PC机之间的从LAN口到WAN口的单向通讯问题

如何在Linux中发现IP地址冲突

IP子网划分

网络基础知识