Post/Code

HomeAboutUsesNow

Running WordPress and React with Docker.

Following on from yesterday's post, in addtion to getting WordPress, MySQL and phpMyAdmin running from one docker-compose up command, I wanted to run the React client accessing the WP REST API from that same command.

In order to do so, I created a Dockerfile in the /client folder (the /client folder was created via the npx create-react-app client command). This added the /client folder into the root directory of the project. I placed the Dockerfile within that.

The Dockerfile looks like this:

FROM node:13.6.0-alpine

# set working directory
WORKDIR /var/www/html/client

# add `/var/www/html/node_modules/.bin` to $PATH
ENV PATH /var/www/html/node_modules/.bin:$PATH

# install and cache app dependencies
COPY package.json /var/www/html/client/package.json
COPY package-lock.json /var/www/html/client/package-lock.json
RUN npm ci

# start app
CMD ["npm", "start"]

Furthermore, in the docker-compose.yml file from yesterday, you add a new service called 'client'. You will notice that the I have added a React environment variable named REACT_APP_WP_API. This is set to http://localhost:8080 because that is where the WordPress site is running from. As a result, in order to access the url with something like Axios, you will need to prefix your urls with the appropriate environment variable.

For example (Note the use of process.env.REACT_APP_WP_API):

const res = await axios.get(`${process.env.REACT_APP_WP_API}/wp-json/wp/v2/posts`);

The reason I am no longer using the "proxy" field within React's package.json file is because, within the container running React, there is nothing running on localhost:8080. As such, it is set in the running React app so that it refers to port 8080 on the machine running the containers' localhost. The React client will be found on http://localhost:3000.

Granted, this approach is more verbose, than using "proxy" since you need to prefix all the urls with the environment variable.

Add the following service named 'client' to the docker-compose.yml file:

client:
    depends_on:
      - wordpress
    build:
      context: ./client
      dockerfile: Dockerfile
    volumes:
      - "./client:/var/www/html/client"
      - "/var/www/html/node_modules"
    ports:
      - 3000:3000
    environment:
      - NODE_ENV=development
      - REACT_APP_WP_API=http://localhost:8080

As a result, the entire docker-compose.yml will looks as follows:

version: "3"

services:
  # database
  db:
    image: mysql:5.7
    volumes:
      - db_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}
    networks:
      - wpsite
  # phpMyAdmin
  phpmyadmin:
    depends_on:
      - db
    image: phpmyadmin/phpmyadmin
    restart: always
    ports:
      - "8081:80"
    environment:
      PMA_HOST: db
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    networks:
      - wpsite
  # WordPress
  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    ports:
      # 8000 on localhost, to 80 on container
      - "8080:80"
    restart: always
    # ./ on local machine maps to /var/www/html on Apache, which is where WP files are stored
    volumes: ["./:/var/www/html"]
    environment:
      # 'db' is service above. 3306 is default port on MySQL
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: ${WORDPRESS_DB_USER}
      WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
    networks:
      - wpsite
  client:
    depends_on:
      - wordpress
    build:
      context: ./client
      dockerfile: Dockerfile
    volumes:
      - "./client:/var/www/html/client"
      - "/var/www/html/node_modules"
    ports:
      - 3000:3000
    environment:
      - NODE_ENV=development
      - REACT_APP_WP_API=http://localhost:8080
networks:
  wpsite:
volumes:
  db_data:

With this setup, you can now setup and run and entire working WordPress installation with MySQL, phpMyAdmin and a running React client with one docker-compose up command!