Skip to content

Full stack (LEMP) Wordpress docker environment for dev and production use

License

Notifications You must be signed in to change notification settings

garutilorenzo/wordpress-docker

Repository files navigation

wordpress-docker

Wordpress CI GitHub issues GitHub GitHub forks GitHub stars

Table of Contents

Requirements

To use this environment you need Docker an Docker compose installed.

Environment setup

You can find all the settings in the .env file in the root folder of this repository. The default settings are:

Label Required Default Description
ENV yes PROD Valid values are: PROD or DEV. Changing this varialbe the environment will use a different WP image. In DEV environment is used the docker image with embadded Apache, in prod env is used the php-fpm docker image
WORDPRESS_IMAGE yes wordpress The default docker image to use.
WORDPRESS_PROD_VERSION yes php7.4-fpm Production docker image version (php-fpm)
WORDPRESS_DEV_VERSION yes php7.4 Development docker image version (embadded apache)
WORDPRESS_CLI_VERSION yes cli-php7.4 WP client docker image version
WORDPRESS_DB_NAME no wordpress WP database name
WORDPRESS_TABLE_PREFIX no wp_ WP mysql table prefix
WORDPRESS_DB_HOST no myslq MySQL container name
WORDPRESS_DB_USER no wordpress MySQL WP user
WORDPRESS_DB_PASSWORD no password MySQL WP user
MARIADB_VERSION no latest MariaDB container version
MYSQL_ROOT_PASSWORD no s3cretPassW0rd Development docker image version (embadded apache)
MYSQL_DATA_DIR no ./wordpress-sql Local path for MySQL backup/restore
MYSQL_DUMP_DIR no ./mysql-dumps Local where dump_mysql.sh store the MySQL dumps
NGINX_VERSION no latest Nginx container version
SERVER_NAME yes example.com Second level domain name (Example: example.com)
SERVER_ALT_NAME yes www.example.com Third level domain name (Example: www.example.com)
WP_CONTAINER_NAME yes wordpress WP container name (defined in docker-compose.yml)
SECURE_SUBNET no 192.168.0.0/16 Secure subnet to allow traffic to wp-admin, wp-login.php and xmlrpc.php
NGINX_CONF_DIR no ./config/nginx/cfg/ Nginx custom configuration path
NGINX_TEMPLATE_DIR no ./config/nginx/tpl/ Nginx template configuration path
WORDPRESS_UID no 1000 UID of the user running docker
WORDPRESS_GID no 1000 GID of the user running docker
WORDPRESS_USER no app Username used inside the WP docer container
WORDPRESS_GROUP no app Group assigned to WORDPRESS_USER
CUSTOM_WORDPRESS_IMAGE no my-wordpress WP custom docker image name

Use the environment

Development

If you would like to use this environment for local test or if you are developing a new plugin or theme you have to use the develompment version. To use this version create a symlink from docker-compose-dev.yml to docker-compose.yml

ln -s docker-compose-dev.yml docker-compose.yml

and change in the .env file the ENV value to DEV:

ENV=DEV

you can now start the environment with:

docker compose up -d

you can check the logs with:

docker compose logs -f

Now you have:

  • wordpress listening on port 80 (with embadded Apache). Access your wordpress on http://localhost
  • PhpMyAdmin listening on port 8080. Access PMA on http://localhost:8080 (see PhpMyAdmin section)
  • MySQL running but is not listening on any interface
  • Wordpress CLI container available (see WP Cli section)

If you are developing a new theme or plugin is possible that you're facing a permission problem, if you check the files permission under wordpress-src you see that the files are owned by www-data:

drwxr-xr-x  5 www-data www-data  4096 Oct 12 15:34 wordpress-src

To fix this issue see the "Fix permission problem" section

Production

If you are ready to spin up a production environment simply create a symlink from docker-compose-prod.yml to docker-compose.yml:

ln -s docker-compose-prod.yml docker-compose.yml

and check in the .env file that the ENV variable is set to PROD:

ENV=PROD

On production environment you have to configure also nginx. To do so, check the environment variables attached to the nginx container.

The environment variables are:

  • SERVER_NAME: Second level domain name (Example: example.com)
  • SERVER_ALT_NAME: Third level domain name (Example: www.example.com)
  • WP_CONTAINER_NAME: WP container name (defined in docker-compose.yml)
  • SECURE_SUBNET: Secure subnet to allow traffic to wp-admin, wp-login.php and xmlrpc.php (Default 192.168.0.0/16)

you can now start the environment with:

docker compose up -d

you can check the logs with:

docker compose logs -f

Now you have:

  • nginx listening on ports 80 and 443 (optional). (see nignx section)
  • wordpress running with php-fpm container
  • PhpMyAdmin running, traffic to PhpMyAdmin is filtered by nginx (see PhpMyAdmin section)
  • MySQL running but is not listening on any interface
  • Wordpress CLI container available (see WP Cli section)

Import an existing WP site

If you have a running WP site and you want to use this environment you have to extract your existing sources in wordpress-src directory and the MySQL dump in wordpress-sql directory.

NOTE before spin up the environment, check wordpress-src directory permission. If you have build a custom image remember to:

chown -R uid:gid wordpress-src/

if you use the standard wordpress image all files and directory must be owned by user and group (www-data). Your system might be have a different uid and git for the www-data user and group (or you might don't have this user and group), so to fix the permission problem use the uid and gid directly:

chown -R 33:33 wordpress-src/

MySQL NOTE dump can be in plain text or gzipped. The extension must be *.sql or *.gz

MySQL NOTE2 dump will be restored only on the first startup. If you want to restore a new dump you have to:

  • stop mysql container (docker-compose stop mysql)
  • remove the mysql volume (docker volume rm wordpress-docker_mysql). Tip you can find the volume name with: docker volume ls.
  • place the new dump in wordpress-sql
  • start the container (docker-compose up -d)

WP Cli

Check the Wordpress Client referenche here

To use the wordpress CLI use for example:

docker-compose run --rm wordpress-cli wp core install --url=http://localhost --title=test --admin_user=admin [email protected]
Creating wordpress-docker_wordpress-cli_run ... done
Admin password: &kWu5@BldBHixvvaim
Warning: Unable to create directory wp-content/uploads/2021/10. Is its parent directory writable by the server?
Success: WordPress installed successfully.

Fix permission problem

To fix the permission problem the solution is to build a custom image. This image will then run all the processes inside the container with a user with a user with the same uid and gid of your local computer's user.

First we need to check our uid and gid (use the id command):

id

uid=1000(your-local-user) gid=1000(your-local-group) groups=1000(your-local-group),4(adm),24(cdrom),27(sudo)

then in the .env file adjust the variables:

  • WORDPRESS_UID
  • WORDPRESS_GID

with your uid and gid. Now we can build our custom image:

bash build.sh

this will produce two new images, one for wordpress (my-wordpress:php7.4) and one for the wordpress cli (my-wordpress:cli-php7.4). A sample output will be:

Step 4/10 : ARG WORDPRESS_UID
 ---> Using cache
 ---> 7eb312bf432b
Step 5/10 : ARG WORDPRESS_GID
 ---> Using cache
 ---> 917ace616147
Step 6/10 : ARG WORDPRESS_USER
 ---> Using cache
 ---> aad8c3c33e3a
Step 7/10 : ARG WORDPRESS_GROUP
 ---> Using cache
 ---> 14248a4f8db9
Step 8/10 : COPY ./adduser.sh /
 ---> Using cache
 ---> 255a4a665ac6
Step 9/10 : RUN /adduser.sh && rm -rf /adduser.sh
 ---> Using cache
 ---> 8e84c8cce8b2
Step 10/10 : USER ${WORDPRESS_USER}
 ---> Using cache
 ---> d36fbaf33c9e
Successfully built d36fbaf33c9e
Successfully tagged my-wordpress:cli-php7.4

Now to use this new image you have to change the WORDPRESS_IMAGE in the .env file:

WORDPRESS_IMAGE=my-wordpress

Now stop the environment, fix wordpress-src directory permission and bring up the environment with the new image:

docker-compose down
sudo chown -R your-local-user:your-local-group wordpress-src
[sudo] password for your-local-user:

docker-compose up -d

NOTE you can change the custom image name by editing the .env file and change the CUSTOM_WORDPRESS_IMAGE variable.

Nginx

By default Nginx will expose only the http port (port 80). The default configuration is config/nginx/tpl/nginx-http.conf.template. This template will be rendered on every nginx startup. For more information the nignx documentation is available here

By default this template use many security enhancements, removing access to many WP paths and files. You can find the configurations under: config/nginx/cfg/

To disable this security enhancements edit the config/nginx/tpl/nginx-http.conf.template and comment or delete the lines:

# Security
include /etc/nginx/custom.conf.d/nginx-custom-configs.conf;
include /etc/nginx/custom.conf.d/nginx-wp-hardening.conf;

In the default template the following locations are protected:

  • /pma/ (PhpMyAdmin)
  • /xmlrpc.php
  • /wp-admin/
  • wp-login.php

The traffic to this location is filtered by the SECURE_SUBNET environment variable (Default 192.168.0.0/16). Only the client in this subnet will be able to access this locations.

To disable this filter edit the config/nginx/tpl/nginx-http.conf.template file and comment or delete this lines:

allow ${SECURE_SUBNET};
allow 127.0.0.1; 
deny all;

SSL

A configuration example is placed on config/nginx/tpl/nginx-https.conf.example to enable SSL rename this file with the .template extension.

Note remember to delete or rename the nginx-http.conf.template

Certbot/Let's encrypt

Uncomment certbot service in docker-compose.yml

If you have to create a new SSL certificate, modify init_letsencrypt.sh with your domain(s) name(s) and change the email variable. Require the new certificate with:

bash init_letsencrypt.sh

for nginx auto reload, uncomment the command on the nginx service. This is necessary for auto reload nginx when certot renew the ssl certificates.

Now restart nginx and certbot:

docker-compose up -d

Owned SSL certificates

If you have your own SSL certificate modifiy config/nginx/tpl/nginx-https.conf.example and adjust the nginx volumes in docker-compose.yml.

Note remember to rename config/nginx/tpl/nginx-http.conf.example file with the .template extension.

You can now start the services with:

docker-compose up -d

PhpMyAdmin

The default username is root, and the password is the value of MYSQL_ROOT_PASSWORD in the .env file

Development

You can access phpMyAdmin at http://127.0.0.1:8080

Production

You can access phpMyAdmin at http://example.com/pma (access filtered by ip)

MySQL dump

To dump the current MySQL state you can use the dump.sh file. The dump will be saved in mysql-dumps directory (you can customize the dump directory in the .env file)

bash dump_mysql.sh 
ls -la mysql-dumps/

-rw-rw-r--  1 lorenzo lorenzo    473 Oct 18 12:21 wordpress.20211018122109.gz
-rw-rw-r--  1 lorenzo lorenzo 299673 Oct 18 12:22 wordpress.20211018122247.gz