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:
| Service | Image | What it does | Host port |
|---|---|---|---|
immich-server | ghcr.io/immich-app/immich-server | Web UI, API, mobile backup endpoint, video transcoding | 2283 |
immich-machine-learning | ghcr.io/immich-app/immich-machine-learning | Face recognition and CLIP-based smart search | none |
redis | docker.io/valkey/valkey:9 | Job queues and caching | none |
database | ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0 | Metadata, albums, faces, similarity search | none |
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.env | Compose Builder | |
|---|---|---|
| Files you get | docker-compose.yml plus .env | One docker-compose.yml |
| Hardware acceleration, external libraries | Hand edits to override files and commented blocks | Chosen in the builder |
| Best fit | Scripted installs, following the docs line by line | First 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 deprecateddocker-composeis 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_PASSWORDto a long random string of letters and digits before first launch. Changing it later means migrating the database, which is a hassle. - Uncomment
TZand set your own timezone identifier. - Decide on
IMMICH_VERSION. The template shipsv3, 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 asv3.2.2and 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.
- Install Immich from the App Store or Google Play.
- 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. - Log in with the account you created.
- 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 file | Extends | Backends (service: value) |
|---|---|---|
hwaccel.ml.yml | immich-machine-learning | armnn, cuda, rocm, openvino, openvino-wsl, rknn |
hwaccel.transcoding.yml | immich-server | nvenc, 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:
- The upload library, your
UPLOAD_LOCATIONdirectory. The originals live in itslibrary,uploadandprofilesubfolders; back up the whole directory for the fastest restore. - 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/backupsand 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:
- Read the release notes for the version you’re moving to (Immich calls out breaking changes there).
- Update the mobile apps first; per the upgrade docs, the server only works with the app’s matching major version.
- Make sure your backup just ran.
- Bump
IMMICH_VERSIONin.envto the new tag. - 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.
Related across the network
- Self-Hosted Notion and Docs Alternatives — selfhostrealm.com
- Top 20 Self-Hosted Apps to Replace Google Workspace — selfhostrealm.com
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.