Seafile Docker: Use external hard drive

Basically I tried exactly this so I can use my NAS hdd instead of the VMs SSD for the actual data:

How to move seafile-data folder to my hard drive when using docker

Here is my docker-compose file:

services:
  db:
image: mariadb:10.11
container_name: seafile-mysql
environment:
  - MYSQL_ROOT_PASSWORD=REDACTED  # Requested, set the root's password of MySQL service.
  - MYSQL_LOG_CONSOLE=true
  - MARIADB_AUTO_UPGRADE=1
volumes:
  - /root/docker-compose-files/seafile/mysql:/var/lib/mysql  # Requested, specifies the path to MySQL data persistent store.
networks:
  - seafile-net

  memcached:
image: memcached:1.6.18
container_name: seafile-memcached
entrypoint: memcached -m 256
networks:
  - seafile-net
      
  seafile:
image: seafileltd/seafile-mc:latest
container_name: seafile
ports:
  - "8012:80"
#      - "443:443"  # If https is enabled, cancel the comment.
volumes:
  - /root/docker-compose-files/seafile/config:/shared
  - /mnt/nas/docker/seafile:/shared/seafile/seafile-data

environment:
  - DB_HOST=db
  - DB_ROOT_PASSWD=REDACTED  # Requested, the value should be root's password of MySQL service.
  - TIME_ZONE=Europe/Berlin  # Optional, default is UTC. Should be uncomment and set to your local time zone.
  - SEAFILE_ADMIN_EMAIL=admin@REDACTED # Specifies Seafile admin user, default is 'me@example.com'.
  - SEAFILE_ADMIN_PASSWORD=REDACTED     # Specifies Seafile admin password, default is 'asecret'.
  - SEAFILE_SERVER_LETSENCRYPT=false   # Whether to use https or not.
  - SEAFILE_SERVER_HOSTNAME=seafile.nas.REDACTED # Specifies your host name if https is enabled.
depends_on:
  - db
  - memcached
networks:
  - seafile-net

networks:
  seafile-net:

but I only get:

root@hdocker:~/docker-compose-files/seafile# docker logs seafile
*** Running /etc/my_init.d/01_create_data_links.sh...
*** Booting runit daemon...
*** Runit started as PID 17
*** Running /scripts/enterpoint.sh...
2023-12-22 17:06:32 Waiting Nginx 
2023-12-22 17:06:32 Nginx ready 
2023-12-22 17:06:32 This is an idle script (infinite loop) to keep container running. 
[2023-12-22 17:06:39] Skip running setup-seafile-mysql.py because there is existing seafile-data folder.
waiting for mysql server to be ready: %s (2003, "Can't connect to MySQL server on 'db' ([Errno 111] Connection refused)")
waiting for mysql server to be ready: %s (2003, "Can't connect to MySQL server on 'db' ([Errno 111] Connection refused)")
waiting for mysql server to be ready: %s (2003, "Can't connect to MySQL server on 'db' ([Errno 111] Connection refused)")
[12/22/2023 17:06:39][upgrade]: The container was recreated, start fix the media symlinks
mv: target '/shared/seafile/seahub-data/avatars' is not a directory
Traceback (most recent call last):
  File "/scripts/start.py", line 95, in <module>
    main()
  File "/scripts/start.py", line 61, in main
    check_upgrade()
  File "/scripts/upgrade.py", line 95, in check_upgrade
    fix_media_symlinks()
  File "/scripts/upgrade.py", line 79, in fix_media_symlinks
    call('mv -n %s/* %s' % (avatars_dir, dst_avatars_dir))
  File "/scripts/utils.py", line 70, in call
    return subprocess.check_call(*a, **kw)
  File "/usr/lib/python3.10/subprocess.py", line 369, in check_call
    raise CalledProcessError(retcode, cmd)
**subprocess.CalledProcessError: Command 'mv -n /opt/seafile/seafile-server-11.0.3/seahub/media/avatars/* /shared/seafile/seahub-data/avatars' returned non-zero exit status 1.**

I tried creating an “avatars” directory: mkdir -p /root/docker-compose-files/seafile/config/seafile/seahub-data/avatars

but it still doesn’t work…

What did I do wrong?
Would also gladly accept any other solution on how to use my mounted HDD for the seafile-data and keep the rest on the hosts SSD (I can’t be the only one who wants something like this?)

Here to say that I am also experiencing this problem. I am doing a brand new install. Hopefully someone can chime in :crossed_fingers:

Official compose file states this for volumes:

volumes:
      - /opt/seafile-data:/shared   # Requested, specifies the path to Seafile data persistent store.

Basically, it means everything (seafile-data, seahub-data, conf, logs and nginx stuff) will be mounted from /opt/seafile-data or, in your case, from your NAS (by adjusting the path).

This is the easy way and the one I would recommend. However, if I understand correctly, you’re trying to split the volume in something like this:

  • seafile-data mounted from your NAS
  • Everything else mounted from some directory on the SSD

This is a little trickier and requires a two-step initialization, I’ve written some tips about it here

After your advice in the referenced thread, and some fiddling, I was able to successfully separate the folders by doing this:

  - /mnt/docker-data/seafile/conf/:/shared/seafile/conf # ssd
  - /mnt/docker-data/seafile/ccnet/:/shared/seafile/ccnet # ssd
  - /mnt/docker-data/seafile/logs/:/shared/logs # ssd
  - /mnt/seafile/seafile-data:/shared/seafile/seafile-data # hdd
  - /mnt/seafile/seahub-data:/shared/seafile/seahub-data # hdd

The problem I am having described in this thread, happens when I try a new install using the auto-configuration of nginx and let’s encrypt. Maybe I will try it now with everything on one drive.

That’s why you need to do it in two steps.

Seafile’s scripts use the seafile-data folder to know if the server should be initialized or just launched.

But adding a volume directly mapped to /shared/seafile/seafile-data in the container will create this directory in the container.

Then seafile will think it has already been initialized (which is wrong), skips initialization and you end up with everything broken.

See:

[2023-12-22 17:06:39] Skip running setup-seafile-mysql.py because there is existing seafile-data folder.