首页
/ 深入解析ufw-docker项目的docker-entrypoint.sh实现原理

深入解析ufw-docker项目的docker-entrypoint.sh实现原理

2025-07-08 01:45:22作者:戚魁泉Nursing

项目背景与作用

ufw-docker项目是一个将Docker容器与UFW(Uncomplicated Firewall)防火墙集成的解决方案。该项目通过一个智能代理容器,实现了Docker容器端口与UFW防火墙规则的无缝对接,解决了Docker绕过UFW规则这一常见问题。

docker-entrypoint.sh核心功能解析

这个入口脚本是ufw-docker项目的核心组件,主要负责以下功能:

  1. UFW规则管理:动态添加、删除和更新防火墙规则
  2. Docker服务识别:识别Swarm服务并获取相关信息
  3. 长期运行:作为守护进程持续运行以保持规则更新

主要函数详解

1. ufw-allow-or-deny-service函数

function ufw-allow-or-deny-service() {
    declare id="$1"
    declare port="$2"

    if [[ "$port" = deny ]]; then
        run-ufw-docker delete allow "$id"
    else
        run-ufw-docker add-service-rule "$id" "$port"
    fi
}

这个函数是规则管理的核心逻辑,根据传入参数决定是允许还是拒绝特定服务的端口访问。它接收两个参数:

  • id:服务或容器的标识符
  • port:端口号或"deny"关键字

2. update-ufw-rules函数

function update-ufw-rules() {
    declare -p | sed -e '/^declare -x ufw_public_/!d' \
                     -e 's/^declare -x ufw_public_//' \
                     -e 's/="/ /' \
                     -e 's/"$//' |
        while read -r id port; do
            ufw-allow-or-deny-service "${id}" "${port#*/}"
        done
}

这个函数负责批量更新UFW规则,它:

  1. 从环境变量中筛选出以ufw_public_开头的变量
  2. 解析出服务ID和端口信息
  3. 为每个服务调用ufw-allow-or-deny-service函数设置规则

3. run-ufw-docker函数

function run-ufw-docker() {
    declare -a docker_opts=(run --rm -t --name "ufw-docker-agent-${RANDOM}-$(date '+%Y%m%d%H%M%S')"
         --cap-add NET_ADMIN --network host
         --env "DEBUG=${DEBUG}"
         -v /var/run/docker.sock:/var/run/docker.sock
         -v /etc/ufw:/etc/ufw "${ufw_docker_agent_image}" "$@")
    docker "${docker_opts[@]}"
}

这个函数封装了Docker运行命令,特别之处在于:

  • 使用随机名称避免冲突
  • 添加NET_ADMIN能力以管理网络
  • 使用host网络模式
  • 挂载Docker socket和UFW配置目录

4. 服务识别函数

function get-service-name-of() {
    docker inspect "$1" --format '{{range $k,$v:=.Config.Labels}}{{ if eq $k "com.docker.swarm.service.name" }}{{$v}}{{end}}{{end}}' | grep -E "^.+\$"
}

function get-service-id-of() {
    docker inspect "$1" --format '{{range $k,$v:=.Config.Labels}}{{ if eq $k "com.docker.swarm.service.id" }}{{$v}}{{end}}{{end}}' | grep -E "^.+\$"
}

这两个函数用于从容器中提取Swarm服务的名称和ID,通过查询Docker标签实现。

主流程控制

function main() {
    case "$1" in
        start)
            update-ufw-rules
            while true; do
                sleep "$(( 3600 * 24 * 7 ))" || break
            done
            ;;
        delete|allow|add-service-rule)
            ufw-docker "$@"
            ;;
        update-ufw-rules)
            update-ufw-rules
            ;;
        *)
            if [[ -f "$1" ]]; then
                exec "$@"
            else
                echo "Unknown parameters:" "$@" >&2
                exit 1
            fi
    esac
}

主函数处理不同命令:

  • start:初始化规则并进入守护进程模式
  • 其他命令:直接转发给ufw-docker处理
  • 未知命令:尝试执行或报错

技术亮点

  1. 环境变量驱动配置:通过ufw_public_前缀的环境变量动态配置规则
  2. Swarm服务感知:能够识别Docker Swarm服务并正确处理
  3. 安全设计:使用随机容器名和有限生命周期(--rm)增强安全性
  4. 调试支持:通过DEBUG环境变量控制调试输出

使用建议

  1. 在生产环境中,建议设置合理的DEBUG日志级别
  2. 可以通过环境变量ufw_docker_agent_image自定义代理镜像
  3. 规则更新后无需重启服务,脚本会自动处理

这个入口脚本展示了如何优雅地解决Docker与UFW集成的问题,通过精心设计的函数分工和清晰的流程控制,实现了防火墙规则的动态管理。