集成飞网的容器镜像
2025年4月4日大约 5 分钟
本文档将向你展示如何通过 Dockerfile 将飞网客户端程序与自定义应用(如 Nginx 和 gmzta-nginx-connector)结合,构建并运行自定义容器镜像。
该容器的主要用途是:
快速集成飞网认证机制至已有服务中:借助 gmzta-nginx-connector 与 Nginx 的联动能力,在不改动业务代码的前提下,实现请求认证、用户识别与权限校验。
部署统一认证入口:作为统一的认证代理容器,可用于转发请求并根据认证结果决定是否放行,有效增强服务安全性。
支持多架构构建与部署:支持 x86、ARM 等多平台架构,方便在不同硬件环境下部署,如 x86 主机、树莓派、NAS 等。
1. 准备工作
在构建容器镜像之前,运行环境的系统架构。根据不同架构(如 386
, amd64
, arm
, arm64
),调整dockerfile中的下载地址。
目录结构
├── docker/
├────── Dockerfile #用与配置容器镜像
├────── entrypoint.sh #用与配置容器镜像
├────── nginx.conf #用与配置容器镜像
├────── compose.yaml #用于启动容器
└────── default-nginx.conf #用于启动容器
需要下载的二进制文件
请从以下地址下载对应架构的飞网二进制文件并放到合适的目录:
- linux_386 架构:
- linux_amd64 架构:
- linux_arm 架构:
- linux_arm64 架构:
2. 构建容器镜像
Dockerfile文件
用来定义这个镜像怎么构建,包括安装 Nginx、拷贝配置文件和启动脚本等。
# 第一阶段:准备 gmzta 二进制文件(可自定义构建架构)
FROM alpine:3.18 AS builder
WORKDIR /build
RUN apk add --no-cache wget
RUN mkdir -p linux_amd64 && \
wget -O linux_amd64/gmzta https://pkgs.gmzta.com/docker/linux_amd64/gmzta && \
wget -O linux_amd64/gmztad https://pkgs.gmzta.com/docker/linux_amd64/gmztad && \
wget -O linux_amd64/gmztaenv https://pkgs.gmzta.com/docker/linux_amd64/gmztaenv && \
wget -O linux_amd64/gmzta-nginx-connector https://pkgs.gmzta.com/docker/linux_amd64/gmzta-nginx-connector
RUN chmod +x linux_amd64/*
# 第二阶段:基于 nginx:latest
FROM nginx:latest
# 安装 gmzta 所需的依赖
RUN apt-get update && apt-get install -y \
ca-certificates \
iptables \
iproute2 \
iputils-ping \
&& rm -rf /var/lib/apt/lists/*
# 复制 gmzta 二进制文件
COPY --from=builder /build/linux_amd64/* /usr/bin/
COPY ./nginx.conf /etc/nginx/nginx.conf
# 复制启动脚本
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
# 使用启动脚本
ENTRYPOINT ["/entrypoint.sh"]
entrypoint.sh文件
容器启动时执行的脚本,用来启动飞网、Nginx 和 gmzta-nginx-connector。
#!/bin/bash
# 确保 /run/gmzta 目录存在并设置权限
mkdir -p /run/gmzta
chown nginx:nginx /run/gmzta
chmod 755 /run/gmzta
#启动nginx
echo "Starting nginx..."
nginx -g "daemon off;" >> /var/log/nginx.log 2>&1 &
# 启动 gmztaenv
echo "Starting gmztaenv..."
/usr/bin/gmztaenv >> /var/log/gmztaenv.log 2>&1 &
gmztaenv_pid=$!
# 启动 gmzta-nginx-connector
SOCK_PATH="/var/run/gmzta-nginx-connector.sock"
echo "Starting gmzta-nginx-connector on $SOCK_PATH..."
# 移除旧的 socket 文件(与 gmzta-nginx-connector 内部逻辑一致)
rm -f "$SOCK_PATH"
/usr/bin/gmzta-nginx-connector --sockpath="$SOCK_PATH" >> /var/log/gmzta-nginx-connector.log 2>&1 &
gmzta_nginx_pid=$!
# 等待 gmzta-nginx-connector 创建 socket,最多 10 秒
TIMEOUT=10
WAITED=0
echo "Waiting for $SOCK_PATH to appear (max ${TIMEOUT}s)..."
while [ ! -S "$SOCK_PATH" ] && [ "$WAITED" -lt "$TIMEOUT" ]; do
sleep 1
WAITED=$((WAITED + 1))
echo " Still waiting... (${WAITED}s)"
done
# 判断是否存在 socket 文件
if [ -S "$SOCK_PATH" ]; then
echo "Socket $SOCK_PATH found."
# 循环修改 socket 权限,直到 gmzta-nginx-connector 退出
while kill -0 $gmzta_nginx_pid 2>/dev/null; do
chown nginx:nginx "$SOCK_PATH"
chmod 660 "$SOCK_PATH"
sleep 1
done
echo "gmzta-nginx-connector has exited."
else
echo "Timeout: $SOCK_PATH not found after ${TIMEOUT}s. Exiting."
exit 1
fi
# 等待 gmztaenv 进程(保持容器运行)
wait $gmztaenv_pid
nginx.conf
定义了 Nginx 的全局行为。
user root;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type text/plain;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
gzip on;
include /etc/nginx/conf.d/*.conf;
}
构建镜像:在包含 Dockerfile 的目录下运行以下命令构建镜像:
docker build -t my-gmzta-nginx-container:latest .
3.启动容器
配置nginx转发规则
此文件用于配置nginx,将指定端口的内容转发到gmzta-nginx-connector 进行认证。
vi default-nginx.conf
server {
listen 80; # 在 80 端口监听 HTTP 请求
server_name example.com; # 指定服务的域名为 example.com
error_log /var/log/nginx/error.log debug; # 设置错误日志文件,级别为 debug
access_log /var/log/nginx/access.log; # 设置访问日志文件
location /auth {
internal; # 该路径只能由 Nginx 内部请求访问,外部无法直接访问
proxy_pass http://unix:/var/run/gmzta.nginx-connector.sock; # 转发到 Unix socket 的后端认证服务
proxy_pass_request_body off; # 不转发请求体,认证只需请求头
proxy_set_header Host $http_host; # 传递原始 Host 头
proxy_set_header Remote-Addr $remote_addr; # 客户端 IP
proxy_set_header Remote-Port $remote_port; # 客户端端口
proxy_set_header Original-URI $request_uri; # 原始请求的 URI
proxy_hide_header Content-Type; # 隐藏后端返回的 Content-Type 头部
add_header Content-Type 'text/plain'; # 强制设置返回的 Content-Type 为 text/plain
limit_except GET HEAD { # 限制请求方法,只允许 GET 和 HEAD
deny all; # 其他方法全部拒绝
}
}
location / {
satisfy any; # 满足任意一条访问控制规则即可(不过这里只有 deny all)
deny all; # 默认拒绝所有请求(除非通过 auth_request 授权)
auth_request /auth; # 发起子请求到 /auth 路径进行用户认证
# 从 /auth 返回的响应头中提取用户信息
auth_request_set $auth_user $upstream_http_gmzta_user;
auth_request_set $auth_name $upstream_http_gmzta_name;
auth_request_set $auth_login $upstream_http_gmzta_login;
auth_request_set $auth_gmztanet $upstream_http_gmzta_gmztanet;
auth_request_set $auth_profile_picture $upstream_http_gmzta_profile_picture;
# 将认证信息通过自定义 header 转发给后端服务
proxy_set_header X-Webauth-GmztaUser "$auth_user";
proxy_set_header X-Webauth-GmztaName "$auth_name";
proxy_set_header X-Webauth-GmztaLogin "$auth_login";
proxy_set_header X-Webauth-GmztaNet "$auth_gmztanet";
proxy_set_header X-Webauth-Gmzta-Profile-Picture "$auth_profile_picture";
proxy_pass http://172.26.0.1:8080; # 转发请求到内网的后端服务
proxy_http_version 1.1; # 使用 HTTP 1.1(支持 keep-alive 等特性)
proxy_intercept_errors on; # 允许自定义错误页面(可用于处理认证失败等情况)
default_type text/plain; # 设置默认响应类型为 text/plain
}
}
docker 方式启动
请参考此配置按需调整启动参数。
docker run -d \
--name=gmzta-docker \
-v /var/lib:/var/lib \
-v /dev/net/tun:/dev/net/tun \
--env GM_TOKEN=gmzta-authkey-123-456789abcdef \
--env GM_TUN=false \
--env GM_CONFIG_DIR=/var/lib/gmzta \
-p 80:80 \
-v $(pwd)/my-gmzta-nginx-container/conf:/var/lib/gmzta \
-v $(pwd)/default-nginx.conf:/etc/nginx/conf.d/default-nginx.conf \
my-gmzta-nginx-container:latest
docker compose 方式启动
请参考此配置按需调整启动参数。
services:
gmzta-docker:
image: my-gmzta-nginx-container:latest
container_name: my-gmzta-nginx-container
hostname: my-gmzta-nginx-container
ports:
- 80:80
environment:
- GM_TOKEN=gmzta-authkey-123-456789abcdef # 替换授权密钥
- GM_CONFIG_DIR=/var/lib/gmzta
- GM_TUN=false # 禁用 TUN 模式(即启用 Gvisor 模式)
volumes:
- ${PWD}/my-gmzta-nginx-container/conf:/var/lib/gmzta
- ${PWD}/default-nginx.conf:/etc/nginx/conf.d/default-nginx.conf
restart: unless-stopped # 设置容器重启策略,除非手动停止,否则始终尝试重启