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 -fThis 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 stopBring 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 downThat’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.
Related Reading
- Appwrite Backend-as-a-service (BaaS)
- Automatic Backup of Docker MySQL or MariaDB Containers
- Docker Volume Mounts: Essential Flags
- NocoDB DB Management System
- Uptime Monitoring with Uptime Kuma
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:
docker exec -u www-data nextcloud php occ maintenance:mode --offThat --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:
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:
MYSQL_HOST: nextcloud_dbNextcloud 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:
upload_max_filesize = 16Gpost_max_size = 16Gmemory_limit = 512Mmax_execution_time = 3600Then mount it in the nextcloud service:
volumes: - ./nextcloud:/var/www/html - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.iniRestart 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:
# Set Nextcloud to use cron modedocker 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.phpEvery 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.