如何捕获容器日志并上传到 GitHub Actions Artifact?
解读
在国内 CouchDB 面试场景里,这道题表面问“日志收集”,实则考察候选人是否能把 容器化 CouchDB 的运维可观测性 与 CI/CD 流水线 打通。面试官想确认三件事:
- 你是否知道 CouchDB 在容器里日志到底写在哪、怎么不丢;
- 你是否熟悉 GitHub Actions 在中国网络环境下的缓存与 Artifact 限速痛点;
- 你能否把“日志捕获→压缩→上传”做成幂等、可回溯、低成本的闭环,而不是临时 docker logs 一把梭。
知识点
- CouchDB 日志双通道:/opt/couchdb/var/log/couchdb/*.log 与 docker stdout/stderr,二者格式不同,需分别处理。
- GitHub Actions 国内限速:upload-artifact 走 Azure Blob,华北/华东 Runner 无代理时单文件 >1 GB 易 502,需提前 gzip 并分片。
- 容器生命周期钩子:docker kill -s SIGTERM 后 CouchDB 有 30 s grace period,务必在 ENTRYPOINT 脚本里 trap SIGTERM 把缓冲区刷到磁盘再退出,否则日志截断。
- Artifact 保留策略:公有仓库 90 天自动清理,面试时要主动说“保留周期与合规”——国内金融客户常要求 180 天,可额外推送到 OSS/S3 做二级备份。
- 敏感信息脱敏:couchdb.log 里可能带 _users 密码哈希,上传前用 sed -E ‘s/"password":"[^"]+"/"password":"*"/g’ 做正则脱敏**,否则 Artifact 公开后等于裸奔。
答案
给出一套可直接落地的 GitHub Actions 片段,兼顾国内网络与 CouchDB 特性:
name: capture-couch-logs
on:
workflow_dispatch: # 手工触发,也可改成 on-failure
schedule:
- cron: '0 2 * * *' # 每天凌晨 2 点兜底收集
env:
COUCH_TAG: 3.3.2
ARTIFACT_RETENTION: 15 # 公有仓库节省配额,私有仓可 90
jobs:
logs:
runs-on: ubuntu-22.04
steps:
- name: 启动 CouchDB 容器并挂载日志卷
run: |
docker volume create couch_logs
docker run -d --name couch \
-e COUCHDB_USER=admin \
-e COUCHDB_PASSWORD= ${{ secrets.COUCH_PWD }} \
-v couch_logs:/opt/couchdb/var/log/couchdb \
-p 5984:5984 \
couchdb:${{ env.COUCH_TAG }}
- name: 等待节点就绪
run: |
for i in {1..30}; do
curl -sS -u admin:${{ secrets.COUCH_PWD }} http://localhost:5984/ && break
sleep 2
done
- name: 制造一点访问日志(可选)
run: |
curl -u admin:${{ secrets.COUCH_PWD }} -X PUT http://localhost:5984/iot
curl -u admin:${{ secrets.COUCH_PWD }} -X POST http://localhost:5984/iot -d '{"temp":24}'
- name: 优雅停容器,触发日志刷盘
run: |
docker stop --time=30 couch # 30 s grace period
docker logs couch > /tmp/docker-stdout.log 2>&1
- name: 脱敏 & 打包
run: |
sed -E 's/"password":"[^"]+"/"password":"***"/g' \
/var/lib/docker/volumes/couch_logs/_data/couchdb.log \
> /tmp/couchdb-sanitized.log
tar -czf /tmp/couch-logs-$(date +%Y%m%d-%H%M).tar.gz \
-C /tmp docker-stdout.log couchdb-sanitized.log
- name: 上传到 Artifact
uses: actions/upload-artifact@v4
with:
name: couch-logs-${{ github.run_number }}
path: /tmp/couch-logs-*.tar.gz
retention-days: ${{ env.ARTIFACT_RETENTION }}
关键点解释
- 用 docker volume 把 CouchDB 内部日志目录挂出来,避免容器删除即丢失。
- docker stop --time=30 保证 CouchDB 收到 SIGTERM 后把缓冲区日志写盘,防止截断。
- sed 脱敏 是国内合规硬要求,面试时主动提到会加分。
- 先 tar.gz 再 upload,把体积压到原来 10 % 以下,解决国内上传大文件 502 问题。
- retention-days 显式声明,体现成本意识。
拓展思考
- 如果集群有 5 个 CouchDB 节点,Artifact 文件名需带 节点序号与容器 ID 前 6 位,否则并行上传会覆盖。
- 对金融级场景,仅靠 GitHub Artifact 不够,可在同一步骤里加 aliyun-oss-sync,走内网上传,实现“双轨保留”。
- 日志里若开启 debug=info,体积会暴涨,考虑在 CI 里动态降级:
curl -X PUT http://admin:pwd@localhost:5984/_node/_local/_config/log/level -d '"warning"'
采集完再调回 error,既省空间又避免重启容器。 - 国内私有 Runner 若用 k8s+hostPath,记得给 Pod 加 preStop hook,同样 trap SIGTERM,保持与 Docker 方案一致。