使用 docker-compose 搭建自己的 Overleaf Community 服务器

在使用 Word 撰写论文时,发现就算有现成的示例,也还是经常和文档的格式搏斗。使用 LaTeX 可以在一定程度上避免这个问题。依赖于线上的服务(比如 Overleaf 网页版)虽然方便,但是有隐私泄露的风险。因此,我决定在本地搭建一个 Overleaf Community 服务器,用来安全地管理和编辑 LaTeX 项目。

Overleaf 已经提供了基于 Docker 镜像快速配置方法,因此可以很快捷地构建相关服务。不过在顺利编译出 IEEE 示例项目的 PDF 文件之前,还需要进行一些额外的设置。

编辑 docker-compose.yaml

Overleaf 提供的 docker-compose.yaml 中对于 mongo 的初始化设置存在一些问题,可能会出现报错:

1
2
3
4
5
6
7
8
9
Mongo instance doesn't support transactions
MongoServerError: Transaction numbers are only allowed on a replica set member or mongos
// Error log...
at Socket.emit (node:events:517:28) {
ok: 0,
code: 20,
codeName: 'IllegalOperation',
[Symbol(errorLabels)]: Set(0) {}
}

为了解决此问题,需要对 docker-compose.yaml 进行一些修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# docker-compose.yaml
services:
sharelatex:
restart: always
image: sharelatex/sharelatex
container_name: sharelatex
depends_on:
mongo:
condition: service_healthy
redis:
condition: service_started
ports:
- 10802:80
links:
- mongo
- redis
stop_grace_period: 60s
volumes:
- './overleaf_data:/var/lib/overleaf'

environment:
OVERLEAF_APP_NAME: Overleaf Community Edition
OVERLEAF_MONGO_URL: mongodb://mongo/sharelatex
OVERLEAF_REDIS_HOST: redis
REDIS_HOST: redis
ENABLED_LINKED_FILE_TYPES: 'project_file,project_output_file'
ENABLE_CONVERSIONS: 'true'
EMAIL_CONFIRMATION_DISABLED: 'true'
TEXMFVAR: /var/lib/overleaf/tmp/texmf-var

mongo:
restart: always
image: mongo:5.0
container_name: mongo
command: "--replSet overleaf"
expose:
- 27017
volumes:
- "./mongo_data:/data/db"
healthcheck:
test: echo 'db.stats().ok' | mongo localhost:27017/test --quiet
interval: 10s
timeout: 10s
retries: 5

mongoinit:
image: mongo:5.0
# this container will exit after executing the command
restart: "no"
depends_on:
mongo:
condition: service_healthy
entrypoint:
[
"mongo",
"--host",
"mongo:27017",
"--eval",
'rs.initiate({ _id: "overleaf", members: [ { _id: 0, host: "mongo:27017" } ] })'
]

redis:
restart: always
image: redis:alpine
container_name: redis
expose:
- 6379
volumes:
- ./redis_data:/data

主要的修改在于:

  • 添加了 mongoinit 实例,在初始化时对 mongo 进行必要的设置;
  • (非必要)使用了更小的 redis:alpine 镜像
  • (非必要)将网页监听端口设置到了 10802
  • (非必要)将数据文件夹设置在当前文件夹下

修改之后在 docker-compose.yaml 所在的文件夹下启动 docker-compose

1
docker-compose up -d

将启动一个正常运行的 Overleaf 服务。

为 LaTeX 编译器安装依赖

Sharelatex 镜像中并没有预先安装所有的 LaTeX 包,想要编译一份全英文的 IEEE 示例项目,需要使用 tlmgr 安装缺少的包,提供必要的功能或字体,否则在编译 LaTeX 项目时可能会出现编译错误,比如:

  • LaTeX Error: File 'algorithmic.sty' not found.
  • LaTeX Error: Font \OT1/ptm/b/n/5=nullfont not loadable: Metric (TFM) file not found.

安装部分依赖

如果只需要编译一个简单的纯英文 PDF,可以使用 tlmgr 安装相关依赖:

1
2
3
4
5
# 在 Docker 容器的终端中:
tlmgr install collection-fontsrecommended algorithms biblatex cite ctex

# ...或者在系统命令行中:
docker exec $id tlmgr install collection-fontsrecommended algorithms biblatex cite ctex

其中 $idsharelatex 的 docker container 的 id(或它的前几位)。

…或者安装所有依赖

也可以让 tlmgr 一次性安装所有依赖,这样一来就再也不用担心依赖问题了:

1
2
3
4
5
# 在 Docker 容器的终端中:
tlmgr install scheme-full

# ...或者在系统命令行中:
docker exec $id tlmgr install scheme-full

其中 $idsharelatex 的 docker container 的 id(或它的前几位)。

需要下载大概 4.5G 的文件,得耐心等待一阵子。

账号设置

刚建立的 Overleaf 服务器中没有任何用户数据,因此需要在设置页面设置第一个管理员账户。设置页面的路径是 /launchpad,比如 http://127.0.0.1:10802/launchpad

创建项目并编译

现在,在本地通过 docker-compose 设置的 Overleaf Community 版应当可以编辑一个 IEEE 示例项目了。可以在 Overleaf 官网上找到模板,将项目压缩包下载到本地,再作为新项目上传到搭建的 Overleaf Community 服务器上,即可将项目编译到 PDF,测试编译效果。