Getting started with Docker - Deploying ownCloud

Docker is another piece of virtualisation-related technology that’s very much ‘in vogue’ at the minute. And for good reason - most of which will be immediately apparent and familiar if you’ve ever worked with FreeBSD’s Jails or Solaris Zones. It’s billed as ‘The Linux container engine’, with a primary goal of providing a framework for self-contained, easily redistributable and deployable images - independantly of hardware, language, operating system, and so on. The upshot really is that it kind of looks and works a lot like the aforementioned Jails or Zones, in that it’s a way of neatly isolating applications or processes within a self-contained environment that doesn’t require a full-blown hypervisor or the typical set of dedicated virtual hardware in order to run. It’s built on top of a few key Linux kernel features, and the Docker project provides the awesomesauce in terms of tooling and framework to make managing and deploying this stuff in a repeatable and easily transferrable manner a snap.

So what can I use it for, you ask? Good question, and one which I hope to explain with an example image that’ll allow you to run your own container hosting another popular bit of open-source software - Owncloud.

Getting Started

First things first and that’s getting Docker installed. I’ll be using Ubuntu 12.04 in my example, so I suggest you follow the existing (and excellent) documentation on getting Docker up and running. Once you’ve managed that we should be on the same page:

# docker version
Client version: 0.4.8
Server version: 0.4.8
Go version: go1.1

If you’ve followed the installation document correctly, you’ll have a default set of base images to work with as a starting point for a project such as this. We can see what’s available with the following:

# docker images
REPOSITORY          TAG                 ID                  CREATED             SIZE
base                latest              b750fe79269d        3 months ago        24.65 kB (virtual 180.1 MB)
base                ubuntu-12.10        b750fe79269d        3 months ago        24.65 kB (virtual 180.1 MB)
base                ubuntu-quantal      b750fe79269d        3 months ago        24.65 kB (virtual 180.1 MB)
ubuntu              12.10               b750fe79269d        3 months ago        24.65 kB (virtual 180.1 MB)
ubuntu              latest              8dbd9e392a96        12 weeks ago        131.5 MB (virtual 131.5 MB)
ubuntu              quantal             b750fe79269d        3 months ago        24.65 kB (virtual 180.1 MB)

As we’ll be basing our Owncloud install around LTS, we need to pull in that image specifically:

# docker pull ubuntu:12.04

Once that command completes, docker images should include the following in its output:

ubuntu               12.04               8dbd9e392a96        3 months ago        131.5 MB (virtual 131.5 MB)

Now we’ve got our starting point it’s on to Owncloud itself.


As you’d probably expect, the base image we’ve pulled in above is relatively sparse and Owncloud has numerous dependancies including Apache httpd and PHP. There’s a few steps we need to run through before we’re able to install the Owncloud package, including grabbing the various dependancies and amending the Apache configuration. While it’s possible to create a new container from the base image and manually run the necessary commands, Docker has a concept known as ‘Dockerfiles’ which allow you to essentially batch all these steps up and have it run through them for you, delivering a built-to-spec image to use. For Owncloud, we’ll need a Dockerfile with the following:

FROM ubuntu:12.04
RUN echo "deb precise main universe" >> /etc/apt/sources.list
RUN apt-get -y update

RUN dpkg-divert --local --rename --add /sbin/initctl
RUN ln -s /bin/true /sbin/initctl

RUN apt-get install -y apache2 php5 php5-gd php-xml-parser php5-intl php5-sqlite smbclient curl libcurl3 php5-curl bzip2 wget vim

RUN wget -O - | tar jx -C /var/www/
RUN chown -R www-data:www-data /var/www/owncloud

ADD ./001-owncloud.conf /etc/apache2/sites-available/
RUN ln -s /etc/apache2/sites-available/001-owncloud.conf /etc/apache2/sites-enabled/
RUN a2enmod rewrite


CMD ["/usr/sbin/apache2ctl", "-D",  "FOREGROUND"]

Stick the above into a file called Dockerfile. This should all look relatively familiar but there’s a few lines that warrant a bit more explanation:

  • 6-7, which are needed because Upstart is currently broken in Docker. This is a workaround so that apt’s actions successfully complete;
  • 18 tells Docker to NAT port 80 on our host to the container when it’s run;
  • 20 is the command that starts Apache’s httpd in the foreground. This is so that Docker can manage the process.

We also need to inject a simple configuration file for Apache into this image so that it’s included when httpd starts. In the same folder that you’ve saved this Dockerfile, create a new file called 001-owncloud.conf with the following basic directives:

<Directory /var/www/owncloud>
		Options Indexes FollowSymLinks MultiViews
		AllowOverride All
		Order allow,deny
		allow from all

Creating an image

Now we’re in a position to go ahead and create our Owncloud image. Run the following command then sit back and watch the magic:

# docker build -t owncloud .

At this point Docker will run through the steps in your Dockerfile and show you the status at each step:

Uploading context 10240 bytes
Step 1 : FROM ubuntu:12.04
 ---> 8dbd9e392a96
Step 2 : MAINTAINER Nick Jones ""
 ---> Running in bd4ffa2bde51
 ---> 5be3042626e5
Step 3 : RUN echo "deb precise main universe" >> /etc/apt/sources.list
 ---> Running in 6342a8a5bf3a
 ---> 0a5f6332ccf1
Step 4 : RUN apt-get -y update
 ---> Running in 5ba451710f4c
 ---> 25275d3b5080
Step 5 : RUN dpkg-divert --local --rename --add /sbin/initctl
 ---> Running in 0a0473208260
 ---> 927abde6330d
Step 6 : RUN ln -s /bin/true /sbin/initctl
 ---> Running in 92844ba5d028
 ---> 21680ab43143
Step 7 : RUN apt-get install -y apache2 php5 php5-gd php-xml-parser php5-intl php5-sqlite smbclient curl libcurl3 php5-curl bzip2 wget vim
 ---> Running in 0380af0585d2
 ---> 2d2684e40291
Step 8 : RUN wget -O - | tar jx -C /var/www/
 ---> Running in f21f8a471b80
 ---> dc2c75b30292
Step 9 : RUN chown -R www-data:www-data /var/www/owncloud
 ---> Running in b9b3e7220075
 ---> 74f5580c700b
Step 10 : ADD ./001-owncloud.conf /etc/apache2/sites-available/
 ---> c0179ce255ef
Step 11 : RUN ln -s /etc/apache2/sites-available/001-owncloud.conf /etc/apache2/sites-enabled/
 ---> Running in 6ba5513a8432
 ---> f96198e6b59d
Step 12 : RUN a2enmod rewrite
 ---> Running in 161a90a9e940
 ---> 67cea873cdd7
Step 13 : EXPOSE :80
 ---> Running in 9d4cfd17812a
 ---> 00bd10cd6f7d
Step 14 : CMD ["/usr/sbin/apache2ctl", "-D",  "FOREGROUND"]
 ---> Running in 2ccef53a5cfe
 ---> f0d7dbd897c5
Successfully built f0d7dbd897c5

The output of docker images should now include our freshly built Owncloud image:

# docker images | grep owncloud
owncloud            latest              f0d7dbd897c5        About a minute ago   12.29 kB (virtual 779.4 MB)

Running the container

With this built-to-spec image we’re in a position to create a new container which will run our Owncloud ‘stack’, isolated from the host OS and using only the bare essentials:

# docker run -d owncloud

This creates and runs the new container; The -d switch tells Docker to kick it off in the background. If successful that command returns a UUID - d7db4d7c6499 in my case. We can view running containers by doing the following:

# docker ps
ID                  IMAGE               COMMAND                CREATED             STATUS              PORTS
d7db4d7c6499        owncloud:latest     /usr/sbin/apache2ctl   2 minutes ago       Up 2 minutes        80->80  

Looks good so far. If you now fire up your browser and point it at your Docker host /owncloud/ you should be greeted by the initial Owncloud setup page asking you to create an Admin user:

Go ahead and do that and you should now be logged into your new Owncloud install, running atop Docker’s various technologies.

Managing containers

So we now have our Owncloud container and our base image, what’s next? Stopping the container is pretty straightforward:

# docker stop d7db4d7c6499
# docker ps
ID                  IMAGE               COMMAND             CREATED             STATUS              PORTS

The output of docker ps shows us that nothing is currently running. To see all containers, stopped or otherwise, do docker ps -a:

# docker ps -a
ID                  IMAGE               COMMAND                CREATED             STATUS              PORTS
d7db4d7c6499        owncloud:latest     /usr/sbin/apache2ctl   12 minutes ago      Exit 137                                
2ccef53a5cfe        00bd10cd6f7d        /bin/sh -c #(nop) CM   15 minutes ago      Exit 0                                  
9d4cfd17812a        67cea873cdd7        /bin/sh -c #(nop) EX   15 minutes ago      Exit 0                                  
161a90a9e940        f96198e6b59d        /bin/sh -c a2enmod r   15 minutes ago      Exit 0                                  
6ba5513a8432        c0179ce255ef        /bin/sh -c ln -s /et   15 minutes ago      Exit 0                                  

I’ve snipped the output for brevity, but what’s interesting here to note is that Docker effectively created a new container from a new image for each step in our Dockerfile before finally committing that image with the tag we specified with the -t option.

To restart our container, run the following:

# docker restart d7db4d7c6499
# docker ps
ID                  IMAGE               COMMAND                CREATED             STATUS              PORTS
d7db4d7c6499        owncloud:latest     /usr/sbin/apache2ctl   15 minutes ago      Up 18 seconds       80->80             

Next Steps

That’s hopefully given you a feel for Docker and the basics of how to get something up and running. At this point we have a very basic installation of Owncloud, there’s potentially a lot more to do before you’d consider making full-time use of it, such as updating the Apache httpd configuration to enable TLS and adding MySQL into the mix instead of SQLite as the database backend.

tl;dr - Feeling lazy?

What if you don’t care about creating your own image from scratch, you just want to be able to run an Owncloud instance with a couple of commands? From what I’ve described so far, this technology should be all about being able to do just that, right? Yup, of course - just do the following:

# docker pull yankcrime/owncloud

And subsequently spin up a new container from that image:

# docker run -d owncloud

Easy. Starting to understand the potential? (-:

Part 2 - adding SSL and MySQL into the mix - is online here.