Docker Compose is a way to deploy and maintain a number of containerized services all at once.
It simplifies the configurations that are sometimes necessary to perform.

Let’s look into it using a Nextcloud Stack.
Nextcloud is an open-source service that allows you to store and share files, doccuments, emails and lots of other cool stuff.
I use it primarily as a DropBox replacement, but there are many other usecases for it.
Let’s look at the parts that make it run:

  • Front-End: a site where you can log into and use the service.
  • Back-End: a database that stores the user information and configurations.
  • Storage: The actual storage that will host your files.

Normally

Normally, you user a Server (computer/vm) that will have an operating system (Windows, Linux, Mac etc..), there you will have to manually install a database (PostgreSQL, MariaDB, etc), Nginx or Apache which are WebServers (they are the applications in charge of handling the traffic coming into the server) and lastly, the front end stack containing the Nextcloud service.
Oh but don’t forget to install PHP, otherwise it will not work!!

Wait, what?!

You can imagine that installing this stack can take quite some time, is prone to human error, and also not so reproducible.
You can check out the documentation: Here
So how can we use the powers of containers to assist us with deploying such a stack??

Solution

Let’s use Docker Compose to create this stack in a few seconds!!
These instructions will work on and linux/mac system with Docker installed.

Requirements

  • A Docker host. (computer/vm with both Docker and the docker-compose plugin installed)

You may consult my docker installation tutorial for more information.)

Let’s do this!

First let’s create a folder in our home directory with a file called docker-compose.yml.

mkdir -p /home/$USER/nextcloud-stack
touch /home/$USER/nextcloud-stack/docker-compose.yml

Now let’s edit that file.

nano /home/$USER/nextcloud-stack/docker-compose.yml

We will add the following code:

---
volumes:
  nextcloud-data:
  nextcloud-db:

services:
  nextcloud-app:
    image: docker.io/library/nextcloud:29.0.1-apache
    container_name: nextcloud-app
    ports:
      - 80:80
    volumes:
      - nextcloud-data:/var/www/html
    environment:
      - MYSQL_PASSWORD=<the_password_you_entered_below>
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_HOST=nextcloud-db
    restart: unless-stopped
  
  nextcloud-db:
    image: docker.io/library/mariadb:10.6.18
    container_name: nextcloud-db
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    volumes:
      - nextcloud-db:/var/lib/mysql
    environment:
      - MYSQL_RANDOM_ROOT_PASSWORD=true
      - MYSQL_PASSWORD=<choose_a_strong_password>
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
    restart: unless-stopped

Now let’s talk about what we’re seeing here.
We’re actually deploying two services, each inside its own container.
The front end is the Nextcloud app, and the backend is a MariaDB instance.
Let’s take a closer look in their configuration:

  • Volume creation: First we create the volumes to be used by the both services (Front-End and Db).
  • Service Declaration: Then we start creating the services configuring them one by one.
    • nextcloud-app: This represents the name of the service we’d like to create (we can name the service anyway we like).
    • image: Here we declare the name of the image to use.
    • container_name: Here we name the container as we please.
    • ports: This is where we map the host’s ports to the ports inside the container. <host_port>:<container_port>
      if we won’t expose the ports there will be no way to reach them from outside the dockr network.
      If the port 80 on your host is already taken by any other application or container you should change the 80 on the left of the ‘:’ in the ports declaration section, but leave the port 80 on the right of the ‘:’ as it is because this is what the app expects.
    • volumes: We specify that we want to use one of the created volumes and mount it to a specific path inside the container ’nextcloud-data:/var/www/html’
      Note: We could have also mapped local folders by specifying them instead of a volume name and commenting out the volume creation portion at the top. (’/path/to/nextcloud_data/:/var/www/html’)
    • environment: Next, we assign some environment variables to be used by the application inside the container.
      In our case we’re setting up login credentials so that the Nextcloud app can login into its Database.
      So whatever values we’ll give in the Database Service’s environment variables below, should be matched in here (the Nextcloud service environment variables)
      Note: These credentials are used between the app and the backend, not by the user.
    • restart: We ask for the container to be restarted if anything goes wrong unless we stop it ourselves.
    • command (in the nextcloud-db service): A custom command to be ran as the container boots.

Okay, we’re done configuring, let’s run this!!
Let’s head into the folder we created, where docker-compose.yml is there, ready and available.

cd /home/$USER/nextcloud-stack

Now let’s deploy the stack.(the -d flag means run in the background)

sudo docker compose -d

If everything went smoothly, you should now be able to point your Web Browser to your docker host and start configuring your new Nextcloud instance.
If Docker is running on a different machine and not your local computer, replace ’localhost’ with the ip of the docker host. (i.e: http://192.168.1.113:80) otherwise:

http://localhost

Enjoy your new Nextcloud instance!!

Note: In order to fully use nextcloud and its capabilities along with its mobile companion app, the Nextcloud instance has to be put behind a reverse proxy with an SSL certificate. This will be reviewed in a future tutorial. This will also require you to own a domain.