Setting up WordPress

Setting up wordpress in pretty easy in docker – but we need to set up two things – a database and the wordpress server itself. We can do some funny stuff with the setup though, which will display some nice docker compose features we will later use (a lot).

Setting up the database

Setting up the database, we create a new file, we can call it wordpress-compose.yml, to keep it nice and clean away from the general setup we did last time. Using the same structure as last time, and lookup up a MySQL image on docker hub, we construct the following file

name: wordpress-compose

services:
  wordpress-db:
    container_name: wordpress-db
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: root_password
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: password
    networks:
      - wordpress

networks:
  wordpress:

Now, this will start the database, on it’s own isolated network (so not reachable via traefik, since it is a database where users don’t need direct access). However, we don’t want to have the password just lying there in the definition file – since eventually, we want to check in this setup, and passwords in git histories are a big no-no.

Luckily, docker compose comes with support for secrets, and while that is basically just a (server-local) file that is mounted to a specific path, the MySQL image also supports this easily. We just create two files for the passwords (I put them in a /secrets subfolder) on the server (and don’t check them into your version control), and then bind them like this

name: wordpress-compose

services:
  wordpress-db:
    container_name: wordpress-db
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/wordpress_db_root_password
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD_FILE: /run/secrets/wordpress_db_password
    secrets:
      - wordpress_db_root_password
      - wordpress_db_password
    networks:
      - wordpress
secrets:
  wordpress_db_password:
    file: ./secrets/wordpress_db_password.txt
  wordpress_db_root_password:
    file: ./secrets/wordpress_db_root_password.txt

networks:
  wordpress:

Now, when the service starts up, it will load the files at the paths of MYSQL_ROOT_PASSWORD_FILE and MYSQL_PASSWORD_FILE into the (not ‘_FILE’) environment variables, and run as normal. This allows us to give this service access to these specific secrets, while not having files with content checked into the version control.1

Well, that was easy. Now we just need to add the wordpress image on top.

WordPress itself

If we take a look at the wordpress image on docker hub, we can quickly construct a pretty good service in the docker file.

wordpress-cbrams:
    container_name: wordpress-cbrams
    depends_on:
      - wordpress-db
    image: wordpress:latest
    environment:
      WORDPRESS_DB_HOST: wordpress-db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD_FILE: /run/secrets/wordpress_db_password
      WORDPRESS_TABLE_PREFIX: cwp_
      WORDPRESS_CONFIG_EXTRA: |
        define('DOMAIN_CURRENT_SITE', 'wordpress.cbrams.dk');
    secrets:
      - wordpress_db_password
    volumes:
      - /opt/server/data/wordpress/wordpress:/var/www/html
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.wordpress-cbrams.loadbalancer.server.port=80"
      - "traefik.http.routers.wordpress.rule=Host(`wordpress.cbrams.dk`)"
      - "traefik.http.routers.wordpress.entrypoints=web"
      - "traefik.http.routers.wordpress.priority=10"
      - "traefik.http.routers.wordpress-secure.rule=Host(`wordpress.cbrams.dk`)"
      - "traefik.http.routers.wordpress-secure.entrypoints=websecure"
      - "traefik.http.routers.wordpress-secure.priority=10"
      - "traefik.http.routers.wordpress-secure.tls=true"
      - "traefik.http.routers.wordpress-secure.tls.certresolver=httpchallenge"
    networks:
      - wordpress
      - traefik

There are a few things to note here. First is that this service depends on the other service – which is because we only want to start wordpress, once we already know the database is running. Otherwise we will just get errors.

Another is that the host of the database is just the name of the service the database runs on. This is available because they share a network – the wordpress network. This is an isolated network shared by these two services, and they can easily connect to any ports of each others on this network.

Finally, we only need the wordpress database password here, not the root password, and we have elected to only give this service access to that secret. This is a small thing, but will be nice especially for more advanced setups.

Finally, we consume the traefik network to enable the traefik reverse proxy, but this means that we need to append our network definition to include this network, which is not defined in this file (but rather in the file of the traefik service)

networks:
  wordpress:
  traefik:
    name: traefik
    external: true

If you want, you can inlclude an IP whitelist while you do the initial setup of wordpress, and just remove it after. Any way you do it, you start the services with

docker compose -f wordpress-compose.yml up -d

And now we have a blog!

But I want another WordPress

If you want another wordpress installation, you can just extend the same wordpress compose file with another. WordPress is already made for coexisting in the same database, but if you copy the whole setup, you can basically create a whole new isolated instance, where no cross contamination can happen. If you elect to run another wordpress on the same database, just change the URL and the “WORDPRESS_TABLE_PREFIX”, and copy the rest, then it will work. (take a look at an old blod about Lord of the Rings Online I ported into lotro.cbrams.dk, which does this exact thing

  wordpress-cbrams-lotro:
    container_name: wordpress-cbrams-lotro
    depends_on:
      - wordpress-db
    image: wordpress:latest
    environment:
      WORDPRESS_DB_HOST: wordpress-db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD_FILE: /run/secrets/wordpress_db_password
      WORDPRESS_TABLE_PREFIX: lotrowp_
      WORDPRESS_CONFIG_EXTRA: |
        define('DOMAIN_CURRENT_SITE', 'lotro.cbrams.dk');
    secrets:
      - wordpress_db_password
    volumes:
      - /opt/server/data/wordpress/lotro:/var/www/html
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.wordpress-cbrams-lotro.loadbalancer.server.port=80"
      - "traefik.http.routers.wordpress-cbrams-lotro.rule=Host(`lotro.cbrams.dk`)"
      - "traefik.http.routers.wordpress-cbrams-lotro.entrypoints=web"
      - "traefik.http.routers.wordpress-cbrams-lotro.priority=10"
      - "traefik.http.routers.wordpress-cbrams-lotro-secure.rule=Host(`lotro.cbrams.dk`)"
      - "traefik.http.routers.wordpress-cbrams-lotro-secure.entrypoints=websecure"
      - "traefik.http.routers.wordpress-cbrams-lotro-secure.priority=10"
      - "traefik.http.routers.wordpress-cbrams-lotro-secure.tls=true"
      - "traefik.http.routers.wordpress-cbrams-lotro-secure.tls.certresolver=httpchallenge"
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
      - "traefik.http.routers.wordpress-cbrams-lotro.middlewares=redirect-to-https@docker"
    networks:
      - wordpress
      - traefik
  1. If your image does not support these FILE environment variables, or does not support the correct variables you would like to hide, you can create a dockerfile that takes the other as a base image, loads these into the environment, and then runs whatever command the original file ran to start up. It’s pretty easy, I will probably describe it in another post when I need that functionality, and hope I will cross over this again to link it. ↩︎

Posted

in

by

Tags:

Comments

Leave a Reply

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