You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Resin.io环境下Docker特权容器管理主机iptables规则的实现

在Resin.io环境下用特权容器管理主机iptables并自动清理规则

需求背景

你在树莓派的Resin.io框架里跑Mosquitto服务,设备有两个网络接口(分别连互联网和内网),希望只让Mosquitto暴露给局域网。之前用单容器的方案有几个头疼的问题:

  • 容器里的服务必须用特权权限运行
  • 没法用Docker DNS(通过容器名解析IP)
    所以改用独立的防火墙容器来统一配置,完美解决这些问题的同时,还能在容器停止时自动清理iptables规则,避免残留问题。

核心配置拆解

1. docker-compose.yml 配置

在你提供的基础配置上,我补了个重启策略,确保容器意外退出能自动恢复:

version: '2'
services:
  firewall:
    build: ./firewall
    container_name: firewall
    network_mode: host
    privileged: true
    restart: unless-stopped  # 新增:意外退出自动重启
  • network_mode: host:让容器直接使用主机的网络命名空间,这样才能操作主机的iptables
  • privileged: true:必须开启,否则容器没有权限修改主机的iptables规则

2. Dockerfile 编写

我们用Resin官方的树莓派基础镜像,把防火墙脚本复制进去并设置为入口点:

# 根据你的树莓派型号选择镜像,比如raspberrypi3/4/zero等
FROM resin/raspberrypi3-debian:latest

# 安装iptables(部分基础镜像可能自带,保险起见加上)
RUN apt-get update && apt-get install -y --no-install-recommends iptables && rm -rf /var/lib/apt/lists/*

# 复制防火墙脚本到容器内并赋予执行权限
COPY firewall.sh /usr/local/bin/firewall.sh
RUN chmod +x /usr/local/bin/firewall.sh

# 设置入口点,让脚本在前台运行
ENTRYPOINT ["/usr/local/bin/firewall.sh"]

3. 关键的防火墙脚本(firewall.sh)

这个脚本要完成两个核心任务:添加iptables规则,以及捕获SIGTERM信号并清理规则

#!/bin/bash

# 定义清理规则的函数
cleanup() {
    echo "收到停止信号,开始清理iptables规则..."
    # 用-D(删除)对应添加时的-A,确保精准移除目标规则
    iptables -D INPUT -i wlan0 -p tcp --destination-port 1883 -j DROP
    echo "规则已清理,容器退出"
    exit 0
}

# 捕获Docker停止容器时发送的SIGTERM信号
trap cleanup SIGTERM

# 添加iptables规则:禁止从wlan0接口访问1883端口(如果内网是eth0就替换成eth0)
echo "添加iptables规则:禁止wlan0接口的TCP 1883端口访问..."
iptables -A INPUT -i wlan0 -p tcp --destination-port 1883 -j DROP

# 让脚本在前台持续运行,避免容器执行完脚本直接退出
echo "防火墙规则已生效,容器持续运行中..."
tail -f /dev/null
  • trap cleanup SIGTERM:这是核心逻辑,当Docker发送停止信号给容器时,会自动触发清理函数,删掉之前添加的规则
  • tail -f /dev/null:让脚本一直前台运行,保证容器存活,才能持续监听停止信号

部署步骤

  1. 在项目根目录下创建firewall文件夹,把Dockerfile和firewall.sh放进去
  2. 把上面的docker-compose.yml放在项目根目录
  3. 正常通过Resin.io的部署流程推送代码即可

这样一来,防火墙容器会自动添加规则,当你停止容器时,规则也会被自动清理,完全不会留下残留问题,而且Mosquitto容器可以不用特权权限,还能正常使用Docker DNS啦~

内容的提问来源于stack exchange,提问作者Moritz

火山引擎 最新活动