Hello everyone,
I’m trying to migrate my Seafile instance from the Community Edition to the Professional Edition and I’m running into a database-related error that prevents the server from starting.
My goal is to perform a simple migration first, without enabling full-text search (Elasticsearch) for now.
Environment:
- Seafile Version: 13.0.11 (migrating from CE 13.0.11 to Pro 13.0.11)
- Deployment: Using Docker Compose
My Process:
My migration process was to simply change the image name in my docker-compose.yml file for the seafile service:
- From:
seafileltd/seafile-mc:13.0-latest - To:
seafileltd/seafile-pro-mc:13.0-latest
After making this change and running docker-compose up -d, the seafile container fails to start.
Error Log:
The container log shows the following critical error, indicating a missing database column. It seems a database schema upgrade is required.
seafile-1 | 2025-10-14T12:55:22.796376000Z [seaf-server] [2025-10-14 08:55:22] [WARNING] ../common/seaf-db-mysql.c(239): Failed to prepare sql SELECT COUNT(id) FROM EmailUser WHERE is_active = 1 AND is_department_owner = 0: Unknown column 'is_department_owner' in 'WHERE'
seafile-1 | 2025-10-14T12:55:22.796412000Z [seaf-server] [2025-10-14 08:55:22] [WARNING] ../common/user-mgr.c(97): Failed to get user number from DB.
seafile-1 | 2025-10-14T12:55:22.796444000Z [seaf-server] [2025-10-14 08:55:22] [WARNING] seafile-session.c(699): Failed to init user manager.
seafile-1 | 2025-10-14T12:55:23.769361000Z Failed to start seafile server
seafile-1 | 2025-10-14T12:55:23.779543000Z Traceback (most recent call last):
seafile-1 | 2025-10-14T12:55:23.779772000Z File "/scripts/start.py", line 94, in
seafile-1 | 2025-10-14T12:55:23.780441000Z main()
seafile-1 | 2025-10-14T12:55:23.780810000Z File "/scripts/start.py", line 79, in main
seafile-1 | 2025-10-14T12:55:23.781011000Z call('{} start'.format(get_script('seafile.sh')))
seafile-1 | 2025-10-14T12:55:23.781240000Z File "/scripts/utils.py", line 71, in call
seafile-1 | 2025-10-14T12:55:23.782362000Z return subprocess.check_call(*a, **kw)
seafile-1 | 2025-10-14T12:55:23.782410000Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
seafile-1 | 2025-10-14T12:55:23.782442000Z File "/usr/lib/python3.12/subprocess.py", line 413, in check_call
seafile-1 | 2025-10-14T12:55:23.782489000Z raise CalledProcessError(retcode, cmd)
seafile-1 | 2025-10-14T12:55:23.782514000Z subprocess.CalledProcessError: Command '/opt/seafile/seafile-pro-server-13.0.11/seafile.sh start' returned non-zero exit status 1.
My docker-compose.yml:
Here is my full docker-compose.yml file (with the Pro image configured in the seafile service).
services:
db:
image: mariadb:10
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${INIT_SEAFILE_MYSQL_ROOT_PASSWORD}
MYSQL_LOG_CONSOLE: true
MARIADB_AUTO_UPGRADE: 1
volumes:
- ${DATA_PATH}/seafile/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
redis:
image: redis
restart: unless-stopped
command: ["sh", "-c", "redis-server --requirepass \"$$REDIS_PASSWORD\""]
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD}
volumes:
- ${DATA_PATH}/seafile/redis:/data
networks:
- seafile_net
seafile:
image: seafileltd/seafile-pro-mc:13.0-latest
restart: unless-stopped
volumes:
- ${SEAFILE_PATH}/files:/shared
environment:
SEAFILE_MYSQL_DB_HOST: db
SEAFILE_MYSQL_DB_PORT: 3306
SEAFILE_MYSQL_DB_USER: seafile
SEAFILE_MYSQL_DB_PASSWORD: ${SEAFILE_MYSQL_DB_PASSWORD}
# INIT_SEAFILE_MYSQL_ROOT_PASSWORD: ${INIT_SEAFILE_MYSQL_ROOT_PASSWORD}
SEAFILE_MYSQL_DB_CCNET_DB_NAME: ccnet_db
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME: seafile_db
SEAFILE_MYSQL_DB_SEAHUB_DB_NAME: seahub_db
TIME_ZONE: ${TIME_ZONE:-Etc/UTC}
SEAFILE_LOG_TO_STDOUT: ${SEAFILE_LOG_TO_STDOUT:-true}
# INIT_SEAFILE_ADMIN_EMAIL: ${INIT_SEAFILE_ADMIN_EMAIL:-admin@example.com}
# INIT_SEAFILE_ADMIN_PASSWORD: ${INIT_SEAFILE_ADMIN_PASSWORD:-asecret}
SEAFILE_SERVER_HOSTNAME: ${SEAFILE_SERVER_HOSTNAME}
SEAFILE_SERVER_PROTOCOL: https
JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY}
ENABLE_SEADOC: true
SEADOC_SERVER_URL: https://${SEAFILE_SERVER_HOSTNAME}/sdoc-server
CACHE_PROVIDER: redis
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD}
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
networks:
- seafile_net
- caddy_seafile_net
seadoc:
image: seafileltd/sdoc-server:2.0-latest
restart: unless-stopped
volumes:
- ${SEAFILE_PATH}/docs:/shared
environment:
DB_HOST: db
DB_PORT: 3306
DB_USER: seafile
DB_PASSWORD: ${SEAFILE_MYSQL_DB_PASSWORD}
DB_NAME: seahub_db
TIME_ZONE: ${TIME_ZONE:-Etc/UTC}
JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY}
SEAHUB_SERVICE_URL: http://seafile
depends_on:
db:
condition: service_healthy
networks:
- seafile_net
- caddy_seafile_net
notification-server:
image: seafileltd/notification-server:13.0-latest
restart: unless-stopped
volumes:
- ${SEAFILE_PATH}/logs:/shared/logs
environment:
SEAFILE_MYSQL_DB_HOST: db
SEAFILE_MYSQL_DB_PORT: 3306
SEAFILE_MYSQL_DB_USER: seafile
SEAFILE_MYSQL_DB_PASSWORD: ${SEAFILE_MYSQL_DB_PASSWORD}
SEAFILE_MYSQL_DB_CCNET_DB_NAME: ccnet_db
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME: seafile_db
JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY}
SEAFILE_LOG_TO_STDOUT: ${SEAFILE_LOG_TO_STDOUT:-true}
NOTIFICATION_SERVER_LOG_LEVEL: ${NOTIFICATION_SERVER_LOG_LEVEL:-info}
depends_on:
db:
condition: service_healthy
networks:
- seafile_net
- caddy_seafile_net
onlyoffice:
image: onlyoffice/documentserver:latest
restart: unless-stopped
environment:
#DB_TYPE: ${DB_TYPE:-mariadb}
#DB_HOST: ${SEAFILE_MYSQL_DB_HOST:-db}
#DB_USER: ${SEAFILE_MYSQL_DB_USER:-seafile}
#DB_PWD: ${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
JWT_ENABLED: true
JWT_SECRET: ${ONLYOFFICE_JWT_SECRET:?Variable is not set or empty}
volumes:
- ${DATA_PATH}/seafile/onlyoffice/data:/var/www/onlyoffice/Data
- ${DATA_PATH}/seafile/onlyoffice/logs:/var/log/onlyoffice
- ${DATA_PATH}/seafile/onlyoffice/lib:/var/lib/onlyoffice
- ${DATA_PATH}/seafile/onlyoffice/db:/var/lib/postgresql
- ${DATA_PATH}/seafile/onlyoffice/redis:/var/lib/redis
- ${DATA_PATH}/seafile/onlyoffice/rabbitmq:/var/lib/rabbitmq
- ${DATA_PATH}/seafile/onlyoffice/fonts:/usr/share/fonts/truetype/custom
networks:
- caddy_seafile_net
seafile-md-server:
image: seafileltd/seafile-md-server:13.0-latest
restart: unless-stopped
volumes:
# - ${SEAFILE_PATH}/metadata:/shared
- ${SEAFILE_PATH}/files:/shared
#ports:
# - ${MD_PORT:-8084}:${MD_PORT:-8084}
environment:
JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY:?Variable is not set or empty}
SEAFILE_MYSQL_DB_HOST: db
SEAFILE_MYSQL_DB_PORT: 3306
SEAFILE_MYSQL_DB_USER: seafile
SEAFILE_MYSQL_DB_PASSWORD: ${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME: seafile_db
SEAFILE_LOG_TO_STDOUT: ${SEAFILE_LOG_TO_STDOUT:-true}
MD_PORT: ${MD_PORT:-8084}
MD_LOG_LEVEL: ${MD_LOG_LEVEL:-info}
MD_MAX_CACHE_SIZE: ${MD_MAX_CACHE_SIZE:-1GB}
MD_CHECK_UPDATE_INTERVAL: ${MD_CHECK_UPDATE_INTERVAL:-30m}
MD_FILE_COUNT_LIMIT: ${MD_FILE_COUNT_LIMIT:-100000}
MD_STORAGE_TYPE: ${MD_STORAGE_TYPE:-disk}
CACHE_PROVIDER: redis
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD}
depends_on:
db:
condition: service_healthy
networks:
- seafile_net
- caddy_seafile_net
networks:
caddy_seafile_net:
external: true
seafile_net:
internal: true
Question:
I have tried entering the container and running various scripts to upgrade the database (pro.py setup, etc.) but the arguments seem to be invalid for this version.
What is the correct and official procedure to upgrade the database schema when migrating from Community to Professional edition for version 13.0.11 in a Docker environment?
Thank you in advance for your help.