crazy-max / docker-qbittorrent

qBittorrent Docker image
MIT License
74 stars 15 forks source link

entrypoint.sh creates recursive symlinks on subsequent starts (after first) #26

Closed adamrothman closed 3 years ago

adamrothman commented 3 years ago

Behaviour

Steps to reproduce this issue

  1. Pull crazymax/qbittorrent:latest
  2. Start a container
  3. Restart the container
  4. Observe recursive symlinks /data/config/config -> /data/config and /data/data/data -> /data/data
# docker exec test_qbittorrent_1 ls -ahl /data/config
total 26M
drwxrwxr-x    1 qbittorr qbittorr     114 Mar 10 22:18 .
drwxrwxr-x    1 qbittorr qbittorr      82 Mar  8 23:16 ..
-rwxr-xr-x    1 root     root       26.2M Mar  8 00:00 biglist.p2p
lrwxrwxrwx    1 root     root          12 Mar 10 22:18 config -> /data/config
-rwxrwxrwx    1 qbittorr qbittorr     196 Mar 10 22:15 qBittorrent-data.conf
-rwxrwxrwx    1 qbittorr qbittorr    2.5K Mar 10 22:18 qBittorrent.conf
drwxrwxr-x    1 qbittorr qbittorr      44 Mar 10 22:18 rss

# docker exec test_qbittorrent_1 ls -ahl /data/data
total 4K
drwxrwxr-x    1 qbittorr qbittorr      52 Mar 10 22:18 .
drwxrwxr-x    1 qbittorr qbittorr      82 Mar  8 23:16 ..
drwxrwxr-x    1 qbittorr qbittorr   18.8K Mar 10 22:18 BT_backup
drwxrwxr-x    1 qbittorr qbittorr      44 Mar  3 23:26 GeoDB
lrwxrwxrwx    1 root     root          10 Mar 10 22:18 data -> /data/data
drwxrwxr-x    1 qbittorr qbittorr     158 Mar 10 02:18 nova3
drwxrwxr-x    1 qbittorr qbittorr      16 Mar  3 23:26 rss

Expected behaviour

Based on reading these lines: https://github.com/crazy-max/docker-qbittorrent/blob/4f3a6acd126dc3ff5536eb5611b86d29a6f05720/entrypoint.sh#L33-L34

I expect the script to create a link at /home/qbittorrent/.config/qBittorrent -> /data/config (it does):

# docker exec test_qbittorrent_1 ls -ahl /home/qbittorrent/.config
total 4K     
drwxr-sr-x    1 qbittorr qbittorr      22 Mar 10 21:17 .
drwxr-sr-x    1 qbittorr qbittorr      38 Mar 10 21:17 ..
lrwxrwxrwx    1 qbittorr qbittorr      12 Mar 10 21:17 qBittorrent -> /data/config

I also expect the script to create a link at /home/qbittorrent/.local/share/qBittorrent -> /data/data (it does):

# docker exec test_qbittorrent_1 ls -ahl /home/qbittorrent/.local/share
total 4K     
drwxr-sr-x    1 qbittorr qbittorr      22 Mar 10 21:17 .
drwxr-sr-x    1 qbittorr qbittorr      10 Mar 10 21:17 ..
lrwxrwxrwx    1 qbittorr qbittorr      10 Mar 10 21:17 qBittorrent -> /data/data

These should be the only links created.

Actual behaviour

Because the ln commands highlighted above are executed without first checking whether the destination already exists (unlike the preceding mkdir -p), restarting the container results in the creation of the recursive links described above.

When the container is restarted, the entrypoint script has already run once. Thus /home/qbittorrent/.config/qBittorrent already exists and is already a symlink to /data/config. When the ln command is run a second time, it creates another link – this time inside the existing linked directory.

The same is true for the other symlink.

Configuration

Here's the relevant excerpt from my compose file:

docker-compose.yml ```yaml version: '3' services: qbittorrent: depends_on: - nginx environment: ALT_WEBUI: 'false' PUID: '1044' PGID: '65538' TZ: America/Los_Angeles image: crazymax/qbittorrent networks: - tarsnet ports: - 'XXX:6881/tcp' # redacted - 'XXX:6881/udp' # redacted restart: always ulimits: nproc: 65535 nofile: soft: 32000 hard: 40000 volumes: - /volume1/docker/qbittorrent:/data - /volume1/Media/Downloads:/data/downloads ```

Docker info

# docker info
Containers: 4
 Running: 4
 Paused: 0
 Stopped: 0
Images: 34
Server Version: 18.09.8
Storage Driver: btrfs
Logging Driver: db
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs db fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 0cf16177dbb234350dc27dd2bbd1d7cebd098108
runc version: 6cc9d3f2cd512eeb3d548e2f6b75bcdebc779d4d
init version: e01de58 (expected: fec3683)
Security Options:
 apparmor
Kernel Version: 3.10.105
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 5.814GiB
Name: TARS
ID: VC5Y:VJHJ:EHD3:JVFU:RQPU:MTKU:ULVH:PZPM:NL2Z:HWP5:4UUO:XZ5D
Docker Root Dir: /volume1/@docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

WARNING: No kernel memory limit support
WARNING: No cpu cfs quota support
WARNING: No cpu cfs period support

Logs

WAN IP address is X.X.X.X
Creating folders...
Overriding required parameters...
Fixing perms...

******** Information ********
To control qBittorrent, access the Web UI at http://localhost:8080

Discussion

I think the solution is fairly simple: those invocations of ln should only happen if the target doesn't exist yet. Something like this maybe?

if [ ! -e "${QBITTORRENT_HOME}/.config/qBittorrent" ]; then
  ln -s /data/config "${QBITTORRENT_HOME}/.config/qBittorrent"
fi

if [ ! -e "${QBITTORRENT_HOME}/.local/share/qBittorrent" ]; then
  ln -s /data/data "${QBITTORRENT_HOME}/.local/share/qBittorrent"
fi
crazy-max commented 3 years ago

@adamrothman

I think the solution is fairly simple: those invocations of ln should only happen if the target doesn't exist yet. Something like this maybe?

LGTM, feel free to open a PR.