Apache Traffic Server 10.2.0 Docker Compose 部署指南
本文讲解以 Docker Compose 部署 Traffic Server 10.2.0:官方镜像与自建 Dockerfile 路线选型、编排样例、缓存卷与配置持久化、等价 docker run 与运维命令,流程经真实部署验证。
Apache Traffic Server 10.2.0 Docker Compose 部署指南
一、环境信息
| 项目 | 内容 |
|---|---|
| 组件版本 | Apache Traffic Server 10.2.0 |
| 宿主系统 | Linux x86_64(实测 Ubuntu 22.04 基座) |
| Docker 版本 | 29.8.0(实测版本,24 及以上均可) |
| Compose 版本 | v5.5.1(实测版本,v2.x 起语法兼容) |
| 服务端口 | 容器内 8080(HTTP 代理) |
| 配置目录 | /usr/local/etc/trafficserver(自建镜像) |
| 缓存目录 | /usr/local/var/trafficserver(自建镜像) |
二、镜像选型说明
2.1 两条路线对比
| 对比项 | 官方镜像 apache/trafficserver | 自建镜像(本文实测主线) |
|---|---|---|
| 获取方式 | Docker Hub 拉取 | Dockerfile 从官方源码构建 |
| 版本 | 10.2.0 等官方 tag | 任意官方发行版本 |
| 安装前缀 | /usr/local | /usr/local(与本文一致) |
| 网络依赖 | 需要 Docker Hub 可达 | 仅需 downloads.apache.org 可达 |
| 定制性 | 无法改编译参数 | 可加插件、关闭测试目标、选 OpenSSL 版本 |
实测提示:部分受限网络环境下 Docker Hub 的 apache/trafficserver 命名空间拉取会被 registry 代理拒绝(实测 docker pull apache/trafficserver:10.2.0 返回 denied),此时自建镜像是唯一可行路线;本文全部编排与命令以自建镜像实测通过为准,官方镜像用法在其可直接拉取的环境下等价适用。
2.2 自建 Dockerfile(实测通过版本,产物 703MB)
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential cmake libssl-dev libpcre2-dev libcap-dev libhwloc-dev \
libcurl4-openssl-dev tcl-dev zlib1g-dev bison flex libbrotli-dev liblzma-dev \
libluajit-5.1-dev pkg-config \
curl ca-certificates && rm -rf /var/lib/apt/lists/*
RUN mkdir -p /usr/local/src \
&& curl -fL https://downloads.apache.org/trafficserver/trafficserver-10.2.0.tar.bz2 -o /tmp/ats.tar.bz2 \
&& tar xjf /tmp/ats.tar.bz2 -C /usr/local/src \
&& cd /usr/local/src/trafficserver-10.2.0 \
&& cmake -B build -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release -DBUILD_REGRESSION_TESTING=OFF \
&& cmake --build build -j"$(nproc)" && cmake --install build \
&& rm -rf /usr/local/src /tmp/ats.tar.bz2
RUN useradd -r -s /usr/sbin/nologin ats \
&& mkdir -p /usr/local/var/trafficserver /usr/local/var/log/trafficserver \
&& chown -R ats:ats /usr/local/var
USER ats
EXPOSE 8080
ENTRYPOINT ["/usr/local/bin/traffic_server"]
构建要点(均为实测踩坑结论):
- pkg-config 与 libpcre2-dev 是 CMake 配置必需项,缺 pkg-config 报 Could NOT find PkgConfig,缺 PCRE2 报 No package 'libpcre2-8'。
- libluajit-5.1-dev 缺失时 CMake 的 luajit 自动探测直接报错终止,必须安装。
- BUILD_REGRESSION_TESTING=OFF 跳过单元测试编译,12 核实测构建时间从约 20 分钟降到 10 分钟左右,镜像体积从 2.1GB 级降到 703MB。
- 运行用户 ats 通过 USER 指令固定,非 root 启动时 ATS 日志确认 Traffic Server is running unprivileged。
构建镜像:
docker build -t ats-selfbuilt:10.2.0 .
三、前置条件
- 宿主机已安装 Docker 与 Compose 插件:
docker version --format '{{.Server.Version}}'
docker compose version
Docker Compose version v5.5.1
-
镜像就绪:官方环境直接 docker pull apache/trafficserver:10.2.0;受限环境先完成上节自建构建。
-
宿主机 8080 端口空闲:
ss -lnt | grep 8080 || echo '端口空闲'
- 创建部署目录与配置文件:
mkdir -p /opt/ats-compose/conf && cd /opt/ats-compose
四、部署步骤
4.1 准备配置文件
写反向代理映射(conf/remap.config):
printf 'map / http://example.com/\n' > conf/remap.config
写缓存存储(conf/storage.config,路径指向容器内挂载的命名卷):
printf '/usr/local/var/trafficserver 256M\n' > conf/storage.config
4.2 编写 docker-compose.yml
services:
trafficserver:
image: ats-selfbuilt:10.2.0
container_name: trafficserver
ports:
- "8080:8080"
volumes:
- ./conf/remap.config:/usr/local/etc/trafficserver/remap.config:ro
- ./conf/storage.config:/usr/local/etc/trafficserver/storage.config:ro
- cache-data:/usr/local/var/trafficserver
ulimits:
nofile:
soft: 131072
hard: 131072
restart: unless-stopped
healthcheck:
test: ["CMD", "/usr/local/bin/traffic_ctl", "server", "status"]
interval: 30s
timeout: 10s
retries: 3
start_period: 20s
volumes:
cache-data:
设计说明:
- 配置文件以只读方式挂载,容器内以 ats 用户运行无法也无需改写配置,变更走宿主机改文件加重启。
- cache-data 命名卷承载缓存文件,容器重建不丢缓存。
- healthcheck 用容器内 traffic_ctl 探测 JSONRPC,比 TCP 探测更能反映服务真实可用性。
- nofile 131072 匹配高并发连接需求。
4.3 启动服务
cd /opt/ats-compose && docker compose up -d
Container trafficserver Started
查看状态(实测启动约 10 秒后转为 healthy):
docker compose ps
NAME IMAGE STATUS
trafficserver ats-selfbuilt:10.2.0 Up 12 seconds (healthy)
4.4 启动验证
请求验证代理链路(宿主机或容器内均可):
curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://127.0.0.1:8080/
HTTP 200
第二次请求确认缓存生效:
curl -sI http://127.0.0.1:8080/ | grep -E '^Age|^Server'
Age: 2
Server: ATS/10.2.0
容器内确认缓存文件与指标:
docker exec trafficserver ls -lh /usr/local/var/trafficserver/cache.db
-rw-r--r-- 1 ats ats 256M Oct 12 07:11 /usr/local/var/trafficserver/cache.db
docker exec trafficserver /usr/local/bin/traffic_ctl metric get proxy.process.http.incoming_requests
proxy.process.http.incoming_requests 1
查看启动日志:
docker compose logs --tail 5 trafficserver
trafficserver | [Oct 12 07:10:10.804] traffic_server NOTE: records parsing completed.
trafficserver | [Oct 12 07:10:10.804] traffic_server NOTE: /usr/local/etc/trafficserver/records.yaml finished loading
trafficserver | [Oct 12 07:10:10.805] traffic_server NOTE: Traffic Server is running unprivileged, not switching to user 'nobody'
五、数据持久化说明
| 数据 | 容器内路径 | 持久化方式 | 说明 |
|---|---|---|---|
| 缓存 | /usr/local/var/trafficserver | 命名卷 cache-data | cache.db 落卷,容器删除重建不丢;compose down 不删卷 |
| remap 规则 | /usr/local/etc/trafficserver/remap.config | bind 挂载(只读) | 宿主机单文件维护 |
| 存储定义 | /usr/local/etc/trafficserver/storage.config | bind 挂载(只读) | 路径必须指向卷内挂载点 |
| 运行时锁与 socket | /usr/local/var/trafficserver | 随缓存卷 | server.lock 与 jsonrpc20.sock 落在卷内 |
| 日志 | /usr/local/var/log/trafficserver | 可选 bind 挂载 | 默认随容器,采集接入时挂出到宿主机 |
实测结论:docker compose down 后命名卷 cache-data 依然保留(docker volume ls 可见 ats-compose_cache-data),缓存命中数据跨生命周期存活;要彻底重建缓存执行 docker compose down -v。
六、常用环境变量表
容器内 ATS 相关环境变量:
| 变量 | 示例值 | 作用 |
|---|---|---|
| TS_RUNROOT | /usr/local | 指定 traffic_server 运行根(runroot 沙箱),多实例隔离时设置;单实例默认免设 |
Compose 层变量(写入 .env 文件供 docker-compose.yml 引用):
| 变量 | 示例值 | 用途 |
|---|---|---|
| ATS_IMAGE | ats-selfbuilt:10.2.0 | 镜像与版本 |
| ATS_HTTP_PORT | 8080 | 宿主机对外端口 |
| ATS_CACHE_SIZE | 256M | 缓存大小,渲染进 storage.config |
| ATS_CACHE_VOL | cache-data | 缓存命名卷名 |
使用 .env 后 docker-compose.yml 的 image 写为 ${ATS_IMAGE},ports 写为 "${ATS_HTTP_PORT}:8080"。生成 .env:
printf 'ATS_IMAGE=ats-selfbuilt:10.2.0\nATS_HTTP_PORT=8080\n' > .env
说明:官方与自建镜像均无强制的启动环境变量,配置全部经文件挂载;TS_RUNROOT 仅在单容器多进程或特殊路径需求时使用。
七、常用配置参数说明
容器内主配置为 /usr/local/etc/trafficserver/records.yaml(YAML 格式)。部署中最常调整的参数:
| 参数(点分名) | YAML 片段 | 默认值 | 容器场景建议 |
|---|---|---|---|
| proxy.config.http.server_ports | http.server_ports | 8080 8080:ipv6 | 容器内保持 8080,由端口映射控制对外端口 |
| proxy.config.http.insert_response_via_str | http.insert_response_via_str | 0 | 调试期设 1 便于观察命中 |
| proxy.config.url_remap.remap_required | url_remap.remap_required | 1 | 反向代理保持 1 |
| proxy.config.cache.ram_cache.size | cache.ram_cache.size | -1 | 按容器内存限制设定,避免 OOM |
| proxy.config.net.connections_throttle | net.connections_throttle | 30000 | 与 nofile 与宿主负载匹配 |
因 records.yaml 未被挂载时可进入容器查看默认值:
docker exec trafficserver cat /usr/local/etc/trafficserver/records.yaml | head -20
需要整体定制时把 records.yaml 也加入只读挂载列表,宿主机维护一份完整配置。修改挂载的配置后重启容器生效:
docker compose restart trafficserver
storage.config 变更(缓存扩容)同样重启生效,路径必须落在挂载卷内,实测改为 512M 后 cache.db 重新初始化为 536870912 字节。
八、配置文件持久化
推荐目录结构(宿主机):
/opt/ats-compose/
├── docker-compose.yml
├── .env
└── conf/
├── records.yaml
├── remap.config
└── storage.config
对应卷声明(在第四节基础上追加 records.yaml):
volumes:
- ./conf/records.yaml:/usr/local/etc/trafficserver/records.yaml:ro
- ./conf/remap.config:/usr/local/etc/trafficserver/remap.config:ro
- ./conf/storage.config:/usr/local/etc/trafficserver/storage.config:ro
- cache-data:/usr/local/var/trafficserver
持久化校验方法:修改宿主机 conf/remap.config 后重启,确认新规则生效:
docker compose restart trafficserver
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/
配置文件模板从镜像导出(首次部署前取默认副本到宿主机):
docker run --rm --entrypoint cat ats-selfbuilt:10.2.0 /usr/local/etc/trafficserver/records.yaml > conf/records.yaml
九、等价 docker run 运行方式
不使用 Compose 时,以下命令与上文编排等价:
docker run -d --name trafficserver \
-p 8080:8080 \
--ulimit nofile=131072:131072 \
--restart unless-stopped \
-v /opt/ats-compose/conf/remap.config:/usr/local/etc/trafficserver/remap.config:ro \
-v /opt/ats-compose/conf/storage.config:/usr/local/etc/trafficserver/storage.config:ro \
-v ats-cache:/usr/local/var/trafficserver \
ats-selfbuilt:10.2.0
清理等价命令:
docker rm -f trafficserver
docker volume rm ats-cache
使用官方镜像环境下的等价运行方式(镜像可直接拉取时):
docker run -d --name trafficserver \
-p 8080:8080 \
--ulimit nofile=131072:131072 \
apache/trafficserver:10.2.0
官方镜像的配置路径同为 /usr/local 前缀,挂载方式一致;如使用其他第三方镜像,先确认其 ENTRYPOINT 与配置前缀再挂载。
十、常用运维命令
状态与日志:
docker compose ps
docker compose logs -f --tail 100 trafficserver
docker stats trafficserver --no-stream
进入容器运维(traffic_ctl 全套可用):
docker exec -it trafficserver /usr/local/bin/traffic_ctl server status
docker exec -it trafficserver /usr/local/bin/traffic_ctl config diff
docker exec -it trafficserver /usr/local/bin/traffic_ctl metric get proxy.process.http.incoming_requests
在线重载配置(宿主机改完挂载文件后):
docker exec trafficserver /usr/local/bin/traffic_ctl config reload
重启与停止:
docker compose restart trafficserver
docker compose down
彻底重建(含缓存数据,谨慎):
docker compose down -v
镜像与容器信息查看:
docker inspect trafficserver --format '{{.State.Health.Status}}'
healthy
十一、常见问题
Q1:容器反复重启,日志报 lockfile Permission denied?
以 root 启动时 ATS 自动切换 nobody,而镜像内运行目录属主不匹配导致锁文件无法创建。自建镜像已用 USER ats 规避;若镜像以 root 启动,把 entrypoint 改为自愈写法(实测通过):
entrypoint: ["/bin/sh", "-c", "mkdir -p /usr/local/var/trafficserver /usr/local/var/log/trafficserver && chown -R 65534:65534 /usr/local/var/trafficserver /usr/local/var/log/trafficserver && rm -f /usr/local/var/trafficserver/server.lock /usr/local/var/trafficserver/jsonrpc20.sock && exec /usr/local/bin/traffic_server"]
Q2:healthcheck 一直 unhealthy,traffic_ctl 报 RPC Node Error?
进程异常退出后 jsonrpc20.sock 残留,healthcheck 的 traffic_ctl 连不上。按 Q1 的 entrypoint 自愈写法在启动前清理 socket 文件,或手动清理后重启:
docker exec trafficserver sh -c 'rm -f /usr/local/var/trafficserver/jsonrpc20.sock /usr/local/var/trafficserver/jsonrpc20.lock'
docker compose restart trafficserver
Q3:docker pull apache/trafficserver 报 denied?
受 registry 代理或镜像仓库访问策略限制(实测部分网络环境该命名空间整体 denied)。改走本文第二节的自建 Dockerfile 路线,产物功能等价。
Q4:启动报 Address already in use 但容器内没有进程?
宿主机端口被其他进程占用,或上一个容器处于优雅排空未完全退出。确认宿主机 8080 占用并更换映射端口:
ss -lntp | grep 8080
docker rm -f trafficserver
docker compose up -d
Q5:容器内没有 curl 怎么验证服务?
镜像为瘦身未装 curl 时用 wget 或宿主机请求映射端口:
docker exec trafficserver wget -qO- -T 10 http://127.0.0.1:8080/ | head -c 80
Q6:用 docker commit 生成的镜像 compose 起不来或跑起的是 systemd?
commit 自带原容器配置,若源容器 CMD 是 /sbin/init,则新镜像默认仍执行 init 而非 traffic_server。在 compose 中显式覆盖:
entrypoint: ["/usr/local/bin/traffic_server"]
十二、参考链接
- Docker Compose 官方文档:https://docs.docker.com/compose/
- Apache Traffic Server 官方镜像页:https://hub.docker.com/r/apache/trafficserver
- ATS 官方 Docker 构建资料(源码 contrib 目录):https://github.com/apache/trafficserver
- records.yaml 参数参考:https://docs.trafficserver.apache.org/en/latest/admin-guide/files/records.yaml.en.html
- storage.config 参考:https://docs.trafficserver.apache.org/en/latest/admin-guide/files/storage.config.en.html
- ATS 运行与监控文档:https://docs.trafficserver.apache.org/en/latest/admin-guide/monitoring/traffic_ctl.en.html