ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Docker容器化部署PDF翻译工具:从Dockerfile到docker-compose

2026/8/14 4:54:51 拓冰建站 浏览量
Docker容器化部署PDF翻译工具:从Dockerfile到docker-compose

前言

之前写了几篇 PDF 批量翻译的脚本文章,有不少读者反馈:在自己机器上能跑,但部署到团队内部的 Windows/Mac 同事机器上,环境配置成了大问题——Python 版本不一致、依赖库冲突、代理配置麻烦。

最终的解决方案是 Docker。把整个翻译链路封装成镜像,任何拉取镜像的人docker run一行就能用。

本文以"PDF 翻译工具的自托管部署"为例,完整走一遍:

  1. 写 Dockerfile
  2. 写 docker-compose 多服务编排
  3. 处理跨平台镜像构建
  4. 实战中常见的几个坑

环境准备

  • Docker 24+
  • docker-compose v2+
  • 目标镜像基础:FROM python:3.11-slim

一、为什么这个场景适合 Docker 化

PDF 翻译场景有几个特点,天然适合 Docker:

  • 无状态:任务调度、上传、下载,所有数据可外部化
  • 依赖固定:Python + requests + tqdm + pdfplumber,几乎不变
  • 可水平扩展:并发任务,只需多开容器实例

Docker 化能给团队带来的核心好处:

  • 新员工入职 5 分钟上手(只需拉镜像)
  • 屏蔽各机器环境的差异(Windows、Mac、Linux)
  • CI/CD 流水线直接用同一镜像部署

二、Step 1: 写一个基础的 Dockerfile

先给一个能用的最小版本:

# 基础镜像 FROM python:3.11-slim # 设置工作目录 WORKDIR /app # 系统依赖(用于 pdfplumber / pdftotext 等) RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ libpoppler-cpp-dev \ && rm -rf /var/lib/apt/lists/* # 先复制 requirements 单独一层,利用 Docker 缓存 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 应用代码 COPY app/ ./app/ COPY translate_cli.py . # 入口 ENTRYPOINT ["python", "translate_cli.py"] CMD ["--help"]

requirements.txt:

requests>=2.31.0 tqdm>=4.66.0 pdfplumber>=0.10.0 click>=8.1.0

关键技巧:把requirements.txt单独 COPY 一次,利用 Docker 的层缓存。后续只改app/目录时,不会重装依赖,构建快很多。

构建并验证

dockerbuild-tpdf-translator:1.0.dockerrun--rmpdf-translator:1.0--help

三、Step 2: 多阶段构建优化镜像大小

上面的镜像大约 800MB,因为带了 gcc 编译工具。可以改用多阶段构建,把构建期依赖留在第一阶段,运行时只保留必要文件:

# ===== 阶段 1:构建依赖 ===== FROM python:3.11-slim AS builder WORKDIR /build RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ libpoppler-cpp-dev \ && rm -rf /var/lib/apt/lists/* COPY requirements.txt . RUN pip install --no-cache-dir --target=/build/deps -r requirements.txt # ===== 阶段 2:运行时镜像 ===== FROM python:3.11-slim WORKDIR /app RUN apt-get update && apt-get install -y --no-install-recommends \ libpoppler-cpp-dev \ && rm -rf /var/lib/apt/lists/* # 复制依赖 COPY --from=builder /build/deps /usr/local/lib/python3.11/site-packages COPY app/ ./app/ COPY translate_cli.py . ENTRYPOINT ["python", "translate_cli.py"] CMD ["--help"]

这样构建出来的镜像约 380MB,瘦了 50%。对生产部署来说,镜像大小直接关系到拉取和启动速度。

四、Step 3: docker-compose 多服务编排

实际部署时,通常需要多个服务:

  • api:HTTP 接口
  • worker:异步翻译任务消费者(可选 Celery)
  • redis:任务队列
  • monitor:日志聚合(可选 ELK)

docker-compose.yml:

version:"3.9"services:api:build:context:.dockerfile:Dockerfileimage:pdf-translator:1.0container_name:pdf-translator-apicommand:["python","app/server.py","--host","0.0.0.0","--port","8000"]ports:-"8000:8000"environment:-API_KEY=${API_KEY}-REDIS_URL=redis://redis:6379/0-LOG_LEVEL=INFOvolumes:-./uploads:/app/uploads-./outputs:/app/outputsdepends_on:redis:condition:service_healthyrestart:unless-stoppedhealthcheck:test:["CMD","curl","-f","http://localhost:8000/health"]interval:30stimeout:10sretries:3redis:image:redis:7-alpinecontainer_name:pdf-translator-redisports:-"6379:6379"volumes:-redis-data:/datahealthcheck:test:["CMD","redis-cli","ping"]interval:10stimeout:5sretries:3worker:image:pdf-translator:1.0container_name:pdf-translator-workercommand:["python","app/worker.py"]environment:-API_KEY=${API_KEY}-REDIS_URL=redis://redis:6379/0volumes:-./uploads:/app/uploads-./outputs:/app/outputsdepends_on:-api-redisrestart:unless-stoppeddeploy:replicas:2# 水平扩展 2 个 workervolumes:redis-data:

启动:

docker-composeup-ddocker-composelogs-fapi

五、Step 4: 跨平台镜像构建(踩坑重点)

如果你团队既有 Mac 又有 Windows + Linux 服务器,跨平台镜像是个常见痛点。

方案 A: 一次性构建多平台镜像

dockerbuildx create--usedockerbuildx build\--platformlinux/amd64,linux/arm64\-tpdf-translator:1.0\--push.

注意:--push会推到你配置的 registry。Mac M1 (ARM64) 构建的镜像在 x86 服务器上跑,必须用linux/amd64显式指定。

方案 B: 使用 manifest 镜像(可选)

如果你的镜像要分发到内网多台不同架构的机器,可以创建 manifest list:

dockermanifest create pdf-translator:1.0\your-registry/pdf-translator:1.0-amd64\your-registry/pdf-translator:1.0-arm64dockermanifest push pdf-translator:1.0

六、实战中常见的几个坑

坑 1: 文件中文名编码问题

Docker for Windows + WSL 2 的中文文件名,有时会变成乱码。强烈建议:

  • Docker 内部统一使用 UTF-8
  • 容器 ENV 设置:
    ENV LANG=C.UTF-8 \ LC_ALL=C.UTF-8 \ PYTHONIOENCODING=utf-8

坑 2: 时区不一致

容器默认 UTC,日志时间会差 8 小时:

ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

或者在 docker-compose 用environment:

environment:-TZ=Asia/Shanghai

坑 3: 容器重启丢日志

容器默认日志写到 stdout,但宿主机没有持久化。建议:

  • loggingdriver + 集中日志服务(Loki/ELK)
  • 或者挂载/var/log目录
services:api:logging:driver:"json-file"options:max-size:"10m"max-file:"3"

坑 4: 代理配置

如果你的服务器需要通过代理访问外网(很多办公网是这样),Docker 构建时常常遇到:

# 构建期代理 ENV HTTP_PROXY=http://your-proxy:7897 \ HTTPS_PROXY=http://your-proxy:7897

运行时通过环境变量注入:

services:api:environment:-HTTP_PROXY=http://host.docker.internal:7897

注意:Windows + Docker Desktop 场景下,宿主机代理地址用host.docker.internal而不是127.0.0.1(容器内 127.0.0.1 是容器自己)。

七、生产化部署 checklist

上线前自检:

  • 镜像版本 tag 写具体版本号,不用latest
  • healthcheck 写好,k8s/docker-compose 都看得到
  • 日志结构化输出(JSON 格式)
  • API Key 通过 secret 管理,不写在镜像里
  • volumes 持久化数据(上传文件、翻译结果)
  • 镜像定期扫描漏洞(docker scan)
  • 资源限制加好(memory / cpu limit)
services:api:deploy:resources:limits:memory:1Gcpus:"1.0"

八、回顾与下一步

到这里,我们已经:

  • 写了基础 Dockerfile 和多阶段构建版本
  • 用 docker-compose 编排了多服务
  • 处理了跨平台构建
  • 解决了几个常见的中文路径、时区、代理坑

接下来还可以做

  1. 接入 GitHub Actions 自动构建镜像
  2. 用 Kubernetes 部署 docker-compose(kompose 工具转译)
  3. 接入 Prometheus + Grafana 做监控
  4. 镜像推送到 Harbor 自建仓库

总结

Docker 不只是"换个环境跑",更是把运维复杂度从团队每个人身上,集中到镜像里。一次构建,全员可用。这就是工程化的价值。

后续如果有时间,会写一篇"Kubernetes 部署 PDF 翻译服务"的进阶文章,敬请期待。


标签:Docker、Python、容器化、PDF翻译、DevOps