
近两年凡是写过毕业论文章节或者投过期刊的人多少都被 LaTeX 编译环境折磨过。装一个完整的 TeX Live 动辄几个 GB升级一个宏包可能要全局重来换一台电脑环境又得从头收拾一遍。更不用说同一份文档在不同机器上编译出来的效果可能完全不一样。我也在这种反复折腾里耗了不少时间后来决定彻底换个思路把 TeX Live 装进 Docker 里。这个方案我现在用了很长时间实际体验稳定、干净还能和 VS Code 无缝配合顺着模板改改就能出 PDF。这篇内容就把我搭建这套 LaTeX 编译平台的完整过程、踩过的坑和优化细节一次性讲清楚。Docker 部署 TeX Live轻松搭建 LaTeX 论文排版编译平台1. 为什么用 Docker 装 LaTeX本地安装的坑有多深1.1 本地安装的典型痛点先聊聊本地安装 TeX Live 到底哪里让人抓狂。第一是体积和安装时间。完整的 TeX Live 套装接近 4 GB即便只装 scheme-small 或 scheme-medium也动不动就是几百 MB 起步。网络稍微不稳下载过程直接劝退。安装完毕后系统里多出一堆二进制文件、字体、宏包想卸载还不一定能清理干净。第二是版本管理混乱。写作时经常遇到这种情况A 论文用到了某个宏包的新特性B 模板却因为宏包版本太新而编译报错。如果只有一个全局 TeX Live就只能反复升级或者降级宏包一来二去系统环境就被改乱了。第三是跨平台和跨机器的行为不一致。同一份文档在 Windows 上编译没问题到了 macOS 上字体路径不同、行距略有差异最终 PDF 的排版细节对不上投稿时就容易出问题。我自己还碰到过一个很典型的问题系统里之前装过某个旧版 CTeX 宏集结果新版 TeX Live 装好之后编译中文文档时突然报出找不到字体文件的错误。后来排查了很久才发现是旧版本的字体路径污染了新版环境。1.2 Docker 方案的核心优势Docker 的思路本质上把“编译环境”变成了一种可打包、可迁移的资产。我本地不装任何 TeX 工具链只装一个 Docker所有编译能力都在容器里完成。这样做的好处非常具体环境隔离。容器里的 TeX Live 和宿主机完全独立。容器里怎么装宏包、怎么改配置都不会影响宿主机。一致性。同一个镜像在任何机器上表现一致避免了“我这能编你那不行”的问题。可复用。一个镜像可以在多台机器上重复使用也可以打包分享给团队。易清理。不用的时候删掉容器和镜像即可宿主机不会留下任何残留。从使用角度Docker 把 LaTeX 编译变成了一座标准化的“工厂流水线”。我不需要关心流水线内部是什么操作系统、装了什么宏包只要把 LaTeX 源文件作为原料放进去就能稳定产出 PDF 成品。1.3 哪些人最适合用这套方案根据我的使用体验下面几类用户从这套方案里获益最大。论文写作频繁、但不想维护本地 TeX Live 的学生和科研工作者。需要在多台设备间切换写作场景的远程工作人群。需要保证多人协作时编译结果一致的实验室或团队。对 LaTeX 了解不深、希望开箱即用的小白用户。说实话如果你只是偶尔编一份简历或者简单的 PDF完全没必要上 Docker。但只要是高频使用 LaTeX、或者对环境一致性有要求的场景这个方案就值得投入半小时搭建。2. 部署前的准备与镜像选型2.1 基础环境要求开始之前先确认本机 Docker 环境就绪。Windows安装 Docker Desktop 后确认 WSL 2 后端已经启用。macOSDocker Desktop 直接安装即可Apple Silicon 芯片建议选择 arm64 版本镜像。Linux安装 Docker Engine 和 docker compose 插件即可无需桌面版。验证 Docker 是否正常运行在终端执行docker version如果能看到 Client 和 Server 两部分的版本信息说明 Docker 已经在运行了。再确认一下 compose 插件docker compose version这一版信息正常输出就说明环境准备完毕。注意Windows 上 Docker Desktop 依赖 WSL 2 和虚拟化支持。如果启动报错先到 BIOS 里确认虚拟化技术已经开启再在“启用或关闭 Windows 功能”里勾选“适用于 Linux 的 Windows 子系统”和“虚拟机平台”。2.2 镜像选型对比Docker Hub 上常见的 TeX Live 镜像主要有以下几类我列个表方便对比参考镜像特点适用场景texlive/texlive官方维护按 TeX Live 的 collection 拆分成多个 tag通用编译、日常写作snowdreamtech/texlive包含常见宏包和字体使用较方便中文论文、模板编译aergus/latex基于 Alpine Linux体积更小但宏包较少轻量级 CI 场景自己构建 Dockerfile完全可控可按需裁剪有定制需求的团队或项目这里细说一下 texlive/texlive 镜像。它的历史版本标签命名规则很清晰比如 texlive/texlive:latest 默认指向最新稳定版texlive/texlive:2025 则固定到某个具体年份版本。如果你希望编译行为和本地某个特定 TeX Live 版本保持一致那就用具体年份的标签。snowdreamtech/texlive 则在开箱易用性上更胜一筹内置了一大批常用宏包尤其对中文字体和 CTeX 宏集支持友好。如果主要写中文论文不想折腾字体和宏包缺失问题直接用这个镜像更省心。2.3 为什么我选择 texlive/texlive 作为主力镜像我最终选的是 texlive/texlive:latest 作为主力镜像。原因是这个镜像背后有官方维护团队tag 更新及时、宏包覆盖面广、兼容性有保障。搭配方案是日常使用 texlive/texlive:latest 编译英文文档和通用模板当碰到中文论文场景时如果需要更多中文字体和符号支持再切到 snowdreamtech/texlive 镜像。两个镜像同时存在并不冲突因为容器本身天然隔离互不干扰。需要说明的是texlive/texlive 这个镜像体型比较大首次拉取可能要等几个小时。这里有个技巧如果你后续要跑 CI/CD 流水线建议直接使用具体的年份 tag比如 texlive/texlive:2025避免每次构建时的“latest”发生变化导致编译结果不一致。3. 完整部署流程从拉取镜像到编译出第一个 PDF3.1 拉取官方镜像打开终端先拉取镜像docker pull texlive/texlive:latest这里有个小建议如果你带宽有限尽量选在大流量时段下载。镜像解压以后大概占 8 GB 左右加上 Docker 本身的系统盘占用尽量保留至少 20 GB 空闲磁盘。拉取完成后验证镜像是否可用docker images | grep texlive如果能看到 REPOSITORY 为 texlive/texlive 的记录说明镜像已经就位。3.2 建立工作目录与挂载方式Docker 容器内是独立文件系统需要把宿主机上的论文目录挂载进去容器才能访问源文件。我的习惯是建立一个固定工作目录比如~/latex-projects下面按论文或项目分子目录存放。在宿主机创建目录并写一个最简单的测试文件mkdir -p ~/latex-projects/hello cd ~/latex-projects/hello新建一个 hello.tex内容如下\documentclass{article} \begin{document} Hello, Docker LaTeX! \end{document}接下来用 docker run 启动容器并挂载目录docker run --rm -v $(pwd):/workspace -w /workspace texlive/texlive:latest pdflatex hello.tex这条命令的参数解释一下--rm容器运行完自动删除不留垃圾。-v $(pwd):/workspace把当前目录挂载到容器内的 /workspace。-w /workspace进入容器后默认工作目录切换为 /workspace。最后一个参数是容器内要执行的编译命令。如果一切正常你会在当前目录下看到 hello.pdf 生成。至此Docker 版 LaTeX 编译环境已经跑通。3.3 常用编译命令的容器内写法实际论文写作时编译命令远不止 pdflatex 一个。我在这里把常用命令的应用场景和容器内写法统一整理一下。对于英文小文档直接使用docker run --rm -v $(pwd):/workspace -w /workspace texlive/texlive:latest pdflatex main.tex对于包含参考文献的论文需要明确调用 BibTeX命令序列如下docker run --rm -v $(pwd):/workspace -w /workspace texlive/texlive:latest pdflatex main.tex docker run --rm -v $(pwd):/workspace -w /workspace texlive/texlive:latest bibtex main docker run --rm -v $(pwd):/workspace -w /workspace texlive/texlive:latest pdflatex main.tex docker run --rm -v $(pwd):/workspace -w /workspace texlive/texlive:latest pdflatex main.tex这里解释一下为什么要执行多遍 pdflatex。LaTeX 的交叉引用和文献引用机制需要运行多轮才能稳定第一遍记录引用信息后续轮次再根据记录回填编号。中文用户最常遇到的情况是 \cite 标注在首次编译后显示成问号其实第二次编译就恢复了。使用 latexmk 自动化管理多轮编译是一种更省心的方式docker run --rm -v $(pwd):/workspace -w /workspace texlive/texlive:latest latexmk -xelatex main.tex这里特意用了-xelatex因为如果你写中文论文XeLaTeX 配合 CTeX 宏包是目前兼容性最好的编译方案。它把 Unicode 和字体系统完美融合避免了传统 pdflatex 在字体编码处理上的各种限制。3.4 中文论文排版的关键配置中文论文是 LaTeX 使用的重头戏这里单列一节重点说明。第一务必使用 XeLaTeX 编译。传统 pdflatex 需要额外的 CJK 宏包和繁琐的字体配置而 XeLaTeX 可以直接调用系统字体处理中日韩文字更自然。第二文档导言区引入 ctex 宏包\documentclass[UTF8]{ctexart} \begin{document} 中文排版测试。 \end{document}ctexart 是 CTeX 宏集提供的文档类专门面向中文论文和报告排版效果最接近国内学位论文规范。第三中文字体的选择。使用 ctex 宏包时通过 fontset 选项可以指定使用的系统字体版本。如果你的论文模板指定了宋体/黑体/楷体可以通过\documentclass[UTF8, fontsetwindows]{ctexart}这里的 fontset 参数可选 windows、mac、fandol 等。其中 fandol 字体集是 TeX Live 自带的开源中文字体如果你用的是 Docker 镜像不依赖宿主机安装任何中文字体推荐直接用 fontsetfandol这样在隔离环境里也能稳定编译出中文文档。我实测过 texlive/texlive 镜像自带的 fandol 字体已经可以完整支持中文论文的宋体、黑体、楷体和仿宋。这意味着你不需要在宿主机上额外安装中文字体这也是使用 Docker 编译中文论文的一个巨大便利。4. 集成到日常写作VS Code 联动方案4.1 为什么推荐 VS Code 作为前端编辑器命令行的方式适合验证环境和脚本自动化但平时写作还是需要一个好用的编辑器。VS Code 的 LaTeX Workshop 插件是目前体验最好的免费方案原因有三支持语法高亮、自动补全、公式预览。内置 PDF 预览保存后自动编译刷新。可以自定义编译方式把 Docker 命令作为编译工具链接入。经过实际体验把 Docker 作为 LaTeX Workshop 的后端编译工具和本地 TeX Live 的体验差距几乎为 0。VS Code 只是触发命令真正干活的是容器。4.2 latex-workshop 配置 Docker 编译任务安装好 LaTeX Workshop 插件后需要在 VS Code 的 settings.json 里插入一段自定义配置让插件调用 Docker 命令而非本地命令。在用户设置或工作区设置中添加如下配置{ latex-workshop.latex.recipes: [ { name: docker-xelatex, tools: [ docker-xelatex ] }, { name: docker-latexmk, tools: [ docker-latexmk ] } ], latex-workshop.latex.tools: [ { name: docker-xelatex, command: docker, args: [ run, --rm, -v, %DIR%:/workspace, -w, /workspace, texlive/texlive:latest, xelatex, -synctex1, -interactionnonstopmode, -file-line-error, %DOC% ] }, { name: docker-latexmk, command: docker, args: [ run, --rm, -v, %DIR%:/workspace, -w, /workspace, texlive/texlive:latest, latexmk, -xelatex, -synctex1, -interactionnonstopmode, %DOC% ] } ] }配置要点说明%DIR%会被 LaTeX Workshop 自动替换为当前源文件所在目录。%DOC%会被替换为当前源文件的完整路径。-interactionnonstopmode让编译过程遇到错误不中断等待方便编辑器捕获日志。-synctex1开启反向定位方便在 PDF 和源码之间跳转。配置完成后打开任意 .tex 文件点一下编译按钮VS Code 就会通过 Docker 执行编译。PDF 预览会在编译完成后自动刷新。我实测下来这套方案非常顺滑。唯一需要注意的是首次编译会慢一点因为容器每次都是新的一次性启动后续会好很多。4.3 使用 Dev Container 打造持久开发环境如果你希望进入容器做更复杂的操作比如安装新宏包、修改全局配置可以使用 Dev Containers 插件。项目根目录创建.devcontainer/devcontainer.json{ name: latex-dev, image: texlive/texlive:latest, workspaceFolder: /workspace, workspaceMount: source${localWorkspaceFolder},target/workspace,typebind, customizations: { vscode: { extensions: [ james-yu.latex-workshop ] } } }然后在 VS Code 中按 F1选择“Reopen in Container”VS Code 就会重新启动一个带 LaTeX 环境的完整开发容器。这时候你在容器内打开终端执行 tlmgr install 某些缺失宏包效果和直接在容器环境内操作是一样的。这个模式对团队协作尤其友好所有人都用同一套环境和配置妈妈再也不担心“我这编不过你那能编”的老难题了。5. 实际运行中的常见问题与排查实录5.1 问题汇总速查表下面这个表格是我在实际使用中常遇到的问题和对应的解决办法。遇到问题时先看这一节基本能解决 80% 的情况。症状可能原因解决方案docker 命令找不到未安装 Docker 或环境变量未配置安装 Docker 后重启终端镜像拉取超时或失败网络波动配置镜像加速器后重试容器启动报权限错误目录挂载权限问题Docker Desktop 设置中开启文件共享编译后没有 PDF默认编译引擎不对使用 xelatex 并检查日志中文显示为乱码编码或字体缺失确保使用 UTF-8 编码并引入 ctex参考文献显示问号多轮编译未完成使用 latexmk 自动处理引用的图片不显示图片路径不对检查相对路径和大小写宏包缺失镜像未包含该宏包使用 tlmgr 在容器内安装容器运行时报内存不足镜像体积大增加 Docker 内存配额5.2 典型案例深度分析案例一运行时提示“virtualization support not detected”。这个问题常见于 Windows 下 Docker Desktop 启动失败本质是宿主机没有开启硬件虚拟化支持。解决办法是重启进入 BIOS在 CPU 配置中开启 Intel VT-x 或 AMD-V然后在 Windows 功能中确认“虚拟机平台”和“适用于 Linux 的 Windows 子系统”均已勾选。开启后重启电脑Docker Desktop 就能正常启动。案例二编译时报错“Package ctex Error: CTeX fontsetfandol is unavailable”。这个错误出现在某些修改过的 ctex 版本中。最常见的原因是镜像内的字体缓存没有刷新或者是宏包版本冲突。解决方法是清理辅助文件后重新编译或者在文档开头显式声明\usepackage[fontsetfandol]{ctex}。如果仍然报错把编译命令改成 xelatex 再试一次。案例三BibTeX 版本报错出现类似 “This is BibTeX, Version 0.99d (TeX Live 2022)” 的信息后终止。很多情况下问题不在 BibTeX 本身而是 .bib 文件里混入了不规范的条目或者临时文件里有残留的 .bbl 文件。处理办法是删除 .aux、.bbl、.blg 等临时文件重新执行 latexmk 完整编译流程。实际动手排错过程中这类报错有几次就是清理后就好了。案例四容器内找不到某个字体编译出来的文档报 “font not found”。这种情况最容易出现在中文排版中解决思路有两种一是直接在容器内使用 tlmgr 安装字体相关宏包和字体文件二是干脆切换到 snowdreamtech/texlive 这种内置更多字体的镜像。考虑到便利性我自己更习惯于直接用 fandol 字体方案它不需要宿主机额外安装任何字体。5.3 我一直在用的避坑小技巧这里分享几个我实际踩过坑之后总结出来的经验属于网上教程很少提及的细节。第一不要每次编译都手动敲一长串 docker run 命令。把常用命令写进项目的 Makefile再配合 VS Code 插件触发效率能提升好几倍。第二在项目根目录放一个.dockerignore文件。虽然我们不直接构建镜像但 Docker 在上下文中扫描整个目录时加上这个文件可以避免把大量临时文件拷入上下文提升挂载性能。第三如果需要新增宏包不要直接修改基础镜像。正确做法是在容器内使用 tlmgr 安装完之后用 docker commit 或编写 Dockerfile 构建一个新镜像以后所有项目都基于新镜像编译。第四区分“编译环境”和“写作环境”。Docker 只管编译写作和代码跳转交给编辑器。刚开始接触时容易把两件事混在一起实际两者职责单一才是效率最大化的关键。6. 进阶思路定制镜像与流水线化6.1 用 Dockerfile 定制个人编译镜像默认的 texlive/texlive 镜像已经非常完善但你可能需要一些它没内置的宏包或设置。这时就该定制自己的镜像了。新建一个 DockerfileFROM texlive/texlive:latest # 安装额外宏包 RUN tlmgr update --self \ tlmgr install algorithm2e \ tlmgr install enumitem \ tlmgr install fontawesome5 # 设置默认工作目录 WORKDIR /workspace然后在同目录执行构建docker build -t my-latex:latest .构建后自定义镜像 my-latex 就可以替代官方的 texlive/texlive 使用了。这种定制化的思路非常适合固定投稿期刊或毕业论文的团队把所有需要的宏包一次集成到镜像里后续编译统一走这个镜像彻底告别“本地宏包不全”的痛点。6.2 在 CI/CD 流水线中使用 Docker 编译 LaTeX结合 Docker 的一键编译能力还能把论文的编译过程集成到自动化流水线中。举个例子在 GitHub Actions 里写一个简单的 workflow 文件name: Build LaTeX Paper on: push: paths: - paper/** jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - name: Compile LaTeX paper uses: docker://texlive/texlive:latest with: args: | cd paper latexmk -xelatex main.tex - name: Upload PDF uses: actions/upload-artifactv4 with: name: paper-pdf path: paper/main.pdf配置好了以后每次把 .tex 源文件推送到仓库云端的流水线就会自动编译出新版 PDF。对多人合作的论文项目来说这个流程等于给文档加了一个“持续发布通道”每次改动后大家拿到的永远是当期最新的编译成品。6.3 对自己更高效的脚本化封装为了更进一步压缩编译成本我把常用命令封装成了一个小脚本。在宿主机某个目录下创建一个texbuild.sh#!/bin/bash set -e IMAGE${IMAGE:-texlive/texlive:latest} ENGINE${ENGINE:-xelatex} if [ -z $1 ]; then echo Usage: ./texbuild.sh main.tex exit 1 fi DIR$(cd $(dirname $1) pwd) FILE$(basename $1) docker run --rm \ -v $DIR:/workspace \ -w /workspace \ $IMAGE \ latexmk -$ENGINE -synctex1 -interactionnonstopmode $FILE echo Build completed.之后只需在项目目录下执行./texbuild.sh main.tex脚本会自动识别路径、启动容器、编译输出 PDF。这套脚本我用了很长时间配合 VS Code 的 latex-workshop几乎可以完全替代本地 TeX 工具链的使用体验。我个人在实际操作中最大的体会是Docker 化 LaTeX 真正解决了“环境焦虑”的问题。以前换电脑、换系统、更新宏包都要提心吊胆现在只要 Docker 在、镜像在任何机器上都能以完全一致的方式产出 PDF。如果你也常年在论文排版、期刊投稿里摸爬滚打非常建议花上一个小时把这套环境搭起来后面的省心程度会超出你的预期。最后再提一个很多人忽略的点镜像不是越新越好建议固定到一个经过验证的 tag 长期使用。我自己的主力镜像固定在某个稳定版本只有确定新宏包版本不影响现有文档时才会重新构建。这种谨慎的做法反而让排版成果更持久可靠。