Docker部署Overleaf

参考资料:
Docker部署Overleaf包含中文字体与全套texlive镜像
搭建和使用overleaf服务器
自建overleaf (在线latex环境)全过程指南
Overleaf in Docker
阿里云ECS官方文档:如何配置Linux实例的swap分区?

安装Docker和Docker Compose

Overleaf依赖dockerdocker compose,因此需要先安装docker和docker compose。

使用宝塔面板安装

使用宝塔面板安装Docker和Docker Compose非常简单,只需要在宝塔面板的左侧菜单->Docker,直接安装即可。宝塔会同时安装好Docker和Docker Compose。

使用命令行安装

Docker安装详见官方文档

Docker-Compose组件的安装详见官方文档

配置并安装Overleaf Toolkit

overleaf的安装需要创建三个容器,包括sharelatex、mongo和redis。Overleaf Toolkit可以几乎一键完成这三个容器的部署。

拉取Overleaf Toolkit

  1. 将Overleaf Toolkit从github克隆到本地主机上(以下命令已重命名为overleaf文件夹)
git clone https://github.com/overleaf/toolkit.git ./overleaf
  1. 进入overleaf目录
cd overleaf

后续的所有指令都在overleaf目录下执行。

配置Overleaf Toolkit

  1. 创建本地配置文件
bin/init

bin是该工具包提供的一组脚本,这些脚本封装起来,并为你处理大部分的细节。

  1. 查看配置目录下的内容config/
ls config

config目录下有三个文件,名字和作用分别为:

  • overleaf.rc:顶级配置文件
  • variables.env:加载到 docker 容器中的环境变量
  • version:使用的 docker 镜像版本
  1. 参数配置

    这一步修改的参数,在docker运行起来之后(即后面运行的bin/up),再修改是不会生效的!

打开文件修改参数可以通过宝塔面板打开文件来修改,会更加方便一些,更习惯用vim也是可以的。

打开overleaf.rc文件,修改以下参数:

OVERLEAF_LISTEN_IP=127.0.0.1    # 监听的本地IP地址。如果这里的ip设置为服务器的公网ip,那么就可以通过公网ip+端口来访问overleaf。
OVERLEAF_PORT=9000 # 监听的本地端口,默认是80,可修改为任意可用的其他端口

修改后的完整文件如下:

#### Overleaf RC ####

PROJECT_NAME=overleaf

# Sharelatex container
# Uncomment the OVERLEAF_IMAGE_NAME variable to use a user-defined image.
# OVERLEAF_IMAGE_NAME=sharelatex/sharelatex
OVERLEAF_DATA_PATH=data/overleaf
SERVER_PRO=false
OVERLEAF_LISTEN_IP=127.0.0.1
OVERLEAF_PORT=9000

# Sibling Containers
SIBLING_CONTAINERS_ENABLED=true
DOCKER_SOCKET_PATH=/var/run/docker.sock

# Mongo configuration
MONGO_ENABLED=true
MONGO_DATA_PATH=data/mongo
MONGO_IMAGE=mongo
MONGO_VERSION=6.0

# Redis configuration
REDIS_ENABLED=true
REDIS_DATA_PATH=data/redis
REDIS_IMAGE=redis:6.2
REDIS_AOF_PERSISTENCE=true

# Git-bridge configuration (Server Pro only)
GIT_BRIDGE_ENABLED=false
GIT_BRIDGE_DATA_PATH=data/git-bridge

# TLS proxy configuration (optional)
# See documentation in doc/tls-proxy.md
NGINX_ENABLED=false
NGINX_CONFIG_PATH=config/nginx/nginx.conf
NGINX_HTTP_PORT=80
# Replace these IP addresses with the external IP address of your host
NGINX_HTTP_LISTEN_IP=127.0.1.1
NGINX_TLS_LISTEN_IP=127.0.1.1
TLS_PRIVATE_KEY_PATH=config/nginx/certs/overleaf_key.pem
TLS_CERTIFICATE_PATH=config/nginx/certs/overleaf_certificate.pem
TLS_PORT=443

# In Air-gapped setups, skip pulling images
# PULL_BEFORE_UPGRADE=false
# SIBLING_CONTAINERS_PULL=false

这里没有使用toolkit来创建nginx容器进行反代,而是使用了宝塔面板的nginx进行反代,后面会提到。


打开variables.env文件,修改以下参数:

OVERLEAF_APP_NAME="Overleaf"

OVERLEAF_SITE_URL=http://tex.example.com # 网站的url,无论是否配置此项,都能通过之前配置的本地ip地址+端口来访问overleaf
OVERLEAF_NAV_TITLE=Overleaf
[email protected] # 管理员账号登录邮箱

修改后的完整文件如下:

OVERLEAF_APP_NAME="Overleaf"

ENABLED_LINKED_FILE_TYPES=project_file,project_output_file

# Enables Thumbnail generation using ImageMagick
ENABLE_CONVERSIONS=true

# Disables email confirmation requirement
EMAIL_CONFIRMATION_DISABLED=true

## Nginx
# NGINX_WORKER_PROCESSES=4
# NGINX_WORKER_CONNECTIONS=768

## Set for TLS via nginx-proxy
# OVERLEAF_BEHIND_PROXY=true
# OVERLEAF_SECURE_COOKIE=true

OVERLEAF_SITE_URL=http://tex.example.com
OVERLEAF_NAV_TITLE=Overleaf
# OVERLEAF_HEADER_IMAGE_URL=http://somewhere.com/mylogo.png
[email protected]

# OVERLEAF_LEFT_FOOTER='[{"text": "Contact your support team", "url": "mailto:[email protected]"}]'
# OVERLEAF_RIGHT_FOOTER='[{"text": "Hello, I am on the Right"}]'

# [email protected]

# OVERLEAF_EMAIL_AWS_SES_ACCESS_KEY_ID=
# OVERLEAF_EMAIL_AWS_SES_SECRET_KEY=

# OVERLEAF_EMAIL_SMTP_HOST=smtp.example.com
# OVERLEAF_EMAIL_SMTP_PORT=587
# OVERLEAF_EMAIL_SMTP_SECURE=false
# OVERLEAF_EMAIL_SMTP_USER=
# OVERLEAF_EMAIL_SMTP_PASS=
# OVERLEAF_EMAIL_SMTP_NAME=
# OVERLEAF_EMAIL_SMTP_LOGGER=false
# OVERLEAF_EMAIL_SMTP_TLS_REJECT_UNAUTH=true
# OVERLEAF_EMAIL_SMTP_IGNORE_TLS=false
# OVERLEAF_CUSTOM_EMAIL_FOOTER=This system is run by department x

################
## Server Pro ##
################

EXTERNAL_AUTH=none
# OVERLEAF_LDAP_URL=ldap://ldap:389
# OVERLEAF_LDAP_SEARCH_BASE=ou=people,dc=planetexpress,dc=com
# OVERLEAF_LDAP_SEARCH_FILTER=(uid={{username}})
# OVERLEAF_LDAP_BIND_DN=cn=admin,dc=planetexpress,dc=com
# OVERLEAF_LDAP_BIND_CREDENTIALS=GoodNewsEveryone
# OVERLEAF_LDAP_EMAIL_ATT=mail
# OVERLEAF_LDAP_NAME_ATT=cn
# OVERLEAF_LDAP_LAST_NAME_ATT=sn
# OVERLEAF_LDAP_UPDATE_USER_DETAILS_ON_LOGIN=true

# OVERLEAF_TEMPLATES_USER_ID=578773160210479700917ee5
# OVERLEAF_NEW_PROJECT_TEMPLATE_LINKS=[{"name":"All Templates","url":"/templates/all"}]

# TEX_LIVE_DOCKER_IMAGE=quay.io/sharelatex/texlive-full:2022.1
# ALL_TEX_LIVE_DOCKER_IMAGES=quay.io/sharelatex/texlive-full:2022.1,quay.io/sharelatex/texlive-full:2021.1,quay.io/sharelatex/texlive-full:2020.1

# OVERLEAF_PROXY_LEARN=true

# S3
# Docs: https://github.com/overleaf/overleaf/wiki/S3
# ## Enable the s3 backend for filestore
# OVERLEAF_FILESTORE_BACKEND=s3
# ## Enable S3 backend for history
# OVERLEAF_HISTORY_BACKEND=s3
# #
# # Pick one of the two sections "AWS S3" or "Self-hosted S3".
# #
# # AWS S3
# ## Bucket name for project files
# OVERLEAF_FILESTORE_USER_FILES_BUCKET_NAME=overleaf-user-files
# ## Bucket name for template files
# OVERLEAF_FILESTORE_TEMPLATE_FILES_BUCKET_NAME=overleaf-template-files
# ## Key for filestore user
# OVERLEAF_FILESTORE_S3_ACCESS_KEY_ID=...
# ## Secret for filestore user
# OVERLEAF_FILESTORE_S3_SECRET_ACCESS_KEY=...
# ## Bucket region you picked when creating the buckets.
# OVERLEAF_FILESTORE_S3_REGION=""
# ## Bucket name for project history blobs
# OVERLEAF_HISTORY_PROJECT_BLOBS_BUCKET=overleaf-project-blobs
# ## Bucket name for history chunks
# OVERLEAF_HISTORY_CHUNKS_BUCKET=overleaf-chunks
# ## Key for history user
# OVERLEAF_HISTORY_S3_ACCESS_KEY_ID=...
# ## Secret for history user
# OVERLEAF_HISTORY_S3_SECRET_ACCESS_KEY=...
# ## Bucket region you picked when creating the buckets.
# OVERLEAF_HISTORY_S3_REGION=""
#
# # Self-hosted S3
# ## Bucket name for project files
# OVERLEAF_FILESTORE_USER_FILES_BUCKET_NAME=overleaf-user-files
# ## Bucket name for template files
# OVERLEAF_FILESTORE_TEMPLATE_FILES_BUCKET_NAME=overleaf-template-files
# ## Key for filestore user
# OVERLEAF_FILESTORE_S3_ACCESS_KEY_ID=...
# ## Secret for filestore user
# OVERLEAF_FILESTORE_S3_SECRET_ACCESS_KEY=...
# ## S3 provider endpoint
# OVERLEAF_FILESTORE_S3_ENDPOINT=http://10.10.10.10:9000
# ## Path style addressing of buckets. Most likely you need to set this to "true".
# OVERLEAF_FILESTORE_S3_PATH_STYLE="true"
# ## Bucket region. Most likely you do not need to configure this.
# OVERLEAF_FILESTORE_S3_REGION=""
# ## Bucket name for project history blobs
# OVERLEAF_HISTORY_PROJECT_BLOBS_BUCKET=overleaf-project-blobs
# ## Bucket name for history chunks
# OVERLEAF_HISTORY_CHUNKS_BUCKET=overleaf-chunks
# ## Key for history user
# OVERLEAF_HISTORY_S3_ACCESS_KEY_ID=...
# ## Secret for history user
# OVERLEAF_HISTORY_S3_SECRET_ACCESS_KEY=...
# ## S3 provider endpoint
# OVERLEAF_HISTORY_S3_ENDPOINT=http://10.10.10.10:9000
# ## Path style addressing of buckets. Most likely you need to set this to "true".
# OVERLEAF_HISTORY_S3_PATH_STYLE="true"
# ## Bucket region. Most likely you do not need to configure this.
# OVERLEAF_HISTORY_S3_REGION=""

修改启动镜像

官方提供的镜像是不完全Texlive程序且不支持中文字体。参考1基于官方开源的overleaf镜像搭建了自己的docker镜像:wrm244/sharelatex:with-texlive-full,如果对docker比较熟悉的同学可以跳过该步骤自行拉取官方镜像然后再进行配置,当然官方镜像不包含中文字体支持,可参考文章配置。

在这里直接使用wrm244/sharelatex:with-texlive-full作为sharelatex的镜像,但该镜像直接使用时,出现很多docker变量还是原作者的自定义内容(包括但不限于:左下角标注、联系邮箱、用户修改密码的域名等),笔者目前没有寻找使用toolkit的情况下,修改这里面的变量的方法,有待后续更新。

  1. 进入overleaf文件夹下的lib目录
cd lib
  1. 打开docker-compose.base.yml文件,将image: "${IMAGE}"修改为image: wrm244/sharelatex:with-texlive-full,改这一行就好,修改后的完整文件内容如下:
---
services:

sharelatex:
restart: always
image: wrm244/sharelatex:with-texlive-full
container_name: sharelatex
volumes:
- "${OVERLEAF_DATA_PATH}:${OVERLEAF_IN_CONTAINER_DATA_PATH}"
ports:
- "${OVERLEAF_LISTEN_IP:-127.0.0.1}:${OVERLEAF_PORT:-80}:80"
environment:
GIT_BRIDGE_ENABLED: "${GIT_BRIDGE_ENABLED}"
GIT_BRIDGE_HOST: "git-bridge"
GIT_BRIDGE_PORT: "8000"
REDIS_HOST: "${REDIS_HOST}"
REDIS_PORT: "${REDIS_PORT}"
V1_HISTORY_URL: "http://sharelatex:3100/api"
env_file:
- ../config/variables.env
stop_grace_period: 60s

咋哩也可以修改config目录下overleaf.rc配置文件赋值为SHARELATEX_IMAGE=wrm244/sharelatex:with-texlive-full

(可选)关闭docker自启,配置服务器的swap分区

overleaf的镜像对内存要求并不高,但是笔者在初次尝试使用了内存2G的ECS服务器,启动docker服务后,服务器磁盘读取拉满,直接导致进不去命令行。

关闭docker服务自启动

在启动docker镜像前,建议先关闭docker服务的自启动:

systemctl disable docker
systemctl disable docker.socket

另外,将上一小节中的docker-compose.base.yml文件中的restart: always修改为restart: no,这样容器不会在出现问题关闭后又自动重启。

关闭docker服务自启动后,需要手动启动docker服务:

systemctl start docker

这样万一docker出问题导致服务器宕机,无法进入命令行,也可以通过强制重启服务器来关闭docker。

在确认docker容器运行正常后,可以通过以下命令重新开启docker服务的自启动:

systemctl enable docker
systemctl enable docker.socket

配置服务器的swap分区

参考阿里云ECS官方文档:如何配置Linux实例的swap分区?

启动docker容器

在overleaf目录下执行以下命令:

bin/up

注意:第一次启动时,会下载镜像,可能会比较慢。

该命令类似于docker run命令,但是会自动拉取镜像并启动容器。
首次运行会看到下载镜像的过程,下载完成后会自动运行容器。然后会输出日志。在输出日志时,可用用ctrl+c来停止日志输出,此时会停止容器。
停止后,可通过bin/start来重新启动容器,并不输出日志。

配置nginx反代

在命令行中运行sudo docker ps -a可以看到有3个容器在运行:

root@xxxxxxx:~# sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e9e7b2b174e0 wrm244/sharelatex:with-texlive-full "/sbin/my_init" 2 hours ago Up About an hour 127.0.0.1:9000->80/tcp sharelatex
efd2002d6a0c redis:6.2 "docker-entrypoint.s…" 2 hours ago Up About an hour 6379/tcp redis
973152ada599 mongo:6.0 "docker-entrypoint.s…" 2 hours ago Up About an hour (healthy) 27017/tcp

PORTS列中,可以看到容器的端口映射。在sharelatex容器的端口映射为127.0.0.1:9000->80/tcp,这意味着容器的80端口被映射到主机本地ip的9000端口,也就是overleaf的网页被映射到了127.0.0.1:9000上。

接下来配置宝塔面板的nginx反代。
在宝塔面板的左侧菜单->网站->方向代理,点击添加反代
域名中填写要在外网使用的域名,例如设置为tex.example.com
目标中选择URL地址,IP填写0.0.0.0:9000,暂不清楚这里为什么不是127.0.0.1。
发送域名(host)中填写$http_host,是默认填写好的。

完成以上步骤后,即将127.0.0.1:9000反向代理到了tex.example.com上。

至于域名使用https,只要在宝塔面板中为域名配置ssl证书即可。

使用overleaf

创建管理员账户:
在浏览器中访问https://tex.example.com/launchpad或者在局域网内访问http://localhost:服务端口/launchpad即可看到管理员的注册界面,输入密码注册即可。

笔者使用该镜像没有再研究注册更多用户时,给出的修改密码的链接仍然是原作者的域名的问题,应该需要更改sharelatex的docker镜像的变量,有待后续更新。

迁移与备份

本节完全转自参考1,没有经过测试!!!
如果是采用overleaf-toolkit工具包进行部署服务的话,在该overleaf目录下的data文件夹会映射docker容器的文件,包括sharelatexredismongo文件夹,备份这几个文件夹即可,在迁移的时候,启动容器前先把文件复制到data目录下即可恢复数据。