Skip to content
Go back

How to install NextCloud via Docker

· Updated:
By SumGuy 5 min read
How to install NextCloud via Docker

Install Docker

Install docker on Ubuntu/DebianInstall docker on Ubuntu/Debian

Create a Docker Compose file

Once you have Docker and Docker Compose installed, create a new file called docker-compose.yml. You can do this in any text editor of your choice. In this file, we will define the Nextcloud service and its dependencies.

version: '3'
services:
nextcloud:
image: nextcloud:fpm
container_name: nextcloud
restart: unless-stopped
volumes:
- ./nextcloud:/var/www/html
depends_on:
- nextcloud_db
- nextcloud_redis
environment:
MYSQL_HOST: db
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_PASSWORD: nextcloud
networks:
- net
nextcloud_db:
image: mariadb
container_name: nextcloud_db
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
restart: unless-stopped
volumes:
- ./db:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: nextcloud_r_pass
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_PASSWORD: nextcloud
networks:
- net
nextcloud_redis:
image: "redis:alpine"
container_name: nextcloud_redis
command: redis-server --appendonly yes --save 20 1 --loglevel warning
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
start_period: 20s
interval: 30s
retries: 5
timeout: 3s
expose:
- 6379
mem_limit: 2048m
mem_reservation: 512m
volumes:
- ./redis:/data
environment:
- REDIS_REPLICATION_MODE=master
networks:
- net
caddy:
image: caddy
container_name: caddy
ports:
- "80:80"
- "443:443"
environment:
- ACME_AGREE=true
restart: unless-stopped
depends_on:
- nextcloud
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./caddy_data:/data
- ./caddy_config:/config
- ./nextcloud:/var/www/html
networks:
- net
networks:
net:

So what does this docker compose file do?

This file defines four services, nextcloud_db, nextcloud, nextcloud_redis and caddy the reverse proxy. The nextcloud_db service uses the mariadb image to run a MariaDB database container. It also sets the necessary environment variables. The nextcloud service uses the nextcloud image to run the Nextcloud application container. the nextcloud_redis is used for significantly improving your Nextcloud server performance with memory caching, where frequently-requested objects are stored in memory for faster retrieval

Create Caddyfile

example.com {
redir /.well-known/carddav /remote.php/dav 301
redir /.well-known/caldav /remote.php/dav 301
@forbidden {
path /.htaccess
path /data/*
path /config/*
path /db_structure
path /.xml
path /README
path /3rdparty/*
path /lib/*
path /templates/*
path /occ
path /console.php
}
respond @forbidden 404
root * /var/www/html
php_fastcgi nextcloud:9000
file_server
}

Change example.com to your domain or subdomain.

Bring up the docker containers

docker compose up -d && docker compose logs -f

This command will start the nextcloud container in detached mode, meaning it will run in the background. and it will show you the logs from nextcloud so you can make sure there were no errors. hit CTRL + C to close the logs.

Stop containers temporarily

This will stop the containers but not delete the temporary network, or remove temporary files etc.

docker compose stop

Bring down the containers completely

This will stop and remove the containers, but keep the data in the volumes mentioned in docker-compose.yml intact so that your data is not lost.

docker compose down

That’s it! You’ve now installed Nextcloud using Docker Compose. With Docker Compose, you can easily manage and deploy complex applications like Nextcloud with just a few commands.

Things That Will Bite You (and How to Unbit Yourself)

Nextcloud has a reputation for working great until it doesn’t, and then being aggressively unhelpful about why. Here’s the greatest hits.

The “Maintenance Mode” trap

You run an update, something fails mid-way, and now every page shows a maintenance mode banner. Nextcloud locked itself. To unlock it, run occ through the container:

Terminal window
docker exec -u www-data nextcloud php occ maintenance:mode --off

That --u www-data matters. Run it as root and you’ll get a permissions mess that makes the original problem look fun.

Trusted domains blocking your own setup

You bring it up, open the browser, and get a big red “Access through untrusted domain” error. This happens when you access Nextcloud via an IP or hostname that isn’t whitelisted. Fix it with occ:

Terminal window
docker exec -u www-data nextcloud php occ config:system:set trusted_domains 1 --value="cloud.example.com"

Index 0 is localhost (leave it alone). Add your actual domain at index 1 and above. If you’re accessing by IP during testing, add that too — you can always clean it up later.

Missing environment variable: MYSQL_HOST

Notice the Compose file above has MYSQL_HOST: db but the service is named nextcloud_db. That’s a copy-paste bug waiting to get you. The value needs to match the actual service name, so change it to:

Terminal window
MYSQL_HOST: nextcloud_db

Nextcloud will silently fail to connect to the database and you’ll spend 20 minutes reading PHP logs wondering why everything is on fire.

The “big file upload” wall

Default PHP config caps uploads at 2MB. Uploading your first ISO or VM backup will just… fail silently in the browser. You need to pass a custom PHP config into the container. Drop a file called uploads.ini next to your Compose file:

uploads.ini
upload_max_filesize = 16G
post_max_size = 16G
memory_limit = 512M
max_execution_time = 3600

Then mount it in the nextcloud service:

volumes:
- ./nextcloud:/var/www/html
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini

Restart the container and you’re good. Your 40GB Plex library backup will no longer time out at 2MB.

Cron jobs aren’t running

Background jobs in Nextcloud default to AJAX (runs when someone’s in the browser). That’s not good enough for a real setup. Switch it to cron-based scheduling and add an actual cron entry:

Terminal window
# Set Nextcloud to use cron mode
docker exec -u www-data nextcloud php occ background:cron
# Add to your host crontab (crontab -e)
*/5 * * * * docker exec -u www-data nextcloud php -f /var/www/html/cron.php

Every 5 minutes, jobs actually run. File previews generate, notifications send, shares expire on schedule — the whole thing behaves like a real application instead of a science project.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Previous Post
Home Lab Hardware Guide 2026: What to Buy, What to Avoid, and What to Beg For
Next Post
How to Transfer docker Images Without a Repository

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts