Migrate NextCloud to Docker

3 minute read

NextCloud is a self-hosted Dropbox alternative. Installing it with Docker has the advantage of easily migrating it, which might happen when you decide to upgrade your VPS.

This post are personal notes about how I migrated from a traditional installation on Ubuntu to a Docker install.


Get your mysql version with

mysql --version
mysql  Ver 14.14 Distrib 5.7.25, for Linux (x86_64) using  EditLine wrapper

Mine is 5.7.25.

Get your Nextcloud version with

cat /var/www/nextcloud_site/version.php
$OC_Version = array(13,0,4,0);
$OC_VersionString = '13.0.4';
$OC_Edition = '';
$OC_Channel = 'stable';
$OC_VersionCanBeUpgradedFrom = array (
  'nextcloud' => 
  array (
    '12.0' => true,
    '13.0' => true,
  'owncloud' => 
  array (
$OC_Build = '2018-06-11T08:24:28+00:00 5c97dc3de30c06971fc077cc2385aedef8dd6f20';
$vendor = 'nextcloud';

Mine is 13.0.4.

We will use these versions to build our docker-compose file.

Create the docker-compose

We create it in ~/Docker/Nextcloud:

mkdir -p Docker/Nextcloud
cd Docker/Nextcloud

Docker-compose file vim docker-compose.yml:

version: '2'

    image: mysql:5.7.25 
    container_name: nextcloud_db
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    restart: always
      - ./db:/var/lib/mysql
    env_file: nextcloud_db_env

    image: nextcloud:13.0.4
    container_name: nextcloud
      - 8080:80
      - nextcloud_db
      - ./html:/var/www/html
      - /mnt/data/nextcloud-data:/mnt/data/nextcloud-data
    restart: always

In this configuration we mount two volumes for nextcloud:

  • html which contains our website
  • /mnt/data/nextcloud-data which contains our user data from our previous installation

We also mount the database directory db.

The application is exposed through the port 8080, but we will add a reverse proxy to be able to serve it through a subdomain such as cloud.sammy.fr.

Migrate SQL

We copy our old MySQL installation to ~/Docker/Nextcloud/db

mkdir db
sudo cp -r /var/lib/mysql db

This way when our container starts, it will restart with all our data, users and databases.

But we might have to authorize the users the right to perform operations on the database. Our database has one user nextcloud_admin, we will have to give him privileges not only for localhost but also for the ip address of the mysql container.

To do so we start up our containers with docker-compose up -d.

Then we enter our mysql container :

sudo docker exec -it nextcloud_db /bin/bash

We can now launch a mysql shell with mysql -u root -p and enter the root password for our old database.

To grant privileges to nextcloud_db on all databases and all addresses we use the command:

GRANT ALL ON *.* to nextcloud_admin@'%' IDENTIFIED BY 'mypassword';

Migrate Nextcloud site

mkdir html
sudo cp -r /var/www/old_site html

We will need to adjust the config file to avoid errors. Edit the file Docker/Nextcloud/html/config/config.php.

Ensure that :

  • dbhost is set to nextcloud_db:3306.
  • trusted_domains contains your current domain :
$CONFIG = array (
  'trusted_domains' =>
  array (
    0 => 'sammy.fr',

We also need to make sure the folder is accessible to Apache or Nginx. To do so we change the owner to www-data:

sudo chown -R www-data:www-data ~/Docker/Nextcloud/html

We should now be able to test our configuration by visiting https://sammy.fr:8080.

Reverse proxy configuration

We assume the domain serving the old installation was cloud.sammy.fr. We need to modify our configuration so that requests done to are redirected to cloud.sammy.fr.

We modify the file /etc/apache2/sites-available/cloud.sammy.fr-le-ssl.conf:

IfModule mod_ssl.c>
<VirtualHost *:443>
        ServerAdmin sammy@protonmail.com
        ServerName  cloud.sammy.fr
        ServerAlias www.cloud.sammy.fr
        # We change the document root
        DocumentRoot /home/sammy/Docker/Nextcloud/html

         <Directory /home/sammy/Docker/Nextcloud/html>
                Options +FollowSymlinks
                AllowOverride All

                <IfModule mod_dav.c>
                        Dav off
                SetEnv HOME /home/sammy/Docker/Nextcloud/html
                SetEnv HTTP_HOME /home/sammy/Docker/Nextcloud/html

        ErrorLog ${APACHE_LOG_DIR}/nextcloud.error.log
        CustomLog ${APACHE_LOG_DIR}/nextcloud.access.log combined
RewriteEngine on

Include /etc/letsencrypt/options-ssl-apache.conf
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/wargame.sammy.fr/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/wargame.sammy.fr/privkey.pem

SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLCompression off
SSLHonorCipherOrder on

Header always set Strict-Transport-Security "max-age=15768000; includeSubDomains"

SetEnvIf Host "^(.*)$" THE_HOST=$1
RequestHeader setifempty X-Forwarded-Proto https
RequestHeader setifempty X-Forwarded-Host %{THE_HOST}e
ProxyAddHeaders Off

ProxyPassMatch (.*)(/websocket)$ "ws://$1$2"
ProxyPass / ""
ProxyPassReverse / ""

Backing up

~~~bash mysqldump -u nextcloud_admin -p nextcloud_db > /tmp/nextcloud_backup_20190127.sql cp /tmp/nextcloud_backup_20190127.sql ~/Docker/Nextcloud/db/ ~~~ ## Only-Office ~~~bash sudo docker run -i -t -d -p 81:80 \ --restart always \ -v /mnt/data/onlyoffice-app/onlyoffice/DocumentServer/logs:/var/log/onlyoffice \ -v /mnt/data/onlyoffice-app/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data \ -v /mnt/data/onlyoffice-app/onlyoffice/DocumentServer/lib:/var/lib/onlyoffice \ -v /mnt/data/onlyoffice-app/onlyoffice/DocumentServer/db:/var/lib/postgresql \ onlyoffice/documentserver ~~~