Dockerizing Owncloud

For a long time I wanted a good solution for sharing files with friends and family. I found Owncloud to suite my needs. Luckily there was already a docker image for this that would make my life easier. I just wanted to do some customization like:

  1. I wanted to add letsencrypt to the web-server, so I can get https for encrypted communication.
  2. I wanted to move it to a custom port, because I don’t want shodan and other malware to easily find my Owncloud server
  3. I wanted to separate data and configuration for easy upgrade of owncloud.

So here are my steps to get everything running under Docker.

Dockerfile

First I made a directory for the docker project “opt/docker/owncloud”. Then I create a file named “Dockerfile”:

  1 FROM owncloud
  2
  3 WORKDIR "/root"
  4
  5 RUN     apt-get update && \
  6         apt-get install -y wget smbclient vim mysql-client
  7
  8 RUN     wget https://dl.eff.org/certbot-auto && \
  9         chmod a+x certbot-auto && \
 10         ./certbot-auto -n ; echo Done
 11
 12 COPY    startup.sh /startup.sh
 13 COPY    backup-owncloud.sh /backup-owncloud.sh
 14
 15 RUN     ln -s /etc/apache2/mods-available/ssl.load /etc/apache2/mods-enabled/ssl.load && \
 16         ln -s /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-enabled/default-ssl.conf
 17
 18 CMD     ["/startup.sh"]

This file tells Docker to:

  • Line 1: Build it on top of the official image called “owncloud”.
  • Line 5-10: Install the programs I want in addition to the original image. I want to be able to do SMB mounts, and I want to do letsencrypt certificates.
  • Line 12-13: I copy two custom scripts to my Owncloud image. I have made a special startup-script and a script for doing backups. These will be shown later in this blog posting.
  • Line 15-16: Here I tell apache to enable the SSL module and also to enable SSL on the default website.
  • Line 18: Tells docker to run the startup.sh-script when a new container is instantiated from my image.

Startup Script

Then I created the “startup.sh” script (and chmod it 755):

  1 #!/bin/bash
  2
  3 ./certbot-auto certonly --standalone -d ${domainname} --agree-tos --non-interactive --manual-public-ip-logging-ok --email ${letsencrypt_email}
  4
  5 sed -i "s/SSLCertificateFile.*/SSLCertificateFile \/etc\/letsencrypt\/live\/${domainname}\/fullchain.pem/" /etc/apache2/sites-enabled/default-ssl.conf
  6 sed -i "s/SSLCertificateKeyFile.*/SSLCertificateKeyFile \/etc\/letsencrypt\/live\/${domainname}\/privkey.pem/" /etc/apache2/sites-enabled/default-ssl.conf
  7 sed -i "s/443/${sslport}/" /etc/apache2/sites-enabled/default-ssl.conf
  8 sed -i "s/443/${sslport}/" /etc/apache2/ports.conf
  9
 10 apache2-foreground

This is the script that will be run whenever an instance of my Owncloud image is started. It basically does:

  • Line 3: It sets up a letsencrypt certificate for my domain. The domainname needs to be passed with an environment variable. It will do this by launching a small webserver listening on port 443 and write a verification file that letsencrypt instructs it to do. This proves that I am the owner of my domain.
  • Line 5-6: Changes Apache’s configuration to point to the ssl-certificates that was created in line 3.
  • Line 7-8: Instead of the standard port 443 for the Owncloud webserver, I want to change it to my preferred port.
  • Line 10: Finally apache is launched in foreground mode. This makes it possible for docker to get the log from the docker instance.

Backup Script

The last part of my image is a file called “backup-owncloud.sh” (remember to chmod 755):

  1 #!/bin/bash
  2 tmpdir=$(mktemp -d)
  3 cd $tmpdir
  4
  5 mysqldump -h mysql -u root -p$MYSQL_ROOT_PASSWORD --all-databases > database-dump.sql
  6 tar cvf backup.tar database-dump.sql >/dev/null
  7
  8 { echo /var/www/html/config ; \
  9   find /var/www/html/data -type d -name "files_encryption" ; } \
 10   | tar rvf backup.tar -T - >/dev/null
 11 tar rvf backup.tar /etc/letsencrypt >/dev/null
 12
 13 cat backup.tar
 14
 15 rm -rf $tmpdir

I will use this script later on to take backups of the owncloud server configuration and encryption keys

  • Line 5-6: Dumps the full mysql database and adds it to a tar-file
  • Line 8-11: Adds the owncloud config files and the encryption keys to the tar file
  • Line 13: Return the tarfile to stdout. This will be used later from the host-machine

Building the owncloud-image.

Now we are ready to start building our own version of owncloud. The following command pull’s the original Owncloud image and adds everything according to the Dockerfile:

root@owncloud# docker build -t alex/owncloud .

If everything goes fine, you should have two images:

root@owncloud# docker images
alex/owncloud       latest              cbb6bf2a3743        8 minutes ago       811 MB
owncloud            latest              8720bc439c27        3 weeks ago         549 MB

Creating a compose-file to define how things should run

We now create a file called docker-compose.yml that looks like this:

  1 version: '2'
  2
  3 services:
  4
  5   websvc:
  6     restart: always
  7     image: alex/owncloud
  8     ports:
  9       - 27572:27572
 10       - 443:443
 11     volumes:
 12       - owncloud_www:/var/www/html
 13       - owncloud_letsencrypt:/etc/letsencrypt
 15     environment:
 16       - MYSQL_ROOT_PASSWORD=looooong_password
 17       - domainname=owncloud.example.com
 18       - letsencrypt_email=admin@example.com
 19       - sslport=27572
 20     networks:
 21       - owncloud_internal
 22
 23   mysql:
 24     restart: always
 25     image: mariadb
 26     environment:
 27       - MYSQL_ROOT_PASSWORD=looooong_password
 28     volumes:
 29       - owncloud_db:/var/lib/mysql
 30     networks:
 31       - owncloud_internal
 32
 33 volumes:
 34   owncloud_www:
 35   owncloud_letsencrypt:
 36   owncloud_db:
 37
 38 networks:
 39   owncloud_internal:

Basically this file sets up a mysql-server using the official mariadb docker image. And then an instance of the alex/owncloud image that we built previously. Here is what happens.

The web service:
  • Line 6: After reboot the docker instance will be automatically started.
  • Line 7: The instance is made from the previously built alex/owncloud image
  • Line 8-10: Port 27572 on the hostmachine is directed to the docker-container. This is where I want my owncloud to reside. I also forward port 443 only for the purpose of getting certificates from letsencrypt.
  • Line 11-13: I want to have persistent data when I update my image. So I am pointing to datacontainers (they will automatically be created by docker-compose)
  • Line 16-19: I am passing environment variables to the docker container, with some setup of letsencrypt and apache. These variables are referred to in my two custom scripts
The mysql service:
  • Line 25: This container is based on the official mariadb docker image
  • Line 28-29: I want the Mysql database be persistent. Therefore I let docker compose create a persistent data-volume for this purpose.
For both services:
  • Line 20-21, 30-31, 38-39: Sets up an internal network for both the webserver and the database. Only these two docker containers can talk to each other. They can talk to eachother via hostname (the hostnames defined in line 5 and 23)
  • Line 11-13, 28-29, 33-36: Defines the persistent volumes that docker compose should create, the first time the environment i brought up.

Starting up the containers:

Being in the folder containing the docker-compose.yml file I run:

docker-compose up -d

I check that everything is running like it should:

root@owncloud# docker ps
cea42737aaac        mariadb             "docker-entrypoint..."   30 minutes ago      Up 30 minutes       3306/tcp                                                 owncloud_mysql_1
f80a3b41f3d5        alex/owncloud       "/entrypoint.sh /s..."   30 minutes ago      Up 30 minutes       0.0.0.0:443->443/tcp, 80/tcp, 0.0.0.0:27572->27572/tcp   owncloud_websvc_1

I was now able to browse to https://owncloud.example.com:27572 from my favourite browser. For all this to work I made sure DNS for owncloud.example.com was pointing to my docker-host’s IP.
The first thing I entered was: username=admin, password=admin and pointed the database to host=mysql, user=root, password=looooong_password.

Now the Owncloud is configured and I have the green HTTPS-padlock in my browser.

I checked the logs from the webserver like this:

Docker logs owncloud_websrv_1

My first backup

docker exec -i owncloud_websvc_1 /backup-owncloud.sh > /var/backup/owncloud-backup.tar

I checked that everything was in the tarball. Now I am happy with my Owncloud-server 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *