1. 简介

从 6.2.2 版本起,Seatable 的配置方式向 Seafile 的配置模式转变。开始逐步减少 conf 下的配置文件,将这些配置文件的内容全部转移的变量文件中。这个能够保存更精简更易维护的配置文件。在6.2.2 中以下的指令可以用来检测配置文件是否正确有效。

docker exec -it seatable-server /templates/seatable.sh python-env /opt/seatable/seatable-server-latest/dtable-web/manage.py check

详细的升级更新操作步骤可以参考:https://admin.seatable.com/upgrade/extra-upgrade-notice/

官方提供了升级脚本用于实现从 6.1 升级到6.2。脚本内容下载地址https://github.com/seatable/seatable-release/blob/main/compose/migrate/migrate_6.1_6.2.sh。该脚本执行了以下操作:

  • 将 SECRET_KEY 这个变量从  dtable_web_settings.py 迁移到 .env 环境文件
  • 清理 dtable_web_settings.py 中未使用的配置文件设置

另外,这个脚本还检测以下的配置文件情况

  •  dtable-api-gateway.conf, dtable-db.conf, dtable-events.conf, dtable-storage-server.conf 和 dtable_server_config.json 这些配置文件都将被废弃,对应的配置内容全部迁移到 .env 配置文件
  • dtable_web_settings.py 中有关邮件的配置也全部迁移到 .env 变量设置文件

对应废弃的配置文件变量可以参考:https://admin.seatable.com/configuration/components/dtable-api-gateway/

1.1. 参考链接

2. 升级步骤

6.2 版本开始相关的设置信息全部简化到 .env 配置文件中,版本升级大概分为以下几步:

  1. 停止现有版本的服务
  2. 备份现有版本的目录。容器环境仅需备份seatable 对应的文件夹
  3. 下载新版本镜像和升级检查脚本
  4. 执行升级检查脚本
  5. 参照升级检查脚本的提示调整 .env 配置文件的内容,删除 6.2 版本中废弃的配置文件
  6. 调整容器配置文件
  7. 启动容器配置文件

2.1. 检查及故障排查

2.1.1. seatable 无法启动或 web 页面无法打开

Browser -> Domain/DNS -> Caddy -> Nginx -> SeaTable Container -> SeaTable Server(我们这里省略了 Caddy 组件)

2.1.2. 确认 seatable server 服务是否正常

执行 docker logs seatable-server 应该有以下的输出

2024-02-04 12:59:17 Start server
SeaTable started
2024-02-04 12:59:21 For more startup information, please check the /opt/seatable/logs/init.log
2024-02-04 12:59:21 This is an idle script (infinite loop) to keep container running.

docker exec -it seatable-server curl http://127.0.0.1:8000/server-info/

执行上述指令应该有对应的回应。

{"version":"6.1.3","edition":"enterprise edition"}

另外可以通过以下的指令查看 log 日志信息情况。

cd /opt/seatable-compose && docker compose logs -f
tail -f /opt/seatable-server/seatable/logs/*.log

2.1.3. 检查容器健康状态是否正常

执行 docker ps 应该有类似以下的输出

CONTAINER ID   IMAGE                               STATUS                NAMES
0411d977eb25   seatable/seatable-enterprise:6.1.3  Up 3 days (healthy)   seatable-server

2.1.4. 检查 dtable-server

通过以下的指令检查 dtable-server 是否正常。如果没有正常的回应需要检查 moniter.log 日志信息,特定情况下需要调整 DTABLE_SERVER_PING_TIMEOUT 的设定值。

curl https://$SEATABLE_SERVER_HOSTNAME/dtable-server/ping/

变量的设定值需要在 seatable-server.yml 和 .env 文件中配置

2.1.5. 检查 nginx 和 caddy

docker exec -it seatable-server nginx -t
docker logs caddy

对应的输出如下:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

2.1.6. 检查 dtable-web

执行 check-dtable-web.sh 来排查 dtable-web 的故障情况

3. 非 python 环境

3.1. .env

注意新增加 6.2 部分的内容,主要是增加了邮件配置信息和相关的密钥信息。

# components to be used; IMPORTANT: there should be no space between the files names !
COMPOSE_FILE='seatable-server.yml'
COMPOSE_PATH_SEPARATOR=','

# system settings
TIME_ZONE='Asia/Shanghai'

# seatable server url
SEATABLE_SERVER_HOSTNAME='table.waringid.me'
SEATABLE_SERVER_PROTOCOL='https'

# initial web admin
SEATABLE_ADMIN_EMAIL='test@163.com'
SEATABLE_ADMIN_PASSWORD='password'

# database
SEATABLE_MYSQL_ROOT_PASSWORD='password'
MARIADB_PASSWORD='password'

# redis
REDIS_PASSWORD='redis_password'
JWT_PRIVATE_KEY='JWT-key'

SEATABLE_DIR='/rdm_4t/seatable'


# SeaTable v6.2
SECRET_KEY='random password'

SEATABLE_SHOW_TEMPLATES_LINK=true
SEATABLE_TEMPLATE_BASE_API_TOKEN='random password'
SEATABLE_TEMPLATE_TABLE_NAME='templates'
SEATABLE_ENABLE_CREATE_BASE_FROM_TEMPLATE=true

SEATABLE_EMAIL_USE_TLS=True
SEATABLE_EMAIL_HOST='smtp.qq.com'
SEATABLE_EMAIL_HOST_USER='100001@qq.com'
SEATABLE_EMAIL_HOST_PASSWORD='random password'
SEATABLE_EMAIL_PORT=587
SEATABLE_DEFAULT_FROM_EMAIL='100001@qq.com'
SEATABLE_SERVER_EMAIL='100001@qq.com'

DTABLE_BAIDU_MAP_KEY='random password'
PLUGINS_REPO_ID='a5bbeac5-7dea-4092-9d6e-b9198367cb82'

3.2. seatable-server.yml

该配置文件需要注意调整了镜像文件的版本和 Redis 启动命令的内容,增加了内存大小限制

---
services:
  seatable-server:
    image: ${SEATABLE_IMAGE:-seatable/seatable-enterprise:6.2.12}
    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/nginx.conf:/etc/nginx/sites-enabled/default"
      - "${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"
    environment:
      - SEATABLE_MYSQL_DB_HOST=${MARIADB_HOST:-mariadb}
      - SEATABLE_MYSQL_DB_PORT=${MARIADB_PORT:-3306}
      - SEATABLE_MYSQL_DB_USER=root
      - SEATABLE_MYSQL_DB_PASSWORD=${MARIADB_PASSWORD:?Variable is not set or empty}
      - INIT_SEATABLE_MYSQL_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD:-${MARIADB_PASSWORD}}
      - SEATABLE_MYSQL_DB_DTABLE_DB_NAME=dtable_db
      - SEATABLE_MYSQL_DB_CCNET_DB_NAME=ccnet_db
      - SEATABLE_MYSQL_DB_SEAFILE_DB_NAME=seafile_db
      - REDIS_HOST=${REDIS_HOST:-redis}
      - REDIS_PORT=${REDIS_PORT:-6379}
      - REDIS_PASSWORD=${REDIS_PASSWORD:?Variable is not set or empty}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - SECRET_KEY=${SECRET_KEY:?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}
      - ENABLE_PYTHON_SCRIPT=${ENABLE_PYTHON_SCRIPT:-true}
      - PYTHON_SCHEDULER_URL=${PYTHON_SCHEDULER_URL:-http://python-scheduler}
      - PYTHON_SCHEDULER_AUTH_TOKEN=${PYTHON_SCHEDULER_AUTH_TOKEN:-}
      - REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
      - SEATABLE_EMAIL_USE_TLS=${SEATABLE_EMAIL_USE_TLS:-}
      - SEATABLE_EMAIL_HOST=${SEATABLE_EMAIL_HOST:-}
      - SEATABLE_EMAIL_HOST_USER=${SEATABLE_EMAIL_HOST_USER:-}
      - SEATABLE_EMAIL_HOST_PASSWORD=${SEATABLE_EMAIL_HOST_PASSWORD:-}
      - SEATABLE_EMAIL_PORT=${SEATABLE_EMAIL_PORT:-}
      - SEATABLE_DEFAULT_FROM_EMAIL=${SEATABLE_DEFAULT_FROM_EMAIL:-}
      - SEATABLE_SERVER_EMAIL=${SEATABLE_SERVER_EMAIL:-}
      - SEATABLE_SHOW_TEMPLATES_LINK=${SEATABLE_SHOW_TEMPLATES_LINK:-}
      - SEATABLE_TEMPLATE_BASE_API_TOKEN=${SEATABLE_TEMPLATE_BASE_API_TOKEN:-}
      - SEATABLE_TEMPLATE_TABLE_NAME=${SEATABLE_TEMPLATE_TABLE_NAME:-}
      - SEATABLE_ENABLE_CREATE_BASE_FROM_TEMPLATE=${SEATABLE_ENABLE_CREATE_BASE_FROM_TEMPLATE:-}
      - SEATABLE_HELP_LINK=${SEATABLE_HELP_LINK:-https://help.seatable.com}
      - SEATABLE_LOG_LEVEL=${SEATABLE_LOG_LEVEL:-INFO}    
      - ENABLE_SEATABLE_AI=${ENABLE_SEATABLE_AI:-false}
      - SEATABLE_AI_SERVER_URL=${SEATABLE_AI_SERVER_URL:-http://seatable-ai:8888}
    depends_on:
      mariadb:
        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:11.8.5-noble}
    restart: unless-stopped
    container_name: mariadb
    command: ["mariadbd", "--innodb_snapshot_isolation=OFF"]
    environment:
      - MYSQL_ROOT_PASSWORD=${SEATABLE_MYSQL_ROOT_PASSWORD:?Variable is not set or empty}
      - MYSQL_LOG_CONSOLE=true
      - MARIADB_AUTO_UPGRADE=1
      - TZ=${TIME_ZONE}
    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.

  redis:
    image: ${SEATABLE_REDIS_IMAGE:-redis:8.4.0-bookworm}
    restart: unless-stopped
    container_name: redis
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD:?Variable is not set or empty}
    command:
      - /bin/sh
      - -c
      - redis-server --requirepass "$${REDIS_PASSWORD:?REDIS_PASSWORD variable is not set}" --maxmemory "${REDIS_MAX_MEMORY:-500mb}" --maxmemory-policy allkeys-lru
    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

3.3. 删除废弃的配置文件

删除 6.2 版本中已经废弃不再使用的配置文件

rm seatable-server/seatable/conf/dtable-storage-server.conf
rm seatable-server/seatable/conf/dtable-events.conf
rm seatable-server/seatable/conf/dtable-db.conf
rm seatable-server/seatable/conf/dtable_server_config.json
docker-compose -f seatable-server.yml up

3.4. 补充内容(FAQ)

故障现象:版本升级后能正常打开 web 页面并且能正常登录,但是打开具体的表格文件时提示后端服务器错误并且 dtable-api-gateway 提示 404 和 400 错误。其它日志均无异常信息

故障定位:容器镜像、系统服务和端口等均无异常,最后结合 seatable-server.yml 配置文件检查 dtable-storage-server 的挂载位置存在自定义配置。

故障解决:在 .env 中增加 STORAGE_SERVER_FS_PATH 的自定义配置并且在 seatable-server.yml 配置文件中引用。重启后解决

4. python 环境

6.2 版本中 python 环境有一些调整。之前的版本无需调用 Redis 资源,6.2版本使用了 Redis 。

  • 需要在 yml 配置文件中增加对应的内容,另外需要调整 Redis 容器的网络设置,确保 python 环境能正确调用 Redis 服务器。
  • 运行 python 脚本时需要注意超时时间,默认配置的超时时间时 60s,如果需要更长的执行操作需要调整该配置。

4.1. .env

# components to be used; IMPORTANT: there should be no space between the files names !
COMPOSE_FILE='seatable-server.yml'
COMPOSE_PATH_SEPARATOR=','

# system settings
TIME_ZONE='Asia/Shanghai'

# seatable server url
SEATABLE_SERVER_HOSTNAME='seatable.waringid.me'
SEATABLE_SERVER_PROTOCOL='https'

# initial web admin
SEATABLE_ADMIN_EMAIL='test@163.com'
SEATABLE_ADMIN_PASSWORD='random-password'

# database
SEATABLE_MYSQL_ROOT_PASSWORD='random-password'

SEATABLE_DIR='/data/seatable'


SEATABLE_PYTHON_PIPELINE_MYSQL_DB_HOST=db
SEATABLE_PYTHON_PIPELINE_DB_NAME=scheduler
SEATABLE_PYTHON_PIPELINE_MYSQL_ROOT_PASSWORD='random-password'
SEATABLE_PYTHON_PIPELINE_MYSQL_USER=python
SEATABLE_PYTHON_PIPELINE_MYSQL_PASSWORD='random-password'
#SEATABLE_PYTHON_PIPELINE_MYSQL_VOLUMNS=/data/seatable/python-pipeline/mysql-data
PYTHON_TRANSFER_DIRECTORY_PATH=/data/seatable/python-pipeline/tmp
PYTHON_SCHEDULER_AUTH_TOKEN=random-password
PYTHON_SCHEDULER_URL=http://python-scheduler
PYTHON_SCHEDULER_LOGS_DIR=/data/seatable/python-pipeline/logs/scheduler-logs
PYTHON_STARTER_USE_ALTERNATIVE_FILE_SERVER_ROOT=True
PYTHON_STARTER_ALTERNATIVE_FILE_SERVER_ROOT=http://seatable-server
PYTHON_STARTER_LOGS_DIR=/data/seatable/python-pipeline/logs/starter-logs
SEATABLE_SCHEDULER_IMAGE=seatable/seatable-python-scheduler:6.2.1
SEATABLE_STARTER_IMAGE=seatable/seatable-python-starter:6.2.1
SEATABLE_RUNNER_IMAGE=seatable/seatable-python-runner:6.2.2

REDIS_PASSWORD='random-password'
JWT_PRIVATE_KEY='random-password'
SEATABLE_MYSQL_ROOT_PASSWORD='random-password'
MARIADB_PASSWORD='random-password'

# SeaTable v6.2
SECRET_KEY='random-password'

ENABLE_SEATABLE_AI=false

SEATABLE_EMAIL_USE_TLS=True
SEATABLE_EMAIL_HOST='smtp.gmail.com'
SEATABLE_EMAIL_HOST_USER='username@gmail.com'
SEATABLE_EMAIL_HOST_PASSWORD='password'
SEATABLE_EMAIL_PORT=587
SEATABLE_DEFAULT_FROM_EMAIL='username@gmail.com'
SEATABLE_SERVER_EMAIL='username@gmail.com'

TEMPLATE_BASE_API_TOKEN='random-password'  
TEMPLATE_TABLE_NAME='templates'
ENABLE_CREATE_BASE_FROM_TEMPLATE=True
SHOW_TEMPLATES_LINK=True

DTABLE_BAIDU_MAP_KEY='random-password'
PLUGINS_REPO_ID='a5bbeac5-7dea-4092-9d6e-b9198367cb82'

SEATABLE_FAAS_URL='http://python-scheduler'
SEATABLE_FAAS_AUTH_TOKEN='random-password'

4.2. seatable-server.yml

---
services:
  seatable-server:
    image: ${SEATABLE_IMAGE:-seatable/seatable-enterprise:6.2.12}
    restart: unless-stopped
    container_name: seatable-server
    ports:
      - "8006:80"
    volumes:
      - "${SEATABLE_DIR}/seatable-server:/shared"
      - "${SEATABLE_DIR}/deps/nginx.conf:/etc/nginx/sites-enabled/default"
      - "${SEATABLE_DIR}/deps/seatable.sh:/templates/seatable.sh:rx"
      - "${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"
    environment:
      - SEATABLE_MYSQL_DB_HOST=${MARIADB_HOST:-mariadb}
      - SEATABLE_MYSQL_DB_PORT=${MARIADB_PORT:-3306}
      - SEATABLE_MYSQL_DB_USER=root
      - SEATABLE_MYSQL_DB_PASSWORD=${MARIADB_PASSWORD:?Variable is not set or empty}
      - INIT_SEATABLE_MYSQL_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD:-${MARIADB_PASSWORD}}
      - SEATABLE_MYSQL_DB_DTABLE_DB_NAME=dtable_db
      - SEATABLE_MYSQL_DB_CCNET_DB_NAME=ccnet_db
      - SEATABLE_MYSQL_DB_SEAFILE_DB_NAME=seafile_db
      - REDIS_HOST=${REDIS_HOST:-redis}
      - REDIS_PORT=${REDIS_PORT:-6379}
      - REDIS_PASSWORD=${REDIS_PASSWORD:?Variable is not set or empty}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - SECRET_KEY=${SECRET_KEY:?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}
      - ENABLE_PYTHON_SCRIPT=${ENABLE_PYTHON_SCRIPT:-true}
      - PYTHON_SCHEDULER_URL=${PYTHON_SCHEDULER_URL:-http://python-scheduler}
      - PYTHON_SCHEDULER_AUTH_TOKEN=${PYTHON_SCHEDULER_AUTH_TOKEN:-}
      - REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
      - SEATABLE_EMAIL_USE_TLS=${SEATABLE_EMAIL_USE_TLS:-}
      - SEATABLE_EMAIL_HOST=${SEATABLE_EMAIL_HOST:-}
      - SEATABLE_EMAIL_HOST_USER=${SEATABLE_EMAIL_HOST_USER:-}
      - SEATABLE_EMAIL_HOST_PASSWORD=${SEATABLE_EMAIL_HOST_PASSWORD:-}
      - SEATABLE_EMAIL_PORT=${SEATABLE_EMAIL_PORT:-}
      - SEATABLE_DEFAULT_FROM_EMAIL=${SEATABLE_DEFAULT_FROM_EMAIL:-}
      - SEATABLE_SERVER_EMAIL=${SEATABLE_SERVER_EMAIL:-}
      - SEATABLE_SHOW_TEMPLATES_LINK=${SEATABLE_SHOW_TEMPLATES_LINK:-}
      - SEATABLE_TEMPLATE_BASE_API_TOKEN=${SEATABLE_TEMPLATE_BASE_API_TOKEN:-}
      - SEATABLE_TEMPLATE_TABLE_NAME=${SEATABLE_TEMPLATE_TABLE_NAME:-}
      - SEATABLE_ENABLE_CREATE_BASE_FROM_TEMPLATE=${SEATABLE_ENABLE_CREATE_BASE_FROM_TEMPLATE:-}
      - SEATABLE_HELP_LINK=${SEATABLE_HELP_LINK:-https://help.seatable.com}
      - SEATABLE_LOG_LEVEL=${SEATABLE_LOG_LEVEL:-INFO}
      - ENABLE_SEATABLE_AI=${ENABLE_SEATABLE_AI:-false}
      - SEATABLE_AI_SERVER_URL=${SEATABLE_AI_SERVER_URL:-http://seatable-ai:8888}
    depends_on:
      mariadb:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - frontend-net
      - backend-seatable-net
    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:11.8.5-noble}
    restart: unless-stopped
    container_name: mariadb
    command: ["mariadbd", "--innodb_snapshot_isolation=OFF"]
    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.
 
  redis:
    image: ${SEATABLE_REDIS_IMAGE:-redis:8.4.0-bookworm}
    restart: unless-stopped
    container_name: redis
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD:?Variable is not set or empty}
    command:
      - /bin/sh
      - -c
      - redis-server --requirepass "$${REDIS_PASSWORD:?REDIS_PASSWORD variable is not set}" --maxmemory "${REDIS_MAX_MEMORY:-500mb}" --maxmemory-policy allkeys-lru
    networks:
      - backend-seatable-net
      - backend-scheduler-net
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 20s
      retries: 3
      timeout: 5s
 
  python-scheduler:
    image: ${SEATABLE_SCHEDULER_IMAGE:-seatable/seatable-python-scheduler:6.2.1}
    restart: unless-stopped
    container_name: python-scheduler
    environment:
      - TIME_ZONE=${TIME_ZONE}
      - DATABASE_NAME=${SEATABLE_PYTHON_PIPELINE_MYSQL_DB_NAME:-scheduler}
      - DB_HOST=mariadb
      - DB_ROOT_PASSWD=${SEATABLE_PYTHON_PIPELINE_MYSQL_ROOT_PASSWORD:-}
      - DB_USER=${SEATABLE_PYTHON_PIPELINE_MYSQL_USER:-}
      - DB_PASSWD=${SEATABLE_PYTHON_PIPELINE_MYSQL_PASSWORD:-}
      - REDIS_HOST=${REDIS_HOST:-redis}
      - REDIS_PORT=${REDIS_PORT:-6379}
      - REDIS_PASSWORD=${REDIS_PASSWORD:?Variable is not set or empty}
      - PYTHON_SCHEDULER_AUTH_TOKEN=${PYTHON_SCHEDULER_AUTH_TOKEN:?Variable is not set or empty}
      - SEATABLE_SERVER_URL=${SEATABLE_SERVER_PROTOCOL:-https}://${SEATABLE_SERVER_HOSTNAME}
      - PYTHON_SCHEDULER_LOG_LEVEL=${PYTHON_SCHEDULER_LOG_LEVEL:-WARNING}
      - DELETE_LOG_DAYS=${DELETE_LOG_DAYS:-30}
      - PYTHON_SCHEDULER_WINDOW_SECS=${PYTHON_SCHEDULER_WINDOW_SECS:-300}
      - PYTHON_SCHEDULER_RATE_LIMIT_PERCENT=${PYTHON_SCHEDULER_RATE_LIMIT_PERCENT:-0.25}
      - PYTHON_STARTER_TOTAL_THREAD_COUNT=${PYTHON_STARTER_TOTAL_THREAD_COUNT:-10}
      # Timeout is defined in seconds
      - PYTHON_PROCESS_TIMEOUT=${PYTHON_PROCESS_TIMEOUT:-600}
      - REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
      - LOG_TO_STDOUT=true

    volumes:
      - "${PYTHON_SCHEDULER_LOGS_DIR:-/tmp}:/opt/scheduler/logs"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    networks:
      - backend-scheduler-net
      - frontend-net
      - backend-seatable-net
    depends_on:
      mariadb:
        condition: service_healthy
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "pgrep -f 'python3 scheduler.py' && pgrep -f 'python3 flask_server.py'",
        ]
      interval: 20s
      retries: 3
      start_period: 20s
      timeout: 10s
 
  python-starter:
    image: ${SEATABLE_STARTER_IMAGE:-seatable/seatable-python-starter:6.2.1}
    restart: unless-stopped
    container_name: python-starter

    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "${PYTHON_TRANSFER_DIRECTORY_PATH:-/tmp}:${PYTHON_TRANSFER_DIRECTORY_PATH:-/tmp}"
      - "${PYTHON_STARTER_LOGS_DIR:-/tmp}:/opt/seatable-python-starter/logs"
    environment:
      - TIME_ZONE=${TIME_ZONE}
      - REDIS_HOST=${REDIS_HOST:-redis}
      - REDIS_PORT=${REDIS_PORT:-6379}
      - REDIS_PASSWORD=${REDIS_PASSWORD:?Variable is not set or empty}
      - PYTHON_SCHEDULER_URL=${PYTHON_SCHEDULER_URL:-http://python-scheduler}
      - PYTHON_TRANSFER_DIRECTORY=${PYTHON_TRANSFER_DIRECTORY_PATH:-/tmp}
      - PYTHON_RUNNER_IMAGE=${PYTHON_RUNNER_IMAGE:-seatable/seatable-python-runner:6.2.2}
      - PYTHON_STARTER_LOG_LEVEL=${PYTHON_STARTER_LOG_LEVEL:-WARNING}
      - PYTHON_RUNNER_CONTAINER_CPUS=${PYTHON_RUNNER_CONTAINER_CPUS:-1}
      - PYTHON_RUNNER_CONTAINER_MEMORY=${PYTHON_RUNNER_CONTAINER_MEMORY:-1g}
      # Timeout is defined in seconds
      - PYTHON_PROCESS_TIMEOUT=${PYTHON_PROCESS_TIMEOUT:-60}
      - PYTHON_RUNNER_READ_ONLY_FILESYSTEM=${PYTHON_RUNNER_READ_ONLY_FILESYSTEM:-true}
      - PYTHON_RUNNER_TMPFS_MOUNT_SIZE_IN_BYTES=${PYTHON_RUNNER_TMPFS_MOUNT_SIZE_IN_BYTES:-104857600}
      - PYTHON_RUNNER_DROPPED_CAPABILITIES=${PYTHON_RUNNER_DROPPED_CAPABILITIES:-CAP_NET_RAW}
      - PYTHON_RUNNER_NO_NEW_PRIVILEGES=${PYTHON_RUNNER_NO_NEW_PRIVILEGES:-true}
      - REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
      - LOG_TO_STDOUT=true
    networks:
      - backend-scheduler-net
      - frontend-net

  python-runner:
    image: ${PYTHON_RUNNER_IMAGE:-seatable/seatable-python-runner:6.2.2}
    restart: unless-stopped
    container_name: python-runner
    networks:
      # This is added to ensure that the runner-net network is created
      # Docker-Compose does not seem to create networks that are not used by any containers in the compose file(s)
      - runner-net

networks:
  frontend-net:
    name: frontend-net
  backend-seatable-net:
    name: backend-seatable-net
  backend-scheduler-net:
    name: backend-scheduler-net
  runner-net:
    name: runner-net
    driver: bridge
    driver_opts:
      # Disable inter-container connectivity
      com.docker.network.bridge.enable_icc: "false"

4.3. qr-code.py

from seatable_api import Base, context
import qrcode
from io import BytesIO

base = Base(context.api_token, context.server_url)
base.auth()

TABLE_NAME = "商品"
TEXT_COLUMN = "主码"
IMAGE_COLUMN = "条码"
OVERWRITE = False

rows = base.list_rows(TABLE_NAME)
for row in rows:
    text = row.get(TEXT_COLUMN)
    existing = row.get(IMAGE_COLUMN)
    if not text or (existing and not OVERWRITE):
        continue

    qr = qrcode.QRCode(version=2, error_correction=qrcode.constants.ERROR_CORRECT_M, box_size=10, border=4)
    qr.add_data(text)
    qr.make(fit=True)
    img = qr.make_image(fill_color="black", back_color="white")

    buf = BytesIO()
    img.save(buf, format='PNG')
    buf.seek(0)

    info = base.upload_bytes_file(str(text) + '.png', buf.read(), file_type='image')
    base.update_row(TABLE_NAME, row['_id'], {IMAGE_COLUMN: [info.get('url')]})

print("QR codes generated.")

  • 无标签
写评论...