利用iptables给Docker绑定一个外网IP

本文介绍如何通过iptables为Docker容器绑定外部IP地址,实现容器像虚拟机一样与外部网络通信。包括为主机绑定多个IP地址、设置DNAT与SNAT规则等步骤。

背景

由于Docker默认是不能够与外部进行直接的通信,比较普遍的仿佛是利用启动时-p来与主机进行端口映射与外界沟通。但是有时候在有其他需求时并不太方便,特别是在进行一些docker打包之前的内部开发时,希望其能够像虚机一样能够与外部有很好的通信,便希望其能够绑定外部的IP地址。 
docker默认的网络是桥接在创建好后的网桥docker0上的。docker0默认的典型地址为172.17.42.1,子网掩码为255.255.0.0。之后启动容器会给容器分配一个同一网段(172.17.0.0/16)的地址。然后启动docker容器时会创建一对veth pair。其中一端为容器内部的eth0,另外一端为挂载到docker0网桥并以veth开头命名。如下所示:

#brctl show
bridge name bridge id STPenabled interfaces
docker0 8000.56847afe9799 no veth135f096
veth5f8fe2d
 
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

通过这种方式,容器可以跟主机以及容器之间进行通信,主机和容器共享虚拟网络。 
在做开发等时候,可能希望容器能够像虚机一样远程登录与访问,这时候就需要给容器再绑定一个外部IP地址,这时候即可考虑采用iptables进行端口转发来实现对于容器的外部IP绑定。

环境

一台ubuntu的服务器,所属网段为10.50.10.0/26,该服务器的IP为10.50.10.26,由于还使用了ovs,因此是该IP是在br-ex上的; 
一个ubuntu的容器,IP为172.17.0.1/26 。

目的

通过iptables为IP为172.17.0.1的容器绑定外部IP 这里为10.50.10.56.

过程

整个过程大致分为3部分:

1. 为主机绑定多个IP地址

这一步可以通过如下命令来给网桥绑定另外一个IP:

#ifconfig br-ex:010.50.10.56/24
 
  • 1
  • 1

如果希望重启机器后仍然能够生效,需要将其写入到/etc/network/interfaces中。

2. iptables设置DNAT

通过DNAT来重写包的目的地址,将指向10.50.10.56的数据包的目的地址都改为172.17.0.1,这样即可以

#iptables -t nat -A PREROUTING -d 10.50.10.56 -p tcp -m tcp --dport 1:65535 -j DNAT--to-destination 172.17.0.1:1-65535
 
  • 1
  • 1

3. iptables设置SNAT

重写包的源IP地址,即在容器中收到数据包之后,将其源改为docker0的地址。

#iptables -t nat -A POSTROUTING -d 172.17.0.1 -p tcp -m tcp --dport 1:65535 -j SNAT --to-source172.17.42.1
 
  • 1
  • 1

保存规则

如果希望保存下来,需要通过命令:

#/etc/init.d/iptables save
 
  • 1
  • 1

来进行保存。

删除规则

当然如果想删除该规则,也可以通过

# iptables –t nat –D PREROUTING <number>
# iptables –t nat –D POSTROUTING <number>
 
  • 1
  • 2
  • 1
  • 2

来将创建的这两条规则删除。

验证

首先通过iptables来查看是否生效。

# iptables -n -t nat -L
Chain PREROUTING (policyACCEPT)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 10.50.10.56 tcp dpts:1:65535to:172.17.0.1:1-65535
Chain INPUT (policyACCEPT)
target prot opt source destination
Chain OUTPUT (policyACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policyACCEPT)
target prot opt source destination
MASQUERADE all -- 10.50.10.0/26 0.0.0.0/0
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
SNAT tcp -- 0.0.0.0/0 172.17.0.1 tcp dpts:1:65535 to:172.17.42.1
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

然后可以通过安装ssh或者apache2等需要使用端口的服务来进行验证。

当然实现这个功能会有很多种方法,欢迎大家来拍砖~

参考

1,《Docker——从入门到实践》:高级网络配置 
http://dockerpool.com/static/books/docker_practice/advanced_network/README.html 
2,The netfilter/iptables HOWTO’s 
http://www.netfilter.org/documentation/index.html 
3,Iptables 指南 

http://man.chinaunix.net/network/iptables-tutorial-cn-1.1.19.html


转自:http://blog.youkuaiyun.com/shipengfei92/article/details/47089055

当然可以!**Docker 容器完全可以绑定多个 IP 地址**,你可以让同一个容器的服务通过 **多个不同的宿主机 IP(如 `192.168.100.100` 和 `10.20.29.49`)访问到**,每个 IP 都监听相同的端口或不同端口。 --- ### ✅ 方法:使用多个 `-p` 参数绑定多个 IP ```bash docker run -d \ --name webvirtcloud \ -p 192.168.100.100:8000:8000 \ -p 10.20.29.49:8000:8000 \ your-webvirtcloud-image ``` > 🔍 解释: - 将容器的 `8000` 端口映射到两个宿主机 IP 上: - `192.168.100.100:8000` - `10.20.29.49:8000` - 外部用户可以通过任意一个 IP + 端口访问服务 ✅ 效果: - 用户 A 访问:`http://192.168.100.100:8000` - 用户 B 访问:`http://10.20.29.49:8000` - 都能正常打开 WebVirtCloud 页面 --- ### 🌐 更灵活的用法示例 #### 1. 绑定多个 IP 到不同端口(用于测试/隔离) ```bash docker run -d \ --name webvirtcloud \ -p 192.168.100.100:8000:8000 \ -p 10.20.29.49:9000:8000 \ your-webvirtcloud-image ``` - `192.168.100.100:8000` → 容器 8000 - `10.20.29.49:9000` → 容器 8000(对外显示为 9000) 适合做灰度发布、内部调试等场景。 #### 2. 同时绑定 IPv4 和 IPv6 地址 ```bash -p 192.168.100.100:8000:8000 \ -p [2001:db8::1]:8000:8000 ``` 支持双栈网络环境。 #### 3. 绑定所有接口(0.0.0.0)+ 特定 IP(冗余配置) ```bash -p 0.0.0.0:8000:8000 ``` 等价于: ```bash -p 8000:8000 ``` 表示监听在宿主机的所有网卡上(包括 `lo`, `eth0`, `usb0` 等),只要请求发到任意 IP 的 `8000` 端口都能访问。 --- ### ✅ 验证是否成功绑定多个 IP 运行以下命令查看监听状态: ```bash netstat -tulnp | grep :8000 ``` 你应该看到类似输出: ```text tcp6 0 0 192.168.100.100:8000 :::* LISTEN 12345/docker-proxy tcp6 0 0 10.20.29.49:8000 :::* LISTEN 12346/docker-proxy ``` 或者使用 `ss` 命令: ```bash ss -tuln | grep :8000 ``` --- ### ⚠️ 注意事项 | 要点 | 说明 | |------|------| | **IP 必须存在于宿主机上** | 如果你写了一个不存在的 IP(如 `1.1.1.1`),Docker 会启动失败或无法监听 | | **防火墙需放行对应端口** | 每个 IP 的端口都需要在 `iptables` / `ufw` 中开放 | | **Django 的 ALLOWED_HOSTS 要包含这些 IP** | 否则返回 `400 Bad Request` | ```python # settings.py ALLOWED_HOSTS = [ '192.168.100.100', '10.20.29.49', 'localhost' ] CSRF_TRUSTED_ORIGINS = [ 'http://192.168.100.100', 'http://10.20.29.49', 'http://localhost' ] ``` --- ### ✅ 实际应用场景 | 场景 | 如何使用多 IP 绑定 | |------|------------------| | USB 网卡和以太网同时提供服务 | `usb0`: `192.168.100.100`, `eth0`: `10.20.29.49` | | 内外网分离访问 | 内网 IP 开放管理界面,外网 IP 只读 | | 多租户网络隔离 | 不同客户走不同 IP 接入 | | 高可用备用路径 | 主 IP 故障时切到备 IP | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值