1

I have a Docker setup serving two WordPress blogs with a proxy, and using the following structure and docker-compose file:

.
├── nginx-proxy
│   └── docker-compose.yml
└── blogs
    └── docker-compose.yml

docker-compose.yml

version: "3"

services:
  db:
    container_name: ${CONTAINER_DB_NAME}
    image: mariadb:latest
    restart: unless-stopped
    volumes:
      - ${DB_PATH}:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}

  wordpress1:
    depends_on:
      - db
    container_name: ${CONTAINER_WP_NAME1}
    image: wordpress:latest
    restart: unless-stopped
    volumes:
      - ${WP_CORE}:/var/www/html
      - ${WP_CONTENT}:/var/www/html/wp-content
      - ./conf.d/php.ini:/usr/local/etc/php/conf.d/php.ini
    environment:
      WORDPRESS_DB_HOST: ${CONTAINER_DB_NAME1}:3306
      WORDPRESS_DB_NAME: ${MYSQL_DATABASE1}
      WORDPRESS_DB_USER: ${MYSQL_USER1}
      WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD1}
      WORDPRESS_TABLE_PREFIX: ${WORDPRESS_TABLE_PREFIX1}
      VIRTUAL_HOST: ${DOMAINS1}
      LETSENCRYPT_HOST: ${DOMAINS1}
      LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL1}
    logging:
      options:
        max-size: ${LOGGING_OPTIONS_MAX_SIZE1:-200k}

  wordpress2:
    depends_on:
      - db
    container_name: ${CONTAINER_WP_NAME2}
    image: wordpress:latest
    restart: unless-stopped
    volumes:
      - ${WP_CORE}:/var/www/html
      - ${WP_CONTENT}:/var/www/html/wp-content
      - ./conf.d/php.ini:/usr/local/etc/php/conf.d/php.ini
    environment:
      WORDPRESS_DB_HOST: ${CONTAINER_DB_NAME2}:3306
      WORDPRESS_DB_NAME: ${MYSQL_DATABASE2}
      WORDPRESS_DB_USER: ${MYSQL_USER2}
      WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD2}
      WORDPRESS_TABLE_PREFIX: ${WORDPRESS_TABLE_PREFIX2}
      VIRTUAL_HOST: ${DOMAINS2}
      LETSENCRYPT_HOST: ${DOMAINS2}
      LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL2}
    logging:
      options:
        max-size: ${LOGGING_OPTIONS_MAX_SIZE2:-200k}

networks:
  default:
    external:
      name: ${NETWORK}

But I'd like to make it more maintainable. I want to refactor this in order to make a separate container to the mysql db, refactor each blog config to it's own docker-compose file and reference the db on each blog configuration, like so:

.
├── db
│   └── docker-compose.yml
├── blog1
│   └── docker-compose.yml
├── blog2
│   └── docker-compose.yml
└── blog3
    └── docker-compose.yml

db container

version: "3"

services:
  db:
    container_name: ${CONTAINER_DB_NAME}
    image: mariadb:latest
    restart: unless-stopped
    volumes:
      - ${DB_PATH}:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
networks:
  default:
    external:
      name: ${NETWORK}

blog1 container

version: "3"

services:
  wordpress1:
    depends_on:
      - db // Does Docker knows this is db service I created outside it?
    container_name: ${CONTAINER_WP_NAME1}
    image: wordpress:latest
    restart: unless-stopped
    volumes:
        - ${WP_CORE}:/var/www/html
        - ${WP_CONTENT}:/var/www/html/wp-content
        - ./conf.d/php.ini:/usr/local/etc/php/conf.d/php.ini
    environment:
        WORDPRESS_DB_HOST: ${CONTAINER_DB_NAME1}:3306
        WORDPRESS_DB_NAME: ${MYSQL_DATABASE1}
        WORDPRESS_DB_USER: ${MYSQL_USER1}
        WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD1}
        WORDPRESS_TABLE_PREFIX: ${WORDPRESS_TABLE_PREFIX1}
        VIRTUAL_HOST: ${DOMAINS1}
        LETSENCRYPT_HOST: ${DOMAINS1}
        LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL1}
    logging:
        options:
        max-size: ${LOGGING_OPTIONS_MAX_SIZE1:-200k}
networks:
  default:
    external:
      name: ${NETWORK}

... and so on.

I have no idea on how to handle the db connection. Today, I put a reference to it at the "depends_on" section, as the db service configuration lies on the same file as the blog. But how do I invoke the db instance when the sites are declared into separate files? Does Docker knows that the "db" is the db service declared externally to that file?

Any ideas would be great!

2 Answers 2

1

You can specify multiple compose files when running a docker compose command, you could for instance set up a single blog with:

docker-compose -f db.yml -f blog1.yml up

or all of them:

docker-compose -f db.yml -f blog1.yml -f blogX.yml up

Read more on how to specify multiple compose files

Note that you could also use an environment variable to specify your files:

COMPOSE_FILE=db.yml:blog1.yml docker-compose up

More here

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you. But how do I reference the db service into each blog compose file, as it has been split?
In the same way you would do if it was only one, because it actually will be only one, what docker compose does is to take all the files and merge them into a single one. Check the documentation I linked, it explains everything, most of all how docker compose merges property of the same service, but it's not your case so far
Awesome, it works! However, an issue about undefined environment variables showed up, I bet Compose isn't reading the env files contained on each of blog directories. I can, of course, get their contents and merge them manually in the parent .env folder (the one I run the docker-compose cmd from), but that wouldn'd be ideal. So, Is there some way to make compose be aware of the .env files on each dir?
0

The easiest way to set this up would be with a separate database per application. So split this out into blog1/docker-compose.yml and so on as you describe, but have each of those Compose files be self-contained, with its own db: and wordpress: services. You can then launch as many copies of this as you'd like, provided that (a) you set different published ports: for each copy, and (b) that you launch each copy from a differently-named directory.

You should also let Compose set container names for you; this will reduce the possibility of collisions. Delete the container_name: fields. Containers can still reach each other using their services: name as host names; for example, set WORDPRESS_DB_HOST: db:3306. There are docker-compose ... equivalents to most of the standard plain docker commands, but if you do need to directly interact with a container they'll usually be named things like blog1_db_1.

1 Comment

Thanks for your answer! Ok, so maybe I didn't quite understood how Docker handles things. I wanted to split the DB declaration into a separate container because, by doing this, I'd be reusing the same mysql service/installation between the multiple WordPress containers. Am I wrong? As I'm running everything in a VPS, reusing the same mysql installation seems to be ideal for the good resource management, right? If I keep the db config the way it is, that is, coupling a WordPress blog + a db service declaration, wouldn't that be heavier into the VPS, consuming more RAM and CPU?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.