Docker Community Forums

Share and learn in the Docker community.

How to run multiple WordPress instances using docker?

So here is the situation. I have setup a WordPress container. The yml file can be seen here

https://github.com/aslamdoctor/wp-boilerplate-docker/blob/master/docker-compose.yml

This run perfectly if I do

docker-compose up -d

What I do after installing WordPress is that I update the site URL to match the project name(using search/replace plugin)

e.g. http://project1.local

And then I add it into my system’s hosts file like this

127.0.0.1 project1.local

So this way the domain is set up for me locally.
Till this step all is working fine.

But now I want to setup another project e.g. project2.local
And I also want to keep project1.local running.

So I do docker-compose up -d from another folder using same yml file.
At this time, I get errors because the port I have used in project1 are already occupied.

Is there a solution for this so that I can run multiple containers for WordPress and run different project like

http://project1.local
http://project2.local 
http://project3.local

etc…

Thank You

This seems to be a private repository.

woops, made it public now :slight_smile:

You can define a base docker-compose.yml and define environment specific docker-compose yml files that override or extend the base declaration: https://docs.docker.com/compose/extends/#example-use-case

Another option, I realy like and prefer over the override/extend is to declare environment specifc values as variable and use envsubst (from the os gettext package) to actualy render values inside the compose.yml. Appart from not beeing able to conditionaly render content blocks, this approach has no limitation about what can be substituted.

It is important to export all placeholdes into the shell environment, because envsubst will only replace those in the input file:
Assumed you use a variable called ${VAR_A} as a placeholder in your yml. Then execute export VAR_A=myvalue && envsubst < my_docker_compose_template.yml | docker-compose -f - up -d to render the value into the yml and let docker-compose use it from stdin.

Does that make sense?

Little complex to understand as I am still new to this and don’t know much about YML file format.
but I will try it. :slight_smile:

Here is an example of what I mean:

Copy the content of this block into a file called docker-compose.template:

version: "3.3"

services:
  # Database
  ${MYSQL_SERVICE_NAME}:
    image: mysql:5.7
    volumes:
      - ${MYSQL_VOLUME_DATA}:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}

  # phpmyadmin
  ${PHPMYADMIN_SERVICE_NAME}:
    depends_on:
      - ${MYSQL_SERVICE_NAME}
    image: phpmyadmin/phpmyadmin
    restart: always
    ports:
      - "${PHPMYADMIN_HOST_PORT}:80"
    environment:
      PMA_HOST: ${MYSQL_SERVICE_NAME}
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}

  # wordpress
  ${WORDPRESS_SERVICE_NAME}:
    depends_on:
      - ${MYSQL_SERVICE_NAME}
    image: wordpress:latest
    restart: always
    volumes:
      - ${WORDPRESS_VOLUME_BIND_MOUNT_HTML}:/var/www/html
      - ${WORdPRESS_VOLUME_BIND_MOUNT_INI}:/usr/local/etc/php/conf.d/uploads.ini
    ports:
      - "${WORDPRESS_HOST_PORT}:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: ${MYSQL_SERVICE_NAME}:3306
      WORDPRESS_DB_USER: ${MYSQL_USER}
      WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
      WORDPRESS_DB_NAME: ${MYSQL_DATABASE}

volumes:
  ${MYSQL_VOLUME_DATA}: {}

Next, create a bash script calle run_env1.sh with following content:

#!/bin/bash -eu
export MYSQL_SERVICE_NAME=db
export MYSQL_VOLUME_DATA=db_data
export MYSQL_ROOT_PASSWORD=root
export MYSQL_DATABASE=project1
export MYSQL_USER=wordpress
export MYSQL_PASSWORD=wordpress
export PHPMYADMIN_SERVICE_NAME=phpmyadmin
export PHPMYADMIN_HOST_PORT=8080
export WORDPRESS_SERVICE_NAME=wordpress
export WORDPRESS_HOST_PORT=80
export WORDPRESS_VOLUME_BIND_MOUNT_HTML=./shared
export WORdPRESS_VOLUME_BIND_MOUNT_INI=./uploads.ini

PROJECT_NAME=env1
envsubst < docker-compose.template | docker-compose --project-name ${PROJECT_NAME} -f - $@

then make run_env1.sh executable with chmod +x run_env1.sh. Instead of calling docker-compose up -d you need to use ./run_env1.sh up -d. The bash script will render the configuration and pass all commands to docker-compose. For each environment creat such a bash file and customize its values. The variable PROJECT_NAME needs to be different per environment - otherwise docker-compose would replace containers of another environment or complain about orphaned containers.

1 Like

Ah right, I got it now. Its like creating .env files on node js projects. but by using shell scripting. Pretty nice idea. But will this work on Windows ?

I wish you would’ve pointed out earlier that you use windows.
The gettext package is common to linux distributions… not to windows.

If you installed the git client for windows, you have a bash shell and envsubst on your system. Though, you will need to call the script from the git-bash shell.