Immich is one of the most impressive self-hosted photo and video management platforms available today, but it is also the kind of application where storage configuration matters a lot. Your photos are not disposable cache files; they are personal archives, family history, and often the main reason you are running Immich in the first place. When Docker is involved, and especially when your media library lives on a remounted volume such as a dedicated disk, external drive, NAS share, or ZFS dataset, the best configuration is the one that keeps paths stable, permissions predictable, and backups simple.

TLDR: The best Docker configuration for Immich with a remounted volume is to mount your storage on the host at a stable path, then bind-mount that path into the Immich container. Avoid relying on temporary desktop mount locations or anonymous Docker volumes for irreplaceable media. Use UUID-based mounts, clear directory ownership, a proper .env file, and regular backups of both your upload directory and PostgreSQL database.

Why the Mount Strategy Matters

Immich stores uploaded photos, videos, thumbnails, encoded video files, profile images, and metadata-related assets on disk. The database stores the catalog, relationships, albums, users, and internal state. If your volume path changes, fails to mount, or is replaced by an empty directory, Docker may happily start Immich anyway. That can lead to confusion, missing files, failed uploads, or in the worst case, data being written to the wrong location.

A remounted volume usually means storage that is mounted by the host operating system before Docker starts. This could be a second internal drive mounted at /mnt/photos, a RAID array mounted at /srv/immich, a network share mounted at boot, or a filesystem that is remounted after maintenance. The key idea is simple: Docker should not be responsible for discovering your photo disk. The host should mount it reliably, and Docker should consume it through a bind mount.

The Recommended Layout

A clean host layout makes Immich easier to manage. One practical structure is:

  • /srv/immich/library for uploaded photos, videos, thumbnails, and generated assets
  • /srv/immich/postgres for PostgreSQL database files
  • /srv/immich/backups for exported database backups, if stored locally
  • /opt/immich for your Docker Compose file and .env file

This separates application configuration from application data. The Compose file can live on your system disk, while the large and important media files live on the remounted storage volume. For many home servers, /srv/immich is a better long-term mount point than something like /media/user/ExternalDrive, because it is not tied to a desktop login session and is easier to reference in services.

Mount the Volume Using a Stable Path

The host should mount your storage by UUID or another stable identifier. On Linux, you can find disk UUIDs with:

lsblk -f

Then add an entry to /etc/fstab. For an ext4 disk, it might look like this:

UUID=1234abcd-5678-90ef-1234-567890abcdef /srv/immich ext4 defaults,nofail,noatime 0 2

The nofail option prevents the machine from refusing to boot if the disk is temporarily unavailable, while noatime reduces unnecessary write activity. If you are using a NAS share, your mount entry will look different, but the principle remains the same: mount it to a fixed location before Immich starts.

After editing fstab, test it:

sudo mkdir -p /srv/immich
sudo mount -a
findmnt /srv/immich

If findmnt shows the expected device or network share, you are ready to connect it to Docker.

Permissions: Boring but Crucial

Permissions are one of the most common causes of failed uploads, broken thumbnails, and mysterious container errors. The Immich containers need read and write access to the upload directory. A simple approach on a single-user home server is to create the directories and assign ownership to the user that runs Docker Compose.

sudo mkdir -p /srv/immich/library
sudo mkdir -p /srv/immich/postgres
sudo chown -R $USER:$USER /srv/immich

This is not the only valid model, but it is easy to understand. If you run Docker rootless, use NFS, or enforce stricter server permissions, you may need to map user IDs more carefully. The important rule is that the containers must be able to write where Immich expects to write.

A Strong Docker Compose Pattern

The best Compose setup uses environment variables for paths and keeps the remounted volume visible. In your Immich project directory, such as /opt/immich, create a .env file:

IMMICH_VERSION=release
UPLOAD_LOCATION=/srv/immich/library
DB_DATA_LOCATION=/srv/immich/postgres
DB_PASSWORD=change_this_to_a_long_random_password
DB_USERNAME=postgres
DB_DATABASE_NAME=immich

Your Compose file should then bind-mount those locations into the correct containers. A simplified example looks like this:

services:
  immich-server:
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION}
    container_name: immich_server
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    ports:
      - 2283:2283
    depends_on:
      - redis
      - database
    restart: unless-stopped

  immich-machine-learning:
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION}
    container_name: immich_machine_learning
    volumes:
      - model-cache:/cache
    env_file:
      - .env
    restart: unless-stopped

  redis:
    image: redis:6.2-alpine
    container_name: immich_redis
    restart: unless-stopped

  database:
    image: tensorchord/pgvecto-rs:pg14-v0.2.0
    container_name: immich_postgres
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_DB: ${DB_DATABASE_NAME}
    volumes:
      - ${DB_DATA_LOCATION}:/var/lib/postgresql/data
    restart: unless-stopped

volumes:
  model-cache:

This example illustrates the important part: the upload directory and database directory are bind mounts from the host. The machine learning model cache can remain a Docker named volume because it is replaceable. Your photos and database are not.

Image not found in postmeta

Avoid the Empty Directory Trap

One dangerous Docker behavior is easy to miss. If your remounted volume is supposed to be at /srv/immich but it is not actually mounted, the directory may still exist on the root filesystem. Docker will bind-mount that empty directory into the container, and Immich may start writing new data there. Later, when the real disk is mounted again, the files written to the root filesystem appear to “disappear” because they are hidden behind the mounted disk.

To prevent this, you can add a simple check before starting Immich:

findmnt /srv/immich || exit 1
docker compose up -d

For a more advanced setup, create a systemd service that requires the mount to be available before starting Docker Compose. This is especially useful for network shares that may take extra time to appear after boot.

Should the Database Be on the Same Remounted Volume?

There are two reasonable options. Keeping the PostgreSQL database on the same storage volume as the uploads makes the entire Immich data set easy to locate and back up. However, databases are more sensitive to latency and filesystem behavior than media files. If your remounted volume is a fast local SSD or reliable ZFS dataset, placing PostgreSQL there is usually fine.

If your remounted volume is a slow USB drive or network share, consider storing the database on a local SSD and only placing the Immich upload library on the large remounted volume. In that case, your DB_DATA_LOCATION might be something like /var/lib/immich-postgres, while UPLOAD_LOCATION remains /srv/immich/library. This hybrid layout often gives the best balance of performance and capacity.

External Libraries Versus Upload Storage

Immich supports external libraries, which are useful if you already have a large curated photo folder and do not want Immich to reorganize it as uploaded media. This is different from the main upload directory. If you use external libraries, mount them as read-only whenever possible:

volumes:
  - ${UPLOAD_LOCATION}:/usr/src/app/upload
  - /srv/photos/archive:/mnt/archive:ro

This protects your original archive from accidental changes inside the container. Use the main upload location for Immich-managed files, and use external libraries for existing collections you want Immich to index.

Backup Strategy: The Configuration Is Not Complete Without It

A good Docker configuration is not just about starting containers. It is also about recovery. For Immich, you should back up at least two things:

  • The upload directory, including originals, thumbnails, encoded videos, and profile assets
  • The PostgreSQL database, preferably using a proper database dump rather than copying live database files

A typical database backup command might look like this:

docker exec -t immich_postgres pg_dumpall -c -U postgres > /srv/immich/backups/immich-database.sql

Then use a backup tool such as restic, borg, rsync snapshots, or ZFS snapshots to protect both the media directory and the database dump. Remember that RAID is not a backup. A remounted volume can fail, be accidentally erased, or become corrupted just like any other storage.

Performance Tips for Large Libraries

Immich can generate a lot of thumbnails and metadata jobs, especially during the first import. If your library is large, give the system time to process everything. A few practical optimizations help:

  • Use an SSD for PostgreSQL if possible.
  • Keep the upload directory on reliable storage with good sustained write performance.
  • Avoid unstable Wi Fi mounted shares for active upload storage.
  • Use wired networking if Immich writes to a NAS.
  • Monitor disk space, because thumbnails and encoded videos can grow significantly.

If your remounted volume is a NAS share, be cautious with database placement. PostgreSQL over network filesystems can be risky unless you really understand the behavior of your storage stack. Media files are usually fine on a NAS; live database files are better on local storage.

Updating Immich Safely

Immich evolves quickly, so updates are normal. Before updating, read the release notes, then back up the database. Pull the new images and restart:

docker compose pull
docker compose up -d

Because your media and database are stored outside the container, replacing containers should not remove your data. That is one of the biggest advantages of using bind-mounted host paths correctly. Containers become disposable; your data remains deliberate and visible.

The Best Configuration in One Sentence

The best Docker configuration for Immich using a remounted volume is this: mount the storage reliably on the host, bind-mount it explicitly into Immich, store irreplaceable data outside disposable containers, verify the mount before startup, and back up both files and database. That approach is simple, transparent, and resilient.

Immich rewards careful setup. Once the storage layer is stable, the rest of the experience feels polished: automatic mobile uploads, fast browsing, face recognition, albums, sharing, and a private photo cloud that you control. A remounted volume can be an excellent foundation for that system, as long as Docker sees a dependable path and you treat the data with the care it deserves.