In short
- A working Nextcloud Docker Compose stack is four services: the
nextcloudapp container, a PostgreSQL (or MariaDB) database, Redis for caching, and a second Nextcloud container that runs/cron.shfor background jobs. - The compose file below is built from the examples in the official image's README and repository.
- Save it, fill in the passwords, run
docker compose up -d, and Nextcloud answers on port 8080.
Contents12 sections
- Prerequisites
- Step 1: pick the image variant
- Step 2: create the project folder and the database env file
- Step 3: write compose.yaml
- Step 4: start the stack
- Step 5: finish setup in the browser
- Step 6: set trusted domains and check the config
- Step 7: put it behind HTTPS
- Updating
- The alternative: Nextcloud AIO's compose file
- Troubleshooting (documented issues only)
- What to do next
Before you start, read the warning at the top of that README. The image "is maintained by community volunteers and designed for expert use." For the quickest deployment with every Nextcloud Hub feature, the README points you to Nextcloud All-in-One (AIO), which Nextcloud GmbH maintains. There's a short section on AIO's own compose file near the end, so you can pick the right route.
Prerequisites
- A 64-bit Linux host with Docker and the Compose plugin. The admin manual "strongly recommends" a 64-bit CPU, OS and PHP. On 32-bit, dates after 2038 break and some apps may not work.
- RAM for your workload. Nextcloud doesn't publish one number. The manual gives 128MB per PHP process as the minimum and 512MB as the recommendation, and says total needs vary with users, apps and activity.
- A reverse proxy, if the server will face the internet. The README's base examples provide "no TLS encryption", and it calls HTTPS "mandatory" for internet access.
The images used here are multi-arch. On 29 September 2026, Docker Hub listed nextcloud:35-apache, postgres:18-alpine and redis:alpine for both amd64 and arm64, so the same file works on a Raspberry Pi 5.
Step 1: pick the image variant
The README describes two variants:
apache: a full install with Apache built in, exposing port 80. It's the default forlatest, and it's the one used here.fpm: PHP-FPM only, on port 9000. You add your own web server, such as nginx, to serve static files and proxy requests.
Stick with apache unless you already run nginx and know why you'd want FPM.
Step 2: create the project folder and the database env file
mkdir nextcloud && cd nextcloudCreate db.env. This is the file from the official Postgres example, and the app and database containers both read it:
POSTGRES_PASSWORD=
POSTGRES_DB=nextcloud
POSTGRES_USER=nextcloudPut a long random password after POSTGRES_PASSWORD=. Per the README, once all four database variables are known (the three above plus POSTGRES_HOST), the setup wizard won't ask for them. It also warns you to "ONLY use one database type."
Step 3: write compose.yaml
services:
db:
image: postgres:18-alpine
restart: always
volumes:
- db:/var/lib/postgresql
env_file:
- db.env
redis:
image: redis:alpine
restart: always
app:
image: nextcloud:35-apache
restart: always
ports:
- 8080:80
volumes:
- nextcloud:/var/www/html
environment:
- POSTGRES_HOST=db
- REDIS_HOST=redis
env_file:
- db.env
depends_on:
- db
- redis
cron:
image: nextcloud:35-apache
restart: always
volumes:
- nextcloud:/var/www/html
entrypoint: /cron.sh
depends_on:
- db
- redis
volumes:
nextcloud:
db:This is adapted from two official sources. The db, redis, app and cron services come from the repository's with-nginx-proxy/postgres/apache example. The ports: 8080:80 mapping comes from the README's base apache example. Here's what changed:
- Removed the nginx-proxy and acme-companion containers, along with their
VIRTUAL_HOSTandLETSENCRYPT_*variables and theproxy-tiernetwork. Put your own reverse proxy in front instead (see the last section). - Pinned the image tags. The example uses
postgres:alpineandnextcloud:apache, which move to new major versions on their own. The README says Nextcloud can only be upgraded one major version at a time, so an unpinned tag can jump too far.35-apacheis the current major (35.0.1, released 24 September 2026). PostgreSQL 18 is inside the manual's supported range of 14–18. - Dropped the SELinux
:z/:Zvolume suffixes. Keep them if your host runs SELinux.
The example has one comment worth keeping in mind: the cron and app containers' volumes config "must match."
Prefer MariaDB? The README's base apache example uses mariadb:lts with command: --transaction-isolation=READ-COMMITTED, the MYSQL_* variables and MYSQL_HOST=db. Use that instead of the Postgres service, not alongside it.
Step 4: start the stack
docker compose up -dThe first start copies Nextcloud into the nextcloud volume and initialises the database, so give it a minute or two.
What you should see: per the README, Nextcloud at http://localhost:8080/ on the host, or http://your-server-ip:8080/ from another machine.
Step 5: finish setup in the browser
Because the database details are already set, the installation wizard asks only for an admin username and password. The README says that if you also set NEXTCLOUD_ADMIN_USER and NEXTCLOUD_ADMIN_PASSWORD, installation runs fully automatically with no wizard. If you set the database variables only partly, the wizard asks for them. Use db as the host and nextcloud as the database name and user.
Step 6: set trusted domains and check the config
Nextcloud only answers on hostnames it trusts. The image reads NEXTCLOUD_TRUSTED_DOMAINS, a space-separated list that's applied after install. For example, add this to the app service's environment::
- NEXTCLOUD_TRUSTED_DOMAINS=cloud.example.com 192.168.1.50To see the merged configuration, run the occ command the README gives. It hides passwords by default:
docker compose exec -u33 app ./occ config:list system(The README notes that on Alpine-based images the user ID is 82, not 33.) Don't rely on reading config.php directly. The image injects some settings through extra config files, so that file doesn't show everything.
Step 7: put it behind HTTPS
The README recommends a reverse proxy in front of Nextcloud that terminates TLS. So that Nextcloud sees the real client address and protocol, set these on the app service:
TRUSTED_PROXIES: your proxy's IP address, or a CIDR range for IPv4.APACHE_DISABLE_REWRITE_IP=1, needed alongsideTRUSTED_PROXIES.- If that doesn't work, the README's fallback is fixed values such as
OVERWRITEHOST,OVERWRITEPROTOCOL=httpsandOVERWRITECLIURL.
One warning from the README: these values are written into config.php at install time, and removing the variables later doesn't remove them from the file. You'd have to edit config.php by hand. Where you can, set them before the first start.
For the proxy itself, see reverse proxy for a homelab: Caddy or Nginx Proxy Manager. Once the proxy handles traffic, you can remove the 8080:80 mapping.
Updating
With Compose, the README's update procedure is:
docker compose pull
docker compose up -dThe container sees that the image version differs from the one in the volume and runs the upgrade itself. To move to the next major version, change 35-apache to 36-apache in both app and cron, then pull and start again. Never skip a major.
The alternative: Nextcloud AIO's compose file
If you'd rather not manage these containers yourself, AIO is Nextcloud's supported route, and its README suggests the compose file over docker run "for production usage." The core of AIO's compose.yaml is one mastercontainer:
name: nextcloud-aio
services:
nextcloud-aio-mastercontainer:
image: ghcr.io/nextcloud-releases/all-in-one:latest
init: true
restart: always
container_name: nextcloud-aio-mastercontainer
volumes:
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config
- /var/run/docker.sock:/var/run/docker.sock:ro
network_mode: bridge
ports:
- "80:80"
- "8080:8080"
- "8443:8443"
volumes:
nextcloud_aio_mastercontainer:
name: nextcloud_aio_mastercontainerThis is the official file with its inline comments stripped. Download the real one, because its comments explain which lines you must not change: the container name and the volume name both have to stay exactly as they are. Then open https://your-server-ip:8080 by IP address, not a domain. The AIO README warns that using a domain there is "likely to break later due to HSTS." AIO then creates the Nextcloud, database, Redis and backup containers for you.
AIO-specific cautions from its README:
- Snap-based Docker isn't supported. It's generally only an issue on Ubuntu, and the README gives a command to check.
- Some VPS hosts are on its "disrecommended" list. It says Hostinger's VPS "seem to miss a specific Kernel feature which is required for AIO to run correctly." It also flags older Strato VPS on Virtuozzo and hosts with a low
numproclimit. The community image in this guide isn't named on that list. - Behind an existing reverse proxy, follow AIO's separate reverse-proxy docs. The basic steps assume nothing else is using ports 80 and 443.
Troubleshooting (documented issues only)
- The wizard asks for database details anyway. You set only part of a database group. The README says you must set every variable for one database type, or it falls back to SQLite.
- Proxy settings won't go away. See step 7: the values are in
config.phpnow, so edit them there. - Upgrade refuses to run, or breaks. You probably skipped a major version. Go back to the previous major tag and step through them one at a time.
- Background jobs don't run in a custom image. The examples README notes that a cron setup inside one container "must run as root or
cron.phpwill not run." The separatecronservice above avoids that. - AIO on Hostinger misbehaves. It's a known host limitation (above), not a problem with your config.
What to do next
- Compare it with a lighter sync server in Nextcloud vs Seafile, or browse Nextcloud alternatives.
- Running it on a Pi? Sizing notes are in the Nextcloud profile and the best self-hosted apps for a Raspberry Pi.
- Hosting it on a VPS instead? See the VPS guide for self-hosting.
Sources (8)ShowHide
- nextcloud/docker README (official image docs: compose examples, environment variables, occ, updates) · accessed 2026-09-29
- nextcloud/docker example: with-nginx-proxy/postgres/apache compose.yaml and db.env · accessed 2026-09-29
- nextcloud/docker .examples README (cron notes) · accessed 2026-09-29
- Nextcloud All-in-One README (compose.yaml, ports, disrecommended VPS providers) · accessed 2026-09-29
- Nextcloud All-in-One compose.yaml · accessed 2026-09-29
- Nextcloud 35 Administration Manual: System requirements · accessed 2026-09-29
- Docker Hub tags checked: nextcloud:35-apache, postgres:18-alpine, redis:alpine (all list arm64 and amd64) · accessed 2026-09-29
- GitHub releases API: nextcloud/server (35.0.1, 2026-09-24), as recorded in the Nextcloud profile · accessed 2026-09-29