Docker Homelab
Isometric drawing of a four-bay NAS for a self-hosted photo library, wired to a router, with eight blue cubes, bare hard drives, and mountain photo prints.
guides

Immich Docker Compose Setup in 8 Steps (2026 Guide)

Replace Google Photos with Immich: the official Docker Compose stack, mobile auto-backup, hardware-accelerated machine learning, and backups that matter.

By Docker Homelab Editorial · ·Updated · 10 min read

Immich publishes its official Docker Compose file with every release. Download docker-compose.yml and example.env from the latest GitHub release, rename the env file to .env, set UPLOAD_LOCATION and DB_PASSWORD, then run docker compose up -d. That starts four containers, and the web UI comes up on port 2283. The current release is v3.2.2, published September 15, 2026.

Immich is the self-hosted photo and video manager that finally makes leaving Google Photos realistic. It has polished iOS and Android apps with automatic background backup of your camera roll, a fast timeline, albums, sharing, map view, and local machine learning for face recognition and natural-language search (“show me photos of my dog at the beach”). All of it runs on your hardware, and your photos never touch a third party’s servers.

Immich is more involved than a single-container service because it ships as a small stack of containers, but the project maintains an official Docker Compose file that does the heavy lifting. The sections below walk through that stack, then install, mobile backup, hardware acceleration, reverse proxying, backups and upgrades.

One caveat worth knowing up front: Immich is under very active development and the project officially notes that things can change between releases. Pin a version, read the release notes before upgrading, and — most importantly — keep good backups. This is non-negotiable for irreplaceable photos.

What’s in the Immich Docker Compose File

The official Compose file defines four services. The table lists what each one pulls in the v3.2.2 file:

ServiceImageWhat it doesHost port
immich-serverghcr.io/immich-app/immich-serverWeb UI, API, mobile backup endpoint, video transcoding2283
immich-machine-learningghcr.io/immich-app/immich-machine-learningFace recognition and CLIP-based smart searchnone
redisdocker.io/valkey/valkey:9Job queues and cachingnone
databaseghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0Metadata, albums, faces, similarity searchnone

Machine learning is separated so you can give it more resources or hardware acceleration independently. The database is a PostgreSQL image built by the Immich team with the vector extensions that power similarity search. Immich requires this specific image; a stock Postgres will not work.

Here is the v3.2.2 file with its comments trimmed. Read it to understand the wiring, but download it rather than copying it (Step 1). Tags and digests change between releases, and the file’s own header warns that “the compose file on main may not be compatible with the latest release.”

name: immich

services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    # extends:
    #   file: hwaccel.transcoding.yml
    #   service: cpu
    volumes:
      - ${UPLOAD_LOCATION}:/data
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    ports:
      - '2283:2283'
    depends_on:
      - redis
      - database
    restart: always
    healthcheck:
      disable: false

  immich-machine-learning:
    container_name: immich_machine_learning
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
    # extends:
    #   file: hwaccel.ml.yml
    #   service: cpu
    volumes:
      - model-cache:/cache
    env_file:
      - .env
    restart: always
    healthcheck:
      disable: false

  redis:
    container_name: immich_redis
    image: docker.io/valkey/valkey:9@sha256:70739f85ad2ee01a726a965584a0f94895f01b0c60b3cc8b0aeef11eaa6888cf
    healthcheck:
      test: redis-cli ping | grep -q PONG || exit 1
    restart: always

  database:
    container_name: immich_postgres
    image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_DB: ${DB_DATABASE_NAME}
      POSTGRES_INITDB_ARGS: '--data-checksums'
      # DB_STORAGE_TYPE: 'HDD'
    volumes:
      - ${DB_DATA_LOCATION}:/var/lib/postgresql/data
    shm_size: 128mb
    restart: always
    healthcheck:
      disable: false

volumes:
  model-cache:

Your library mounts at /data inside the server container; change the host side through UPLOAD_LOCATION in .env, never on that line. The commented extends: blocks are where hardware acceleration plugs in (Step 5), and DB_STORAGE_TYPE: 'HDD' is the line to uncomment if the database can’t live on an SSD.

ghcr.io or altran1502/immich-server?

Use ghcr.io/immich-app/..., the registry the release file pulls from. Older guides reference altran1502/immich-server on Docker Hub, which is still updated: on September 27, 2026 it carried v3.2.2, v3 and release tags for amd64 and arm64 (Docker Hub tags). It has lagged before, though. Issue #25780, opened in February 2026, reported that 2.5.0 and 2.5.2 were missing there.

Immich Default Port: 2283

Immich’s default port is 2283. The server listens on 2283 and the official file publishes it as '2283:2283', so browsers and the mobile app connect to http://your-server-ip:2283. The machine-learning container listens on 3003 (environment variables), but only other containers reach it, so it is not published.

If 2283 is taken on the host, change only the left side of the mapping, then run docker compose up -d:

    ports:
      - '8080:2283'

A reverse proxy on the same Docker network keeps targeting 2283, because it talks to the container rather than the host; the Docker Compose networking guide explains why.

Official File or the Immich Compose Builder?

Use the official release file for a default install, and the Immich Docker Compose Builder when you want customizations baked in from the start. The builder was announced on September 2, 2026, featured in the v3.2.0 release notes, and outputs one docker-compose.yml with no separate .env.

Release file + example.envCompose Builder
Files you getdocker-compose.yml plus .envOne docker-compose.yml
Hardware acceleration, external librariesHand edits to override files and commented blocksChosen in the builder
Best fitScripted installs, following the docs line by lineFirst installs that need customization

The maintainers built it because those features “always required manual edits based on snippets that are scattered throughout the docs,” but they keep it deliberately small: power users are “still welcome (and expected) to make edits to the resulting file themselves.” With builder output, the .env edits in Steps 2 and 8 become edits inside that one file.

Prerequisites

  • Docker with the Compose plugin, run as docker compose; the deprecated docker-compose is no longer supported, and the install docs ask for Docker Engine v25 or newer. New to Compose? Start with the first self-hosted stack guide.
  • A 64-bit Linux host (amd64 or arm64) with 2 CPU cores minimum, 4 recommended. Since v3, machine learning on amd64 needs an x86-64-v2 CPU, which covers most chips from about 2012 onward (requirements).
  • At least 6 GB RAM, with 8 GB recommended; the documented 4 GB option requires disabling machine learning
  • A directory with plenty of space for your photo library (this only grows); thumbnails and transcodes add 10 to 20 percent
  • Local SSD space for the Postgres files, typically 1 to 3 GB, never a network share

Step 1: Download the Official Compose File and Env Template

Make a directory and pull the two files Immich publishes with each release:

mkdir -p ~/services/immich
cd ~/services/immich

wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
wget -O .env https://github.com/immich-app/immich/releases/latest/download/example.env

These are the exact commands from Immich’s official documentation, and the latest/download URLs always redirect to the newest release (v3.2.2 as of September 27, 2026). Downloading the maintained file (rather than copy-pasting a snippet from a blog) is the right call here: the stack’s service images and wiring change over time, and the released file is always internally consistent.

Step 2: Configure the .env File

Open .env. The v3.2.2 example.env contains these settings (comments shortened):

# Where your uploaded photos and videos are stored on the host
UPLOAD_LOCATION=./library

# Where the Postgres database files live (network shares not supported)
DB_DATA_LOCATION=./postgres

# Commented out by default; uncomment and set your timezone
# TZ=Etc/UTC

# Major-version tag; can be pinned to an exact version
IMMICH_VERSION=v3

# Change to a random password using only A-Za-z0-9
DB_PASSWORD=postgres

# No need to change these
DB_USERNAME=postgres
DB_DATABASE_NAME=immich

Three pieces of advice:

  • Change DB_PASSWORD to a long random string of letters and digits before first launch. Changing it later means migrating the database, which is a hassle.
  • Uncomment TZ and set your own timezone identifier.
  • Decide on IMMICH_VERSION. The template ships v3, a major-version tag that picks up every 3.x release (but not release candidates) on the next pull. For deliberate upgrades, pin an exact tag such as v3.2.2 and review each release’s requirements before moving on.

UPLOAD_LOCATION is the most important setting: it’s the directory holding every photo you back up. Put it on a disk with room to grow, and put it in your backup plan.

Step 3: Start the Stack

From ~/services/immich:

docker compose up -d

Docker pulls four images (server, machine learning, the Valkey cache, and the Immich Postgres image) and starts them in order. The first start takes a few minutes while the database initializes. Watch progress with:

docker compose logs -f immich-server

When the server is ready, open http://your-server-ip:2283. You’ll get the admin registration page — the first account you create is the administrator. Create it, log in, and you’re looking at an empty timeline ready for photos.

Step 4: Set Up Mobile Auto-Backup

This is the feature that replaces Google Photos.

  1. Install Immich from the App Store or Google Play.
  2. On the login screen, enter your server URL. On your local network that’s http://your-server-ip:2283; once you’ve set up a reverse proxy (next section), use the HTTPS domain.
  3. Log in with the account you created.
  4. Open the app’s backup settings, select the albums to back up (usually your Camera Roll), and enable background backup.

The app uploads in the background and tracks which assets are already backed up, so it’s safe to let it run. To migrate your existing Google Photos library, use Google Takeout to export, then upload the export through the web UI or the immich-cli bulk uploader.

Step 5: Hardware Acceleration (Optional but Worth It)

Two parts of Immich benefit from hardware acceleration, and each has an override file that plugs into a commented extends: block in the main file:

Override fileExtendsBackends (service: value)
hwaccel.ml.ymlimmich-machine-learningarmnn, cuda, rocm, openvino, openvino-wsl, rknn
hwaccel.transcoding.ymlimmich-servernvenc, quicksync, rkmpp, vaapi, vaapi-wsl

For machine learning on an NVIDIA card, download the override next to the main file, append -cuda to the image tag, uncomment extends, and change cpu to cuda (ML acceleration docs):

wget -O hwaccel.ml.yml https://github.com/immich-app/immich/releases/latest/download/hwaccel.ml.yml
  immich-machine-learning:
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}-cuda
    extends:
      file: hwaccel.ml.yml
      service: cuda

Then run docker compose up -d. CUDA needs compute capability 5.2 or higher, driver 545 or newer, and the NVIDIA Container Toolkit. For video, do the same under immich-server with hwaccel.transcoding.yml, then pick the matching option in the Admin page’s video transcoding settings (transcoding docs). On CPU-only hardware Immich still works — ML jobs simply run slower, which is fine for a personal library that indexes once and then keeps up incrementally.

Step 6: Reverse Proxy for HTTPS and Remote Access

To use Immich from outside your network, and to let the mobile app connect over HTTPS, put it behind a reverse proxy pointed at the server container’s port 2283. It must sit at the root of a domain or subdomain, not under a sub-path. With Traefik, you add labels to the immich-server service in the downloaded Compose file:

  immich-server:
    # ...existing config from the official file...
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.immich.rule=Host(`photos.yourdomain.com`)"
      - "traefik.http.routers.immich.entrypoints=websecure"
      - "traefik.http.routers.immich.tls.certresolver=letsencrypt"
      - "traefik.http.services.immich.loadbalancer.server.port=2283"
    networks:
      - traefik-proxy

Add the external traefik-proxy network to the file’s networks: block so the server can join it. Traefik has no default body-size cap, but Immich’s reverse proxy docs warn that Traefik v3’s default 60-second responding timeout makes uploads fail after a minute. Raise it in the static config:

entryPoints:
  websecure:
    address: :443
    transport:
      respondingTimeouts:
        readTimeout: 600s
        idleTimeout: 600s

With Nginx Proxy Manager, add Immich’s recommended client_max_body_size 50000M and proxy_request_buffering off to the proxy host’s advanced config, with 600-second timeouts.

Because your entire photo history is sensitive, the same advice as other services applies: if you don’t need public access, exposing Immich only over a VPN (WireGuard or Tailscale) is the safer posture. The mobile app connects to a private hostname just as happily as a public one.

Step 7: Backups — The Part You Cannot Skip

Immich is photo storage. Treat it like the irreplaceable data it is. A complete backup is two things:

  1. The upload library, your UPLOAD_LOCATION directory. The originals live in its library, upload and profile subfolders; back up the whole directory for the fastest restore.
  2. The database: your faces, albums, metadata, and the mapping that makes the library navigable. By default Immich dumps it daily at 2:00 AM into UPLOAD_LOCATION/backups and keeps the last 14 (backup docs). For an on-demand dump before an upgrade:
docker exec -t immich_postgres pg_dump --clean --if-exists --dbname=immich --username=postgres | gzip > "/path/to/backup/dump.sql.gz"

A library backup without the database leaves you with a folder of files and no organization; a database backup without the files leaves you with metadata pointing at nothing. You need both. Apply a real 3-2-1 backup strategy here above any other service — the cost of getting it wrong is your family photos.

Step 8: Updating

If you pinned an exact IMMICH_VERSION, upgrading is deliberate:

  1. Read the release notes for the version you’re moving to (Immich calls out breaking changes there).
  2. Update the mobile apps first; per the upgrade docs, the server only works with the app’s matching major version.
  3. Make sure your backup just ran.
  4. Bump IMMICH_VERSION in .env to the new tag.
  5. Re-pull and recreate:
docker compose pull && docker compose up -d

The database migrations run automatically on start. Downgrades are not supported, so the pre-upgrade backup is your way back. Following the release notes and keeping the version pinned is what keeps Immich’s fast pace of development from surprising you.

The Result

Immich keeps your photo library on storage you manage, with mobile backup and local search. If you are still deciding which photo app to self-host, compare the available apps before committing your library to a deployment.

Two practical follow-ups: the best NAS for Docker containers guide covers storage and container support, while the container resource calculator helps plan the rest of the stack. Reserve Immich’s documented RAM requirement separately and keep its database on local SSD storage, not a network share.

FAQ

what port does immich use by default

Immich uses port 2283 by default. The server container listens on 2283 and the official Compose file maps it as 2283:2283, so browsers and the mobile app connect to http://your-server-ip:2283. The machine-learning container uses port 3003 internally and is never published. To move Immich, change only the host side of that mapping.

is altran1502/immich-server the official immich image

It carries the same Immich releases on Docker Hub, but the official Compose file pulls ghcr.io/immich-app/immich-server instead. On September 27, 2026 the Docker Hub repository had v3.2.2, v3 and release tags for amd64 and arm64. Its tags have lagged behind GHCR before, so the ghcr.io image names are the safer choice.

can i use docker-compose instead of docker compose for immich

No. Immich requires the Docker Compose plugin, run as docker compose, and no longer supports the deprecated standalone docker-compose binary. Its install docs also call for Docker Engine v25 or newer. Errors about shorthand flags or permissions usually mean an outdated Docker, such as the docker.io package on Ubuntu 22.04.

does immich need a gpu

No. Immich runs entirely on CPU; face recognition and smart search just index more slowly. A GPU or NPU speeds things up through the hwaccel.ml.yml override (CUDA, ROCm, OpenVINO, ARM NN or RKNN), and hwaccel.transcoding.yml handles video. NVIDIA cards need compute capability 5.2 or higher and driver 545 or newer.

Sources

  1. Immich — Docker Compose installation (official docs)
  2. Immich — Hardware-Accelerated Machine Learning
  3. Immich — Hardware and storage requirements
  4. Immich v3.2.2 release notes (GitHub)
  5. Immich — docker-compose.yml from the latest release
  6. Immich — example.env from the latest release
  7. Immich v3.2.0 release notes (GitHub)
  8. Immich — Docker Compose Builder
  9. New Docker Compose Builder (immich-app discussion #31232)
  10. Immich — Environment variables
  11. Immich — Hardware Transcoding
  12. Immich — Reverse proxy
  13. Immich — Backup and restore
  14. Immich — Upgrading
  15. Docker Hub — altran1502/immich-server tags
  16. Inconsistent image tags on Docker Hub (immich-app issue #25780)
#immich #docker-compose #photos#google-photos-alternative #self-hosted #homelab

Related