DEV Community

Cover image for Docker(Docker-compose) + Wordpress/Bedrock
Emil Privér
Emil Privér

Posted on • Edited on • Originally published at priver.se

Docker(Docker-compose) + Wordpress/Bedrock

Originally written at: My website

This is a small article on how you can work with Docker and Wordpress(bedrock) to be able to host an wordpress site inside a docker machine.

Information

Wordpress:
Wordpress are one of the most used CMS system for websites. Wordpress is baded on PHP and MySQL. Wordpress was released fist time May 27 2003 by WordpressFoundation. As Wordpress are a big CMS system does a lot of people create plugins, themes and so on for Wordpress which later on, Other people can use.

Bedrock:
Bedrock are an "WordPress boilerplate with modern development tools, easier configuration, and an improved folder structure" - Roots. Bedrock makes it possible to easy handle a Wordpress installation and plugins through an PHP dependency manager named Composer. Bedrock is using Dotenv to be able to easy work with different environments for different purpose. This makes you able to work with production, staging and dev environments etc.
Bedrock is also providing security by isolate web root to limit access to non-web files and also more secure passwords by working with wp-password-bcrypt.

Docker:
Docker is an set coupled SaaS(Software-as-a-service) and PaaS(Platform-as-a-service) products that are using Operating-System-Level Virtualization. This systems or projects that are hosted as a package inside docker are called containers. Multiple Containers are able to to run on the same machine and share the OS kernel that the operativ system provide. Container compared to and Virtual Machine use less space and can handle more applications and require fewer VMs and Operating systems.

Container vs Virtual Machine

Composer:
Composer is a Dependency Manager(Not a Package Manager). Composer makes it possible, in this scenario, to be able to install plugins through command line. More information about composer can you read here


Bedrock and Wordpress

What you need in order to start

  • Docker
  • Composer
  • A MySQL database setup.

Setup

From a folder you like run the

composer create-project roots/bedrock

This command will create a Bedrock folder with necessary files and folders.

Files and folder inside the Bedrock folder:
Bedrock-folder

Information about the folders

  • Config:

    Inside the config folder do you have application.php and env files. The application.php have the same functions as wp-config.php has in an normal wordpress installation. Inside the application.php do you for exempel define database information or auth keys and much more. The env files are used to override some of the code inside application.php file or add more code to the project which you for exempel will use when your developing.

  • Web:

    The web folder have 2 sub folders, index.php and wp-config.php. The app folder contains are the only folder that needed when developing. App folder contains themes, plugins, mu(Most use)-plugins and uploads.

Working with environments

As Bedrock supports use of env, is it really simple to use different .env files. If you add an environments folder with different .env are you able to load different .env files depending of which docker-compose file you will choose(Use of different docker-compose file will come later in this post).

Exempel of .env file:


DB_NAME=database_name
DB_USER=database_user
DB_PASSWORD=database_password

# Optionally, you can use a data source name (DSN)
# When using a DSN, you can remove the DB_NAME, DB_USER, DB_PASSWORD, and DB_HOST variables
# DATABASE_URL=mysql://database_user:database_password@database_host:database_port/database_name

# Optional variables
# DB_HOST=localhost
# DB_PREFIX=wp_

WP_ENV=development
WP_HOME=http://example.com
WP_SITEURL=${WP_HOME}/wp

# Generate your keys here: https://roots.io/salts.html
AUTH_KEY='s]Ae(9f!]KK.hYej(:m6qQ.S[xYQAoA&1IJ1S2P3$pU(5.OQxR*7t3Zcm+0;bjEX'
SECURE_AUTH_KEY='N#1;&qR+eESza?AHsE`:}vHpitkG5|x<{bprQNS3%x;Q*hti=}Li?_Z@?%X;w*E4'
LOGGED_IN_KEY='%-SrP^&lx{#;{,m]2(;J!O^E4Noi{TRf9L_CY-B2XeOB7[D>gh6v&q.Z4YHit%mv'
NONCE_KEY='8ncSeT1eS5X,q>a4y`*=XvczTi>&P92fK4naUmvxEM66;(X1_3kE7qYkRnxoFxFN'
AUTH_SALT='(JGfH8,6P}+>]I+3gyo-Q(KpFN_T&fe[]K+5X!jq}]Cw3l'
SECURE_AUTH_SALT='j>O{0B(94Cy_d!=oLJC$1t&T&7z5A>5&kV:]EdN,!ZNOH>QdVLq`!QTDj&VUj1gG'
LOGGED_IN_SALT='X2WjCA1.?>S+8KT9M19fxD4c#TQ0W>Mdn9`P2X1p)NZ%lS+RuXlI$N5323,?}>L}'
NONCE_SALT='fGcv0C0wk3}+L<&`}{?O;&=$!J3_By$WfnH[Iankm4M*q=)1x/%f5;b(K#^sogUl'


This file are you able to clone into for exempel .env.staging or .env.production to be able to work with different environments. You can add any env variable and load this variable into application.php and the project by defining an variable in the application.php and use the env variable as value. Exempel:

Inside .env.production:

TWITTER_URL = https://twitter.com/emil_priver


And load the env variable inside application.php with:
 Config::define('TWITTER_URL', env('TWITTER_URL')); 

Then you are able to call the new defined variable with TWITTER_URL

Creating the theme.

Developing your theme are the same as with an normal installation. Create your folder inside themes folder and code your theme.

I recommend to work with Roots Sage9 which are an theme creator framework that are using Laravel Blade

Working with plugins

As you use composer to create the Bedrock/Wordpress installation, is it an great idea to work with composer to install plugins aswell. When you create an bedrock installation does bedrock provide a composer.json file inside the installation. This composer.json file does already have WordPress Packagist which are a great repository to use to install and download plugins to Wordpress.

WordPress Packagist

Wordpress Packagist are a Composer repository build to be able to install plugins from command line. Wordpress Packagist makes it possible to install plugins easy via an CI/CD and version controll.

So you know.

Bedrock ads an .gitignore file that are excluding all folder and files inside the plugins, mu-plugins, uploads folders. If you adding custom plugins or files then you need to add that folder to not be excluded inside the .gitignore.


Docker setup

Nginx

Lets go thrue the nginx folder we have in the root directory. This folder have a nginx.conf file and host.conf file. Nginx.conf are a settings file for nginx where you can add custom settings and host.conf are the host file for the site to use. This folder also have an Dockerfile that tells docker which image it should use, but also we're to mount the .conf files.

Exempel of Dockerfile:

 
FROM nginx:latest
COPY /vhost.conf /etc/nginx/conf.d/default.conf
COPY /nginx.conf /etc/nginx/nginx.conf
 
Exempel of nginx.conf:
 
user nginx;
worker_processes auto;

pid /var/run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    include /etc/nginx/conf.d/*.conf;
}
 
Exempel of host.conf:

server {
    listen 80;
    server_name localhost;
    charset utf-8;
    index index.php;
    root /var/www/html/web;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php-fpm:9000;
        fastcgi_index index.php;
        fastcgi_read_timeout 300s;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}
 

PHP

In order to execute our Wordpress PHP code do we need an PHP image. As this is an basic guide will we keep it simple. Inside our docker-compose file can we easy add
  image: php:7.3.6-fpm-alpine3.9  
which will add the php library we need, but this is not the only thing we need to do. If we start our app with docker-compose and going to localhost:8080 will we probably see an 404 page. why? As we haven't mounted the code into PHP so PHP can't access the code. How to fix? By adding volume which mounts the code into docker, like this:
  
volumes:
      - ./website/bedrock:/var/www/html 
 
The PHP part of the docker-compose file should look like this now:
 
 php:
    image: php:7.3.6-fpm-alpine3.9
    volumes:
      - ./website/bedrock:/var/www/html
 

Docker

Docker are an awesome tool to use and makes alot possible while developing with Bedrock and Wordpress. With an CI/CD make this setup it possible to easy deploy multiple container to different servers and use the same database and so on. So how does our final docker-compose file look? Like this:

version: '3'
services:
  nginx:
    build: ./nginx
    volumes:
      - ./website/bedrock:/var/www/html
    ports:
      - '8080:80'
    depends_on:
      - php
  php:
    image: php:7.3.6-fpm-alpine3.9
    volumes:
      - ./website/bedrock:/var/www/html

What if we want to use an different .env file then the one we have inside our bedrock folder? No problem, this is really simple:


version: '3'
services:
  nginx:
    build: ./nginx
    volumes:
      - ./website/bedrock:/var/www/html
    ports:
      - '8080:80'
    depends_on:
      - php
  php:
    image: php:7.3.6-fpm-alpine3.9
    env_file:
      - ./path/to/custom/env-file/.env

    volumes:
      - ./website/bedrock:/var/www/html

By adding env_file into PHP settings of the docker-compose file are we able mount an env file into Bedrock.
If you want to use different env for different enviornments(exempel production or development). Then copy the docker-compose file we have into something else, ex: docker-compose.production.yml and start docker-compose using this file, like this:

  docker-compose -f docker-compose.production.yml up --build  

Or if you want to start the normal docker-compose file use:

  docker-compose up --build  

End

This should be all the stuffs needed to get started with Docker + Bedrock/Wordpress. As this is an basic guide did I want to have everything at a basic level. Docker and Bedrock are great and with adding some information to all this are you able to use different enviornments, use different php.ini and so on.

An exempel of an site using this setup are Leagueshop. This website have Gitlabs CI/CD connected so we never need to login to the server to build the website. The main reason we are using this setup are to be able to scale when more users comes. If many users visits the website, are we able to connect the server we have to an Load Balancer and then startup more servers to be able to run many Wordpress projects on many servers to work against downtime but also have redundancy when alot of users are visiting the site.

DM me for any questions.

Github project that you can use as template: https://github.com/emilpriver/wordpress-docker-bedrock-starter

Twitter for DMs: https://twitter.com/emil_priver

Top comments (7)

Collapse
 
julianfox profile image
Julian Renard

Hey, How can we manage the Wordpress permission with this template?
I tried to run this code in a sh file in a php Dockerfile without success:

!/bin/sh

This script configures WordPress file permissions based on recommendations

from codex.wordpress.org/Hardening_Word...

Author: Michael Conigliaro

WP_OWNER=www-data # <-- wordpress owner
WP_GROUP=www-data # <-- wordpress group
WP_ROOT=/var/www/html/web # <-- wordpress root directory
WS_GROUP=www-data # <-- webserver group

reset to safe defaults

find ${WP_ROOT} -exec chown ${WP_OWNER}:${WP_GROUP} {} \;
find ${WP_ROOT} -type d -exec chmod 755 {} \;
find ${WP_ROOT} -type f -exec chmod 644 {} \;

allow wordpress to manage wp-config.php (but prevent world access)

chgrp ${WS_GROUP} ${WP_ROOT}/wp-config.php
chmod 660 ${WP_ROOT}/wp-config.php

allow wordpress to manage wp-content

find ${WP_ROOT}/app -exec chgrp ${WS_GROUP} {} \;
find ${WP_ROOT}/app -type d -exec chmod 775 {} \;
find ${WP_ROOT}/app -type f -exec chmod 664 {} \;

Collapse
 
emil_priver profile image
Emil Privér

Hi,

I recommend you to create a Dockerfile inside "Website" folder which runs your script on build.

Collapse
 
julianfox profile image
Julian Renard

How can I create a Dockerfile especially for it? Should I add the php Dockerfile in the Website folder.

I tried to add the php dockerfile in website instead of php without success.

Thread Thread
 
emil_priver profile image
Emil Privér

Beat way is to create a Dockerfile inside “website” folder and add context to docker-compose which tells where the Dockerfile is. Inside of that Dockerfile will you need to build everything ans then you will be able to execute your commands

Collapse
 
emil_priver profile image
Emil Privér • Edited

My first article. Please tell me if I typed something bad or anything I should improve.

Collapse
 
pb_gbg profile image
PB

Interesting article, How do you solve media/uploads, and how do you trigger updates on the docker host of new images once you have pushed them?

Collapse
 
emil_priver profile image
Emil Privér

Hi! Media uploads do I solve via an CDN. WP offload media lite (wordpress.org/plugins/amazon-s3-an...) are my recommendation.

Mostly I am using and ci/cd with my projects. So when I push code to master on my git will the ci and cd start build and restart docker image and so on.

But you are able to restart docker with an simple pull and start aswell