环境配置
.env 配置容器运行中的环境变量,在涉及容器镜像版本调整或更改时仅需调整 .env 文件
...
信息 |
---|
官网默认启用 caddy 用来实现网关应用和域名的 https 证书管理,这里直接使用内置的 nginx |
seatable.yml
代码块 |
---|
|
---
services:
seatable-server:
image: ${SEATABLE_IMAGE:-seatable/seatable-enterprise:4.3.8}
restart: unless-stopped
container_name: seatable-server
ports:
- "8006:80"
volumes:
- "${SEATABLE_DIR}/seatable-server:/shared"
- "${SEATABLE_DIR}/deps/seatable.sh:/templates/seatable.sh:rx"
- "${SEATABLE_DIR}/deps/seatable-license.txt:/shared/seatable/seatable-license.txt"
- "${SEATABLE_DIR}/deps/licenseparse.py:/opt/seatable/seatable-server-latest/dtable-web/seahub/utils/licenseparse.py:rw"
- "${SEATABLE_DIR}/deps/seafile-controller:/opt/seatable/seatable-server-latest/seafile/bin/seafile-controller:rw"
- "${SEATABLE_DIR}/deps/seaf-server:/opt/seatable/seatable-server-latest/seafile/bin/seaf-server:rw"
# - type: bind
# source: "./seatable-license.txt"
# target: "/shared/seatable/seatable-license.txt"
# read_only: ${SEATABLE_LICENSE_FORCE_READ_ONLY:-false}
environment:
- DB_HOST=mariadb
- DB_ROOT_PASSWD=${SEATABLE_MYSQL_ROOT_PASSWORD:?Variable is not set or empty}
- SEATABLE_SERVER_HOSTNAME=${SEATABLE_SERVER_HOSTNAME:?Variable is not set or empty}
- SEATABLE_SERVER_PROTOCOL=${SEATABLE_SERVER_PROTOCOL:-https}
- SEATABLE_ADMIN_EMAIL=${SEATABLE_ADMIN_EMAIL:?Variable is not set or empty}
- SEATABLE_ADMIN_PASSWORD=${SEATABLE_ADMIN_PASSWORD:?Variable is not set or empty}
- TIME_ZONE=${TIME_ZONE}
depends_on:
mariadb:
condition: service_healthy
memcached:
condition: service_healthy
redis:
condition: service_healthy
networks:
- frontend-net
- backend-seatable-net
# healthcheck specifically for dtable-web
healthcheck:
test: ["CMD-SHELL", "curl --fail http://localhost:8000 || exit 1"]
interval: 20s
retries: 3
start_period: 30s
timeout: 10s
mariadb:
image: ${SEATABLE_DB_IMAGE:-mariadb:10.11.6}
restart: unless-stopped
container_name: mariadb
environment:
- MYSQL_ROOT_PASSWORD=${SEATABLE_MYSQL_ROOT_PASSWORD:?Variable is not set or empty}
- MYSQL_LOG_CONSOLE=true
- MARIADB_AUTO_UPGRADE=1
volumes:
- "${SEATABLE_DIR}/mariadb:/var/lib/mysql"
networks:
- backend-seatable-net
healthcheck:
test:
[
"CMD",
"/usr/local/bin/healthcheck.sh",
"--connect",
"--mariadbupgrade",
"--innodb_initialized",
]
interval: 20s
retries: 3
start_period: 30s
timeout: 10s
# On older database containers without healthcheck users present you might need to create them manually,
# otherwise the container stays unhealthy.
memcached:
image: ${SEATABLE_MEMCACHED_IMAGE:-memcached:1.6.22}
restart: unless-stopped
container_name: memcached
entrypoint: memcached -m 256
networks:
- backend-seatable-net
healthcheck:
test: ["CMD-SHELL", "timeout 2 bash -c '</dev/tcp/localhost/11211'"]
interval: 20s
retries: 3
timeout: 5s
redis:
image: ${SEATABLE_REDIS_IMAGE:-redis:7.2.3}
restart: unless-stopped
container_name: redis
networks:
- backend-seatable-net
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 20s
retries: 3
timeout: 5s
networks:
frontend-net:
name: frontend-net
backend-seatable-net:
name: backend-seatable-net |
信息 |
---|
注意:需要申请 seatable-license.txt 文件。在初始化的过程中需要校验 license 文件创建对应的 repo 文件夹,在初始化时会有错误的日志提示。 |
seatable-server/seatable/conf/dtable_web_settings.py
代码块 |
---|
|
IS_PRO_VERSION = True
CSRF_TRUSTED_ORIGINS = ['https://table.waringid.me']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': 'mariadb',
'PORT': '3306',
'USER': 'root',
'PASSWORD': 'password',
'NAME': 'dtable_db',
'OPTIONS': {
'charset': 'utf8mb4',
},
}
}
CACHES = {
'default': {
'BACKEND': 'django_pylibmc.memcached.PyLibMCCache',
'LOCATION': 'memcached',
},
'locmem': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
},
}
COMPRESS_CACHE_BACKEND = 'locmem'
SECRET_KEY = '1_n338k*han@4$b'
# for dtable-server
DTABLE_PRIVATE_KEY = 'h@6d%re+(=0nfs!k3_k'
DTABLE_SERVER_URL = 'https://table.waringid.me/dtable-server/'
DTABLE_SOCKET_URL = 'https://table.waringid.me/'
# for dtable-web
DTABLE_WEB_SERVICE_URL = 'https://table.waringid.me/'
# for dtable-db
DTABLE_DB_URL = 'https://table.waringid.me/dtable-db/'
# for dtable-storage-server
DTABLE_STORAGE_SERVER_URL = 'http://127.0.0.1:6666/'
NEW_DTABLE_IN_STORAGE_SERVER = True
# for seaf-server
FILE_SERVER_ROOT = 'https://table.waringid.me/seafhttp/'
ENABLE_USER_TO_SET_NUMBER_SEPARATOR = True
TIME_ZONE = 'Asia/Shanghai'
DISABLE_ADDRESSBOOK_V1 = True
ENABLE_ADDRESSBOOK_V2 = True
TEMPLATE_BASE_API_TOKEN = '36fa233b4a0363d0331c223dfeaa480cc461f265'
TEMPLATE_TABLE_NAME = 'templates'
ENABLE_CREATE_BASE_FROM_TEMPLATE = True
SHOW_TEMPLATES_LINK = True
DTABLE_BAIDU_MAP_KEY = 'PlhFWpA02aoURjAOpnWcRGqw7AI8EEyO'
PLUGINS_REPO_ID='a5bbeac5-7dea-4092-9d6e-b9198367cb82' |
信息 |
---|
还需要记得调整 nginx 中关于 hostname 的设置 |
日常维护
信息 |
---|
注意:如果没有设置 “CSRF_TRUSTED_ORIGINS = ['https://table.waringid.me']” 会出现下图所示的安全提醒。 |
Image Added
模板配置
模板配置参考官网说明 Templates and Manual - SeaTable Admin Manual
- 新建 templates 的群组 【需要管理员权限】
- 在 templates 群组下新建 “Templates and Plugins” 的 Base 表格
- 在 Base 表格中新建 templates 表格,表格内容和格式如图示
Image AddedImage AddedImage Added
Seatable 自带的 Nginx 配置
seatable 自带 Nginx ,这里没有采用官网推荐的 Docker 再增加 caddy 的方式而是直接引用自带的 Nginx ,在部署后的测试过程中发生过很多问题。主要集中在“导入外部文件时提示网络错误”、“打开模板功能链接时提示网络错误”、dtable_web.log 提示“无法访问 API ,后端服务器拒绝”等错误提示。
本文网络访问环境的流程如下
1、DNS 二级域名解析到 Cpolar (提供 ddns 服务)的 Cname【已提前在 cpolar 的控制界面增加预留的二级域名】
2、在容器上启用 cpolar 客户端,配置该客户端将二级域名解析到 WAF 代理【另一个 WAF 容器】同时启用自定义的 SSL 证书
3、WAF 容器监听80 端口,通过 hostname 的方式解析到后端具体的服务器
4、Seatable 容器对外映射8006 端口(内部端口80),seatable 容器本身没有启用 SSL
外网访问 https://table.waringid.me 时自动解析到 seatable 的 8006 端口。出现上述问题的主要原因是:seatable 内置的 nginx 配置并没有启用 SSL ,当外部的 https 传入内部时会出现无法访问后端服务器(443端口)的网络错误和超时提醒。所以需要在 Nginx 的配置文件中增加对应的 SSL 配置。另外需要在容器的宿主机中增加外部域名的本地解析,例如将 table.waringid.me 解析到 127.0.0.1 【/etc/hosts】
代码块 |
---|
|
server {
server_name table.waringid.me 127.0.0.1 192.168.77.12;
listen 443 ssl;
ssl_certificate /shared/ssl/waringid.cer;
ssl_certificate_key /shared/ssl/waringid.key;
proxy_set_header X-Forwarded-For $remote_addr;
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Allow-Headers "deviceType,token, authorization, content-type";
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Allow-Headers "deviceType,token, authorization, content-type";
return 204;
}
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_read_timeout 1200s;
# used for view/edit office file via Office Online Server
client_max_body_size 0;
access_log /opt/nginx-logs/dtable-web.access.log seatableformat;
error_log /opt/nginx-logs/dtable-web.error.log;
}
location /seafhttp {
rewrite ^/seafhttp(.*)$ $1 break;
proxy_pass http://127.0.0.1:8082;
client_max_body_size 0;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_request_buffering off;
proxy_connect_timeout 36000s;
proxy_read_timeout 36000s;
proxy_send_timeout 36000s;
send_timeout 36000s;
access_log /opt/nginx-logs/seafhttp.access.log seatableformat;
error_log /opt/nginx-logs/seafhttp.error.log;
}
location /media {
root /opt/seatable/seatable-server-latest/dtable-web;
}
location /socket.io {
proxy_pass http://dtable_servers;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_redirect off;
proxy_buffers 8 32k;
proxy_buffer_size 64k;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
access_log /opt/nginx-logs/socket-io.access.log seatableformat;
error_log /opt/nginx-logs/socket-io.error.log;
}
location /dtable-server {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Allow-Headers "deviceType,token, authorization, content-type";
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Allow-Headers "deviceType,token, authorization, content-type";
return 204;
}
rewrite ^/dtable-server/(.*)$ /$1 break;
proxy_pass http://dtable_servers;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 100m;
access_log /opt/nginx-logs/dtable-server.access.log seatableformat;
error_log /opt/nginx-logs/dtable-server.error.log;
}
location /dtable-db/ {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Allow-Headers "deviceType,token, authorization, content-type";
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Allow-Headers "deviceType,token, authorization, content-type";
return 204;
}
proxy_pass http://127.0.0.1:7777/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto $scheme;
access_log /opt/nginx-logs/dtable-db.access.log seatableformat;
error_log /opt/nginx-logs/dtable-db.error.log;
} |
日常维护
数据库备份
代码块 |
---|
cd /opt/seatable-backup/databases
docker exec -it seatable-mysql mysqldump -uroot -pMYSQL_ROOT_PASSWORD --opt ccnet_db > ccnet_db.sql
docker exec -it seatable-mysql mysqldump -uroot -pMYSQL_ROOT_PASSWORD --opt seafile_db > seafile_db.sql
docker exec -it seatable-mysql mysqldump -uroot -pMYSQL_ROOT_PASSWORD --opt dtable_db > dtable_db.sql |
数据文件备份
代码块 |
---|
rsync -az --exclude 'ccnet' --exclude 'logs' --exclude 'db-data' /opt/seatable/seatable-data/seatable /opt/seatable-backup/seatable |
dtable-db 备份
代码块 |
---|
docker exec -it seatable /opt/seatable/scripts/seatable.sh backup-all |
数据库恢复
代码块 |
---|
docker exec -i seatable-mysql /usr/bin/mysql -uroot -pMYSQL_ROOT_PASSWORD ccnet_db < /opt/seatable-backup/databases/ccnet_db.sql
docker exec -i seatable-mysql /usr/bin/mysql -uroot -pMYSQL_ROOT_PASSWORD seafile_db < /opt/seatable-backup/databases/seafile_db.sql
docker exec -i seatable-mysql /usr/bin/mysql -uroot -pMYSQL_ROOT_PASSWORD dtable_db < /opt/seatable-backup/databases/dtable_db.sql |
恢复数据文件
代码块 |
---|
rsync -az /opt/seatable-backup/seatable /opt/seatable/seatable-data/seatable |
恢复 dtable-db 文件
代码块 |
---|
docker exec -it seatable /opt/seatable/scripts/seatable.sh restore-all |
更改域名配置
docker exec -it seatable /opt/seatable/scripts/seatable.sh restore-all |
更改域名配置
代码块 |
---|
$ docker exec -it seatable /bin/bash
# for one base
$ seatable.sh python-env /opt/seatable/seatable-server-latest/dtable-web/manage.py domain_transfer -uuid <:base uuid> -od <:old domain> -nd <:new domain> |
代码块 |
---|
$ docker exec -it seatable /bin/bash
# for oneall basebases
$ seatable.sh python-env /opt/seatable/seatable-server-latest/dtable-web/manage.py domain_transfer -uuid <:base uuid> all -od <:old domain> -nd <:new domain>
# for all bases
$ seatable.sh python-env /opt/seatable/seatable-server-latest/dtable-web/manage.py domain_transfer -alluuid 695fa115-4927-4be1-b5b6-fbbbabd43b72 -od <:old domain> -nd <:new domain>
seatable.sh python-env /opt/seatable/seatable-server-latest/dtable-web/manage.py domain_transfer -uuid 695fa115-4927-4be1-b5b6-fbbbabd43b72 -od https://dev.seatable.cn -nd https://cloud.seatable.io |
增加用户
...
https://dev.seatable.cn -nd https://cloud.seatable.io |
增加用户
代码块 |
---|
docker exec -it seatable-server /shared/seatable/scripts/seatable.sh superuser |
增加脚本运行功能