DEV Community

Benjamin Kampmann for Acter

Posted on

Adding a new Ghost via docker-compose to your traefik setup

Sometimes the easiest and quickest way to try (or even deploy) a new service is by using the recommended docker-compose-setup that they often have as an example. But if you have an existing infrastructure, like we do with the great mother of all self-hosting ansible playbooks, this isn't always easy to integrate. In particular when that infrastructure is managed and started and stopped independently from the additional docker-compose you intend to add. Lucky, who is running their out-most proxy using traefik, because with just a few extra labels your docker-compose becomes available TLS-certs included.

Fortunately for us the MASH-playbook uses traefik and so adding a Ghost setup for testing was quick and easy. Let's look at the docker-compose (for our fictional blog.example.org-address) and then we'll explain some of the specific aspects to address:

version: '3.1'

services:

  ghost:
    image: ghost:5-alpine
    restart: unless-stopped
    environment:
      # see https://ghost.org/docs/config/#configuration-options
      database__client: mysql
      database__connection__host: db
      database__connection__user: root
      database__connection__password: SOME_PRIVATE_ROOT_PASSWORD
      database__connection__database: ghost
      # this url value is just an example, and is likely wrong for your environment!
      url: https://blog.example.org
    volumes:
      - ./data/ghost:/var/lib/ghost/content
    networks:
      default:
      traefik:
        aliases:
         - blog-example-org

    labels:
      - traefik.enable=true
      - traefik.docker.network=traefik
      - traefik.http.routers.blog-example-org.rule=Host(`blog.example.org`)
      - traefik.http.services.blog-example-org.loadbalancer.server.port=2368
      - traefik.http.routers.blog-example-org.entrypoints=web-secure
      - traefik.http.routers.blog-example-org.tls=true
      - traefik.http.routers.blog-example-org.tls.certResolver=default
      - traefik.http.routers.blog-example-org.service=blog-example-org
  db:
    image: mysql:8.0
    restart: unless-stopped
    networks:
     - default
    environment:
      MYSQL_ROOT_PASSWORD: SOME_PRIVATE_ROOT_PASSWORD
      MYSQL_DATABASE: ghost
    volumes:
      - ./data/db:/var/lib/mysql


networks:
  traefik:
    external: true
  default:
    external: false
Enter fullscreen mode Exit fullscreen mode

Alright, there's a few things here that have changes compared to the default example from ghost. We will be ignoring the specific Ghost and MySQL changes as they aren't that relevant but are only included for completeness.

The networks

First and foremost, we have the additional networks-section a the bottom of the configuration with two networks: default which we will use for this specific service and the other that is bridging to the traefik-service, which is marked as external: true telling docker to use the existing set up network. This must the the network the dockerized traefik is using. In the case of MASH this is just called traefik as well.

Secondly we need to the networks-section to both our services, where any internal service is only on the default network and the exposed service must also be on the traefik-network. Here we also give it some specific DNS name within that network for traefik to route the traffic to.

the traefik labels

When traefik is set up to use docker-labels, which is the case in our MASH setup, we can just label our service with a view fields and the traefik service will automatically recognize and configure the routing appropriately. Let's go through them one by one:

  • traefik.enable=true: to configure traefik to route this one. Depending on your setup this might not be needed
  • traefik.docker.network=traefik: the network traefik is on
  • traefik.http.routers.blog-example-org.rule=Host(\blog.example.org): the actual hostname we want this service to be available under between the final ticks. Note that we are creating a custom traefik-router for this called blog-example-org, all the following configuration is also using that router prefix:
  • traefik.http.services.blog-example-org.loadbalancer.server.port=2368: the port on this service the traffic should be routed to
  • traefik.http.routers.blog-example-org.entrypoints=web-secure: if the traefik has multiple outsid eendpoints, which ones to serve - in the MASH case we want this to be available at https, which is named web-secure in our setup.
  • traefik.http.routers.blog-example-org.tls=true: to enable TLS for this router
  • traefik.http.routers.blog-example-org.tls.certResolver=default: use the default DNS cert resolving functionality. In MASH this means we are using lets-encrypt certification
  • traefik.http.routers.blog-example-org.service=blog-example-org: the service to route the traffic to. The value is the dns-alias we gave in the network configuration before.

up and go

And that's about it. Assuming the DNS name already resolves to your server and your traefik is already running just doing a docker compose up -d and a short time later (if it needs to fetch the certificates for the first time), the service will be routed through and be available at blog.example.org. Neat!

Top comments (0)