An open API service indexing awesome lists of open source software.

https://github.com/garutilorenzo/wordpress-docker

Full stack (LEMP) Wordpress docker environment for dev and production use
https://github.com/garutilorenzo/wordpress-docker

devops docker-compose dockerfile dokcer hacktoberfest lemp lemp-stack letsencrypt nginx phpmyadmin ssl wordpress workflow

Last synced: about 1 month ago
JSON representation

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

Awesome Lists containing this project

README

          

# wordpress-docker

[![Wordpress CI](https://github.com/garutilorenzo/wordpress-docker/actions/workflows/ci.yml/badge.svg)](https://github.com/garutilorenzo/wordpress-docker/actions/workflows/ci.yml)
[![GitHub issues](https://img.shields.io/github/issues/garutilorenzo/wordpress-docker)](https://github.com/garutilorenzo/wordpress-docker/issues)
![GitHub](https://img.shields.io/github/license/garutilorenzo/wordpress-docker)
[![GitHub forks](https://img.shields.io/github/forks/garutilorenzo/wordpress-docker)](https://github.com/garutilorenzo/wordpress-docker/network)
[![GitHub stars](https://img.shields.io/github/stars/garutilorenzo/wordpress-docker)](https://github.com/garutilorenzo/wordpress-docker/stargazers)

# Table of Contents

* [Requirements](#requirements)
* [Environment setup](#environment-setup)
* [Use the environment](#use-the-environment)
* [Import an existing WP site](#import-an-existing-wp-site)
* [WP Cli](#wp-cli)
* [Fix permission problem](#fix-permission-problem)
* [Nginx](#nginx)
* [SSL](#ssl)
* [Certbot/Let's encrypt](#certbotlets-encrypt)
* [Owned SSL certificates](#owned-ssl-certificates)
* [PhpMyAdmin](#phpmyadmin)
* [MySQL dump](#mysql-dump)

### Requirements

To use this environment you need [Docker](https://docs.docker.com/get-docker/) an [Docker compose](https://docs.docker.com/compose/install/) 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](https://hub.docker.com/_/wordpress) 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](#fix-permission-problem) 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](https://developer.wordpress.org/cli/commands/)

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 --admin_email=test@example.com
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](https://hub.docker.com/_/nginx)

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:

```console
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:

```console
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:

```console
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
```