How to deploy Joomla 3.9.27 in docker swarm behind Caddy v2.4.

How to deploy Joomla 3.9.27 in docker swarm behind Caddy v2.4.

Joomla is a free and open-source content management system (CMS) for publishing web content on websites. Web content applications include discussion forums, photo galleries, e-Commerce, and user communities, and numerous other web-based applications.

In this post, I am going to show you how to deploy Joomla, a free and open-source content management system (CMS) for publishing web content behind Caddy 2.4.3 to our Docker Swarm Cluster using the Docker Compose tool.

Web content applications include discussion forums, photo galleries, e-Commerce, and user communities, and numerous other web-based applications.

Joomla is developed by a community of volunteers supported with the legal, organisational and financial resources of Open Source Matters, Inc.

Let’s start with actual deployment…

Prerequisites

Please make sure you should fulfill the below requirements before proceeding to the actual deployment.

  1. Docker Swarm Cluster with GlusterFS as persistent tool.
  2. Caddy as reverse proxy to expose micro-services to external.
  3. Database stack to host application databases.

Introduction

Joomla is one of the world’s most popular software packages. It is used to build, organize, manage and publish content for small businesses, governments, non-profits, and large organizations worldwide.

Joomla is supported by a large ecosystem and powers:

  1. Nearly 2 Millions active websites
  2. Over 9% of all known business websites
  3. Over 6% of the CMS Market World wide
  4. Over 3% of the entire Web

Joomla offers a great opportunity to grow your business by building websites and applications.

The rock solid code base and large global community will help you to build web sites fast.

Whether you are looking to build websites or develop applications, develop templates or extensions or something completely new based on our framework, with Joomla, the possibilities are endless.

Please go through the below links if you want to know more about Joomla

Joomla

Wikipedia

Joomla Features

Joomla is written in PHP, uses object-oriented programming techniques and software design patterns, stores data in a MySQL database.

Joomla includes features such as page caching, RSS feeds, blogs, search, and support for language internationalisation.

It is built on a model–view–controller web application framework that can be used independently of the CMS.

Over 6,000 extensions are available from the Joomla website and more are available from other sources.

As of 2021, it was estimated to be the third most used CMS on the Internet, after WordPress and Shopify.

Here are some of the features that we think that you’ll love

  1. SEO (Search engine optimisation) out of the box
  2. Multi-User Permission Level
  3. Mobile Friendly
  4. Unlimited Design
  5. Multilingual
  6. Flexible & Fully Extensible

If you want to learn more about Joomla features, please go through the Official Joomla Link.

Persist Joomla Data

Containers are fast to deploy and make efficient use of system resources. Developers get application portability and programmable image management and the operations team gets standard run time units of deployment and management.

With all the known benefits of containers, there is one common misperception that the containers are ephemeral, which means if we restart the container or in case of any issues with it, we lose all the data for that particular container. They are only good for stateless micro-service applications and that it’s not possible to containerize stateful applications.

I am going to use GlusterFS to overcome the ephemeral behavior of Containers.

I already set up a replicated GlusterFS volume to have data replicated throughout the cluster if I would like to have some persistent data.

The below diagram explains how the replicated volume works.

GlusterFS Replicated Volume

Volume will be mounted on all the nodes, and when a file is written to the /mnt partition, data will be replicated to all the nodes in the Cluster

Note

In case of any one of the nodes fails, the application automatically starts on other node without loosing any data and that’s the beauty of the replicated volume.

Persistent application state or data needs to survive application restarts and outages. We are storing the data or state in GlusterFS and had periodic backups performed on it.

Joomla site will be available if something goes wrong with any of the nodes on our Docker Swarm Cluster. The data will be available to all the nodes in the cluster because of GlusterFS Replicated Volume.

I am going to create a folder joomla in /mnt directory to map container volume /var/www/html.

cd /mnt
sudo mkdir -p joomla

Tip

Please watch the below video for the GlusterFS Replicated Volume Setup.

Prepare Joomla Environment

I am going to use docker-compose to prepare the environment file for deploying Joomla. The compose file is known as YAML ( YAML stands for Yet Another Markup Language) and has extension .yml or .yaml

I am going to create application folders in /opt directory on manager node in our docker swarm cluster to store configuration files, nothing but docker compose files (.yml or .yaml).

Also, I am going to use the caddy overlay network created in the previous Caddy post.

Now it’s time to create a folder, joomla in /opt directory to place configuration file, i.e, .yml file for Joomla.

Use the below commands to create the folder.

Go to /opt directory by typing cd /opt in Ubuntu console

make a folder, joomla in /opt with sudo mkdir -p joomla

Let’s get into joomla folder by typing cd joomla

Now create a docker-compose file inside the WordPress folder using sudo touch joomla.yml

Open joomla.yml docker-compose file with nano editor using sudo nano joomla.yml and copy and paste the below code in it.

Joomla Docker Compose

Here is the docker-compose file for Joomla. I am going to utilize the MariaDB stack as a back-end database for it that was deployed earlier.

version: "3.7"
 
services:
  joomla:
    image: joomla
    depends_on:
      - maindb
    volumes:
      - /mnt/joomla:/var/www/html
    environment:
      - JOOMLA_DB_HOST=maindb:3306
      - JOOMLA_DB_USER=joomla
      - JOOMLA_DB_NAME=joomladb
      - JOOMLA_DB_PASSWORD=somesecret
    networks:
      - caddy
    ports:
      - "8009:8080"
    deploy:
      placement:
        constraints: [node.role == worker]
      replicas: 1
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure

volumes:
  joomla:
    driver: "local"
networks:
  caddy:
    external: true

Joomla does not support secrets as of now.

Caddyfile – Joomla

The Caddyfile is a convenient Caddy configuration format for humans.

Caddyfile is easy to write, easy to understand, and expressive enough for most use cases.

Please find Production-ready Caddyfile for Joomla.

Learn more about Caddyfile here to get familiar with it.

{
    email you@example.com
    default_sni joomla
    cert_issuer acme
    # Production acme directory
    acme_ca https://acme-v02.api.letsencrypt.org/directory
    # Staging acme directory
    #acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
    servers {
        protocol {
            experimental_http3
            allow_h2c
            strict_sni_host
        }
        timeouts {
            read_body   10s
            read_header 10s
            write       10s
            idle        2m
        }
        max_header_size 16384
    }
}

joomla.example.com {
    log {
        output file /var/log/caddy/joomla.log {
            roll_size 20mb
            roll_keep 2
            roll_keep_for 6h
        }
        format console
        level error
    }
    
    root * /var/www/html
    reverse_proxy joomla:80
    encode gzip zstd
}

Please go to Caddy Post to get more insight to deploy it in the docker swarm cluster.

Final Joomla Docker Compose (Including caddy server configuartion)

Please find the full docker-compose file below. You can deploy as many sites as you want using it.

Don’t forget to map site data directories like /mnt/joomla:/var/www/html in Caddy configuration caddy.yml.

I already wrote an article Caddy in Docker Swarm. Please go through if you want to learn more.

version: "3.7"

services:
  caddy:
    image: tuneitme/caddy
    ports:
      - "80:80"
      - "443:443"
    networks:
      - caddy
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - /mnt/caddydata:/data
      - /mnt/caddyconfig:/config
      - /mnt/caddylogs:/var/log/caddy
      - /mnt/joomla:/var/www/html
    deploy:
      placement:
        constraints:
          - node.role == manager
      replicas: 1
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
  
  joomla:
    image: joomla
    depends_on:
      - maindb
    volumes:
      - /mnt/joomla:/var/www/html
    environment:
      - JOOMLA_DB_HOST=maindb:3306
      - JOOMLA_DB_USER=joomla
      - JOOMLA_DB_NAME=joomladb
      - JOOMLA_DB_PASSWORD=somesecret
    networks:
      - caddy
    ports:
      - "8009:8080"
    deploy:
      placement:
        constraints: [node.role == worker]
      replicas: 1
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure

volumes:
  caddydata:
    driver: "local"
  caddyconfig:
    driver: "local"
  caddylogs:
    driver: "local"
  joomla
    driver: "local"
networks:
  caddy:
    external: true

Here I used a custom Caddy docker container with plugins, like Cloudflare DNS, Caddy Auth Portal etc…

Please find the custom caddy docker image below.

Tuneit Caddy Docker Image

Deploy Joomla Stack using Docker Compose

Now it’s time to deploy our docker-compose file above, joomla.yml using the below command

docker stack deploy --compose-file joomla.yml joomla

In the above command, you have to replace joomla.yml with your docker-compose file name and Joomla with whatever name you want to call this particular application.

With docker compose in docker swarm what ever we are deploying is called as docker stack and it has multiple services in it as per the requirement.

As mentioned earlier I named my docker-compose as joomla.yml and named my application stack as joomla

Check the status of the stack by using docker stack ps joomla

Check caddy stack logs using docker service logs joomla_joomla

One thing we observe is that it automatically re-directs to https with Letsencrypt generated certificate. The information is stored in /data a directory.

I will be using this caddy stack as a reverse proxy / load balancer for the applications I am going to deploy to Docker Swarm Cluster.

Also I use docker network caddy to access the applications externally.

Access / Install Joomla

Now open any browser and type joomla.example.com to access the site. it will automatically be redirected to https://joomla.example.com/installation/index.php ( Be sure to replace example.com with your actual domain name).

Warning

Make sure that you have DNS entry for your application (joomla.example.com) in your DNS Management Application.

Please find below images for your reference.

Joomla Main Configuration Joomla Site & Admin User Details Joomla Database Configuration Joomla Finalize Configuration Joomla Pre-Installation Checks Joomla Installation in Progress Joomla Installation Complete Joomla Installation Complete – Installation Folder Removed Joomla Admin Login Screen Joomla Admin Control Panel Final Joomla Site

Deployment of Joomla behind Caddy in our Docker Swarm is successful

If you enjoyed this tutorial, please give your input/thought on it by commenting below. It would help me to bring more articles that focus on Open Source to self-host.

Stay tuned for other deployments in coming posts… 🙄