Test WordPress plugins on your computer with a single docker-compose file

To those unfamiliar with Docker, it is a great way to test WordPress on your own computer without having to buy hosting or figure out how to run a web server.

First you’ll have to install Docker Desktop (Search for “install Docker desktop” to get instructions) and understand how to run docker-compose on your computer.

Really quick command line installer:

wget https://plugincritic.com/wordpress/docker-compose.yml && docker-compose up -d && docker-compose up install

This is the default settings I use and I added all the notes to help myself as double hash comments, “##”.

docker-compose.yml:

version: '3.4'

## Terminal commands at the bottom of the file

x-environment:
  site:
    ## server/url info
    host: &site-host "http://localhost"
    port: &site-port 8000
    phpmyadmin_port: &site-phpmyadmin-port 8080
    ## WP credentials
    user: &site-user "admin"
    password: &site-password "password"
    email: &site-email "admin@example.com"
    ## WP plugins to install, space separated list of slugs, local zip files or urls to zip file
    plugins: &site-plugins ""

  services:
    db: &db-properties
      environment:
        MYSQL_PASSWORD: &mysql-password "password"
        MYSQL_USER: &mysql-user "wordpress"
        MYSQL_DATABASE: &mysql-database "wordpress"
        MYSQL_ROOT_PASSWORD: *mysql-password
        ## Environment variables: https://github.com/docker-library/wordpress/blob/master/wp-config-docker.php
      volumes:
        ## Choose one volume location for where to store the database
        - db_data:/var/lib/mysql  ## save in docker
#        - ./db_data:/var/lib/mysql  ## save locally
    wordpress: &wordpress-properties
      volumes:
        - public_html:/var/www/html
        ## uncomment volumes if you want to work on the files locally
        - ./wp-content/plugins:/var/www/html/wp-content/plugins
        - ./wp-content/themes:/var/www/html/wp-content/themes
#        - ./wp-content/uploads:/var/www/html/wp-content/uploads

x-services-properties: &services-properties
  restart: "no"
  networks:
    - frontend

services:
  db:
    <<: [*db-properties, *services-properties]
    image: mariadb:latest

  wordpress:
    <<: [*wordpress-properties, *services-properties]
    depends_on:
      - db
    image: wordpress:latest
    environment: &wordpress-environment
      WORDPRESS_DB_USER: *mysql-user
      WORDPRESS_DB_PASSWORD: *mysql-password
      WORDPRESS_DB_NAME: *mysql-database
      WORDPRESS_DB_HOST: &wordpress-db-host "db:3306"
    ports:
      - target: 80
        published: *site-port

  install:
    <<: [*wordpress-properties, *services-properties]
    depends_on:
      - db
      - wordpress
    image: wordpress:cli
    profiles:
      - install
    # id for xfs has write privilege in wordpress:latest
    user: xfs
    environment:
      <<: *wordpress-environment
      SITE_HOST: *site-host
      SITE_PORT: *site-port
      SITE_USER: *site-user
      SITE_PASSWORD: *site-password
      SITE_EMAIL: *site-email
      SITE_PLUGINS: *site-plugins
    command: >
      /bin/sh -c '
      echo "Check for database connection";
      until [[ $$(wp db query "SELECT 1" --skip-column-names) -eq 1 ]]; do
        echo "Waiting for the database...";
        sleep 1;
      done;
      echo "Connected to database";
      echo "Install WordPress...";
      wp core install --path="/var/www/html" --url="$${SITE_HOST}:$${SITE_PORT}" --title="PluginCritic" --admin_user="$${SITE_USER}" --admin_password="$${SITE_PASSWORD}" --admin_email="$${SITE_EMAIL}" --skip-email;
      wp post update 2 --post_title="PluginCritic Test Space" --post_content="<p>This is only a test space and should not be used for production websites</p><p>Access your site admin at <a href=\"$${SITE_HOST}:$${SITE_PORT}/wp-admin/\">$${SITE_HOST}:$${SITE_PORT}/wp-admin/</a><ul><li>User: $${SITE_USER}</li><li>Password: $${SITE_PASSWORD}</li></ul></p>";
      wp option update page_on_front 2;
      wp option update show_on_front page;
      [ -z $${SITE_PLUGINS} ] || wp plugin install $${SITE_PLUGINS} --activate;
      echo "WordPress setup is complete, site is available at $${SITE_HOST}:$${SITE_PORT}"
      '

  phpmyadmin:
    <<: *services-properties
    image: phpmyadmin:latest
    profiles:
      - phpmyadmin
    depends_on:
      - db
    environment:
      PMA_USER: *mysql-user
      PMA_PASSWORD: *mysql-password
      PMA_HOST: db
      PMA_PORT: 3306
      PMA_ARBITRARY: "1"
      UPLOAD_LIMIT: 100M
    ports:
      - target: 80
        published: *site-phpmyadmin-port

networks:
  frontend:
    name: frontend

volumes:
  db_data:
  public_html:

## Start and install WordPress
#  $ docker-compose up -d && docker-compose up install

## fix local file permissions if needed
#  $ sudo chmod --recursive 0775 wp-content

## xDebug
##  Copy the WordPress core files to your local system for local path mapping
#  $ docker cp $(docker inspect -f '{{.Name}}' $(docker-compose ps -q wordpress) | tr -d '\r' | cut -c2-):/var/www/html wordpress-core

##  Install xDebug, create the ini entries and restart apache/php
#  $ docker exec $(docker inspect -f '{{.Name}}' $(docker-compose ps -q wordpress) | tr -d '\r' | cut -c2-) bash -c 'pecl install xdebug && echo -e "zend_extension=xdebug\n\n[xdebug]\nxdebug.mode=develop,debug\nxdebug.client_host='host.docker.internal'\nxdebug.discover_client_host=1\nxdebug.client_port=9003\nxdebug.start_with_request=trigger" > /usr/local/etc/php/conf.d/plugincritic-php-ext-xdebug.ini && apache2ctl restart'