docker部署seafile(个人详细版本)

1.首先安装docker与dockercompose

在线安装或者离线安装都可以 离线安装docker要使其成为系统级的服务,需要手动编写配置文件才能用systemctl命令对其进行操作

1
vim /etc/systemd/system/docker.service

创建并写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target

[Service]
Type=notify
ExecStart=/usr/bin/dockerd --selinux-enabled=false -H unix:///var/run/docker.sock
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=1048576
LimitNPROC=65536
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s

[Install]
WantedBy=multi-user.target

创建daemon.json文件:

1
2
3
4
5
6
7
8
9
10
11
## 创建相关文件夹,其中/dcdata/docker 是docker的根目录
mkdir -p /etc/docker && mkdir -p /dcdata/docker

vim /etc/docker/daemon.json

## 输入以上内容
{
"data-root": "/dcdata/docker",
"bip":"172.31.0.1/24"
}
# 规定docker内部网络ip段,是因为如果不规定,可能会生成与现在内网ip相同的段

给服务授权:

1
2
chmod 755 /etc/systemd/system/docker.service
chmod 755 /etc/docker/daemon.json

以下是配置文件结构说明:(ai)

一、[Unit] 区块:定义服务的元数据和依赖关系

用于描述服务的基本信息、启动顺序和依赖的其他系统组件。

  • Description=Docker Application Container Engine服务的描述信息,说明这是 Docker 容器引擎服务。
  • Documentation=https://docs.docker.com指向 Docker 官方文档的链接,便于管理员查阅相关说明。
  • After=network-online.target firewalld.service定义服务的启动顺序:Docker 必须在 network-online.target(网络完全就绪)和 firewalld.service(防火墙服务)启动之后才启动,避免因网络未就绪或防火墙未加载导致的问题。
  • Wants=network-online.target表示 Docker 服务 “希望”network-online.target 启动(但不强制依赖),即使该目标未启动,Docker 仍可尝试启动(软依赖)。

二、[Service] 区块:定义服务的运行规则

核心区块,指定 Docker 守护进程的启动命令、运行参数、资源限制等。

  • Type=notify服务类型为 notify:表示 dockerd 启动完成后会主动通知 systemd “已就绪”,systemd 收到通知后才会认为服务启动成功(确保服务完全就绪后再继续后续流程)。
  • ExecStart=/usr/bin/dockerd --selinux-enabled=false -H unix:///var/run/docker.sock启动命令:指定 Docker 守护进程的执行路径和参数。
    • /usr/bin/dockerd:Docker 守护进程的可执行文件路径。
    • --selinux-enabled=false:禁用 SELinux 支持(SELinux 是 Linux 安全模块,部分场景下可能与 Docker 冲突,禁用可简化配置)。
    • -H unix:///var/run/docker.sock:指定 Docker 守护进程的通信端点为 Unix 套接字(/var/run/docker.sock),Docker 客户端(如 docker 命令)通过该套接字与守护进程通信。
  • ExecReload=/bin/kill -s HUP $MAINPID重载命令:当执行 systemctl reload docker 时,通过发送 HUP 信号(挂起信号)给 Docker 主进程($MAINPID),触发守护进程重新加载配置(无需重启服务)。
  • LimitNOFILE=1048576限制 Docker 进程可打开的最大文件描述符数量(1048576),避免因文件描述符不足导致服务异常。
  • LimitNPROC=65536限制 Docker 进程可创建的最大进程数(65536),防止进程数过多导致系统资源耗尽。
  • LimitCORE=infinity允许 Docker 进程生成核心转储文件(core dump)的大小不受限制,便于调试服务崩溃问题(核心转储文件包含进程崩溃时的内存状态)。
  • TimeoutStartSec=0禁用服务启动超时限制(0 表示无超时),因为 Docker 启动可能需要较长时间(尤其首次启动或容器较多时)。
  • Delegate=yes允许 Docker 守护进程管理自身的子进程(如容器进程)的资源控制(如 CPU、内存限制),将部分权限委托给 Docker,提升容器资源管理的灵活性。
  • KillMode=process当执行 systemctl stop docker 时,仅终止 Docker 主进程(dockerd),而不强制终止其所有子进程(容器进程),避免误杀容器(容器可独立于守护进程运行)。
  • Restart=on-failure定义服务故障时的重启策略:仅当 Docker 守护进程非正常退出(如崩溃)时,systemd 才会自动重启它(正常退出时不重启)。
  • StartLimitBurst=3限制单位时间内的最大重启次数:60 秒内最多重启 3 次,防止服务陷入无限重启循环。
  • StartLimitInterval=60sStartLimitBurst 配合,定义计数重启次数的时间窗口(60 秒)。

三、[Install] 区块:定义服务的安装配置

指定服务在系统启动时的激活方式(即是否随系统自动启动)。

  • 1
    WantedBy=multi-user.target

    表示当系统启动到multi-user.target

    (多用户命令行模式,非图形界面)时,Docker 服务会被自动激活(随系统启动)。

    multi-user.target是 Linux 系统的基本运行级别,确保 Docker 在系统启动早期即可可用。

/opt/seafile目录是默认存储Seafile docker compose文件的目录

可以自己更改

Seafile 使用两个 Docker 卷 来保存其数据库和 Seafile Docker 容器中生成的数据。卷的主机路径分别是/opt/seafile-mysql/opt/seafile-data

Seafile 和 Nginx(其他反向代理工具也是) 的所有配置和日志文件都存储在 Seafile 容器的卷中。

2.使用wget命令获取各个配置文件的模板

1
2
3
4
wget -O .env https://manual.seafile.com/12.0/repo/docker/ce/env
wget https://manual.seafile.com/12.0/repo/docker/ce/seafile-server.yml
wget https://manual.seafile.com/12.0/repo/docker/caddy.yml
wget https://manual.seafile.com/12.0/repo/docker/seadoc.yml

内网服务器环境可以自己传

关于JWT认证

如果想使用JWT私钥 可以下载pwgen

1
2
3
4
yum install pwgen #centos
apt install pwgen #ubuntu

pwgen -s 40 1 //是一个用于生成随机密码的命令

之后复制生成的JWT密钥 写在.env这个配置文件里

ps:onlyoffice是单独的一个服务,最好另外再生成一串密钥

之后会在拉取完镜像之后在某个.py的配置脚本里添加(.env中onlyoffice的配置也是要写的)

3 .env与yml配置文件的内容编写

以下是配置文件的详解与具体配置:

img

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
#我新建了一个data目录 将容器的数据卷都放在了data目录下(实际编写时不应该写注释)
COMPOSE_FILE='seafile-server.yml,caddy.yml,seadoc.yml'
COMPOSE_PATH_SEPARATOR=','


SEAFILE_IMAGE=seafileltd/seafile-mc:12.0-latest #指定 Seafile 主服务(含 Web 界面、文件存储核心等)的 Docker 镜像
SEAFILE_DB_IMAGE=mariadb:10.11 #指定 Seafile 所使用的数据库服务镜像
SEAFILE_MEMCACHED_IMAGE=memcached:1.6.29 #指定缓存服务 Memcached 的 Docker 镜像
SEAFILE_CADDY_IMAGE=lucaslorentz/caddy-docker-proxy:2.9-alpine #指定反向代理服务 Caddy 的 Docker 镜像

# OnlyOffice 配置
ONLYOFFICE_IMAGE=onlyoffice/documentserver:7.3.3
ONLYOFFICE_PORT=8082
ONLYOFFICE_JWT_SECRET=MHVRce4bp8g4AyOUT98oEsYrVVexREqfXuUEFYRG

SEAFILE_VOLUME=/data/seafile-data #指定 Seafile 主服务的数据存储路径
SEAFILE_MYSQL_VOLUME=/data/seafile-mysql/db #指定 MariaDB 数据库的数据存储路径
SEAFILE_CADDY_VOLUME=/data/seafile-caddy #指定 Caddy 反向代理的数据存储路径
//以下是数据库的参数配置
SEAFILE_MYSQL_DB_HOST=db
INIT_SEAFILE_MYSQL_ROOT_PASSWORD=Ew5r********f1CYz
SEAFILE_MYSQL_DB_USER=seafile
SEAFILE_MYSQL_DB_PASSWORD=Ew5rP******h2f1CYz

TIME_ZONE=Asia/Shanghai #时区

JWT_PRIVATE_KEY=FjMDpUVCVpCH7OgLAY5dbmWt0jtaOEZwZMDm6MGH #填写使用工具生成的JWT密钥

SEAFILE_SERVER_HOSTNAME=10.XX.XX.102 #填写真实的IP地址
SEAFILE_SERVER_PROTOCOL=http #web服务的协议

INIT_SEAFILE_ADMIN_EMAIL=admin@xxx.work #默认的管理员邮箱 密码 自定义
INIT_SEAFILE_ADMIN_PASSWORD=se7sw@6N~nlCaN


SEADOC_IMAGE=seafileltd/sdoc-server:1.0-latest #指定运行 SeaDoc 服务所使用的 Docker 镜像
SEADOC_VOLUME=/data/seadoc-data #指定SeaDoc服务所使用的存储路径

ENABLE_SEADOC=true #启用 SeaDoc 服务


NOTIFICATION_SERVER_IMAGE=seafileltd/notification-server:12.0-latest #指定运行通知服务器所使用的 Docker 镜像。
NOTIFICATION_SERVER_VOLUME=/data/notification-data #指定通知服务器的数据存储路径

上述配置将seafile的功能全都启用了

另外几个配置文件的数据卷的目录 也要与.env里的一致

这里没有使用统一配置的dockecompose.yml 而是对其进行拆分 再使用.env文件对yml里的参数进行定义 例如下配置文件中的一些参数(从 Seafile Docker 12.0开始,就需要使用四个配置文件.env, seafile-server.yml, caddy.ymlseadoc.yml 。)

配置caddy.yml(反向代理)

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
#示例配置 与.env中的数据卷路径配置一致
services:

caddy:
image: ${SEAFILE_CADDY_IMAGE:-lucaslorentz/caddy-docker-proxy:2.9-alpine}
container_name: seafile-caddy
restart: unless-stopped
ports:
- 80:80
- 443:443
environment:
- CADDY_INGRESS_NETWORKS=seafile-net
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ${SEAFILE_CADDY_VOLUME:-/data/seafile-caddy}:/data/caddy
networks:
- seafile-net
healthcheck:
test: ["CMD-SHELL", "curl --fail http://localhost:2019/metrics || exit 1"]
start_period: 20s
interval: 20s
timeout: 5s
retries: 3

networks:
seafile-net:
name: seafile-net

配置seadoc.yml

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

services:

seadoc:
image: ${SEADOC_IMAGE:-seafileltd/sdoc-server:1.0-latest}
container_name: seadoc
restart: always
volumes:
- ${SEADOC_VOLUME:-/data/seadoc-data/}:/shared
# ports:
# - "80:80"
environment:
- DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
- DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
- DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
- DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
- DB_NAME=${SEADOC_MYSQL_DB_NAME:-seahub_db}
- TIME_ZONE=${TIME_ZONE:-Etc/UTC}
- JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
- NON_ROOT=${NON_ROOT:-false}
- SEAHUB_SERVICE_URL=${SEAFILE_SERVICE_URL:-http://seafile}
labels:
caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
caddy.@ws.0_header: "Connection *Upgrade*"
caddy.@ws.1_header: "Upgrade websocket"
caddy.0_reverse_proxy: "@ws {{upstreams 80}}"
caddy.1_handle_path: "/socket.io/*"
caddy.1_handle_path.0_rewrite: "* /socket.io{uri}"
caddy.1_handle_path.1_reverse_proxy: "{{upstreams 80}}"
caddy.2_handle_path: "/sdoc-server/*"
caddy.2_handle_path.0_rewrite: "* {uri}"
caddy.2_handle_path.1_reverse_proxy: "{{upstreams 80}}"
depends_on:
db:
condition: service_healthy
networks:
- seafile-net

networks:
seafile-net:
name: seafile-net

配置seafile-server.yml

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
services:
db:
image: ${SEAFILE_DB_IMAGE:-mariadb:10.11}
container_name: seafile-mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
- MYSQL_LOG_CONSOLE=true
- MARIADB_AUTO_UPGRADE=1
volumes:
- "${SEAFILE_MYSQL_VOLUME:-/data/seafile-mysql/db}:/var/lib/mysql"
networks:
- seafile-net
healthcheck:
test:
[
"CMD",
"/usr/local/bin/healthcheck.sh",
"--connect",
"--mariadbupgrade",
"--innodb_initialized",
]
interval: 20s
start_period: 30s
timeout: 5s
retries: 10

memcached:
image: ${SEAFILE_MEMCACHED_IMAGE:-memcached:1.6.29}
container_name: seafile-memcached
restart: always
entrypoint: memcached -m 256
networks:
- seafile-net

onlyoffice:
image: ${ONLYOFFICE_IMAGE}
container_name: onlyoffice
restart: always
environment:
- JWT_ENABLED=true
- JWT_SECRET=${ONLYOFFICE_JWT_SECRET}
- JWT_HEADER=Authorization
ports:
- "${ONLYOFFICE_PORT}:80"
networks:
- seafile-net

seafile:
image: ${SEAFILE_IMAGE:-seafileltd/seafile-mc:12.0-latest}
container_name: seafile
restart: always
# ports:
# - "80:80"
volumes:
- ${SEAFILE_VOLUME:-/data/seafile-data}:/shared
environment:
- DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
- DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
- DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
- DB_ROOT_PASSWD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
- DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
- SEAFILE_MYSQL_DB_CCNET_DB_NAME=${SEAFILE_MYSQL_DB_CCNET_DB_NAME:-ccnet_db}
- SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=${SEAFILE_MYSQL_DB_SEAFILE_DB_NAME:-seafile_db}
- SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=${SEAFILE_MYSQL_DB_SEAHUB_DB_NAME:-seahub_db}
- TIME_ZONE=${TIME_ZONE:-Etc/UTC}
- INIT_SEAFILE_ADMIN_EMAIL=${INIT_SEAFILE_ADMIN_EMAIL:-me@example.com}
- INIT_SEAFILE_ADMIN_PASSWORD=${INIT_SEAFILE_ADMIN_PASSWORD:-asecret}
- SEAFILE_SERVER_HOSTNAME=${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
- SEAFILE_SERVER_PROTOCOL=${SEAFILE_SERVER_PROTOCOL:-http}
- SITE_ROOT=${SITE_ROOT:-/}
- NON_ROOT=${NON_ROOT:-false}
- JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
- SEAFILE_LOG_TO_STDOUT=${SEAFILE_LOG_TO_STDOUT:-false}
- ENABLE_SEADOC=${ENABLE_SEADOC:-true}
- SEADOC_SERVER_URL=${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}/sdoc-server
labels:
caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
caddy.reverse_proxy: "{{upstreams 80}}"
depends_on:
db:
condition: service_healthy
memcached:
condition: service_started
networks:
- seafile-net

networks:
seafile-net:
name: seafile-net

4.容器操作

.拉取所需镜像

1
2
3
4
5
6
7
docker pull seafileltd/seafile-mc:12.0-latest
docker pull mariadb:10.11
docker pull memcached:1.6.29
docker pull onlyoffice/documentserver:7.3.3 #onlyoffice
docker pull lucaslorentz/caddy-docker-proxy:2.9-alpine #反向代理
docker pull seafileltd/sdoc-server:1.0-latest #文档服务镜像
docker pull seafileltd/notification-server:12.0-latest #拉这个是因为配置了通知服务

在使用docker拉取完所需镜像过后 可以直接使用命令生成所拉取镜像的离线包

1
docker save -o xxxx.tar  xxxx

这样在新的机器上部署可以不用配置docker的镜像加速直接上传镜像的离线包导入镜像

要对这些离线包进行归档以后再上传

1
docker load -i /离线包所在目录

镜像导入完成后,在配置文件编写的目录启动服务

1
docker-compose up -d

之后查看容器运行状态

1
docker ps   

如有问题 启动失败之类的 查看日志 根据日志中具体哪个组件的报错进行分析

1
docker-compose logs -f --tail=200

停止某服务

1
docker-compose stop xxx

以上部署好了所有的的功能(包括onlyoffcie)。

注:onlyoffcie设置

再拉取 启动服务之后。挂在数据的目录下会出现这几个目录:

1
seadoc-data  seafile  seafile-caddy  seafile-data  seafile-mysql

进入seafile-data目录修改一个配置文件

1
vim /data/seafile-data/seafile/conf/seahub_settings.py

在文件末尾添加以下配置:

1
2
3
4
5
6
7
8
9
ENABLE_ONLYOFFICE = True
VERIFY_ONLYOFFICE_CERTIFICATE = False
ONLYOFFICE_APIJS_URL = 'http://你部署的服务的机器ip以及onlyoffice服务的端口号/web-apps/apps/api/documents/api.js'
ONLYOFFICE_FILE_EXTENSION = ('doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx')
ONLYOFFICE_EDIT_FILE_EXTENSION = ('docx', 'pptx', 'xlsx')

# 尝试这些配置键
ONLYOFFICE_JWT_SECRET = '你单独生成的JWT密钥'
ONLYOFFICE_JWT_HEADER = 'Authorization'

重启容器:

1
2
docker-compose restart seafile
docker-compose restart onlyoffice

登录seafile并使用

ps:如果onlyoffcie提示未授权

检查onlyffcie容器日志输出,一般是JWT密钥配置没有与.env文件中的匹配

(部署完成了一个初步安全可用的seafile)