├── data └── .gitkeep ├── logs └── .gitkeep ├── wordpress └── .gitkeep ├── bin ├── wp.sh ├── shell.sh └── wp_db_restore.sh ├── config ├── php │ ├── docker-php-ext-xdebug.ini │ └── php.ini ├── certs │ ├── localhost.crt │ └── localhost.key └── nginx │ └── default.conf ├── .gitignore ├── Dockerfile ├── LICENSE ├── docker-compose.yml └── README.md /data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /logs/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /wordpress/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bin/wp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker-compose exec --user www-data wordpress wp "$@" 4 | -------------------------------------------------------------------------------- /config/php/docker-php-ext-xdebug.ini: -------------------------------------------------------------------------------- 1 | zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20170718/xdebug.so 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /wordpress/* 3 | !/wordpress/.gitkeep 4 | 5 | /data/* 6 | !/data/.gitkeep 7 | 8 | /logs/* 9 | !/logs/.gitkeep 10 | -------------------------------------------------------------------------------- /config/php/php.ini: -------------------------------------------------------------------------------- 1 | # Custom PHP settings 2 | 3 | upload_max_filesize = 100M 4 | post_max_size = 100M 5 | 6 | [mail function] 7 | sendmail_path = /usr/sbin/ssmtp -t 8 | -------------------------------------------------------------------------------- /bin/shell.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -eq 0 ]; then 4 | docker-compose exec --user www-data wordpress bash 5 | else 6 | docker-compose exec --user $1 wordpress bash 7 | fi 8 | -------------------------------------------------------------------------------- /bin/wp_db_restore.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker cp $1 $(docker-compose ps -q wordpress):/tmp/$1 4 | docker exec --user www-data -i $(docker-compose ps -q wordpress) wp db import /tmp/$1 5 | docker exec -i $(docker-compose ps -q wordpress) rm /tmp/$1 6 | 7 | if [ ! -z "$2" ] && [ ! -z "$3" ]; then 8 | docker exec --user www-data -i $(docker-compose ps -q wordpress) wp search-replace $2 $3 9 | fi 10 | 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM wordpress:php7.2-fpm 2 | RUN apt-get update && apt-get install -y git wget 3 | 4 | # install wp-cli 5 | RUN wget https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar -O /usr/local/bin/wp && chmod +x /usr/local/bin/wp 6 | RUN apt-get install -y mysql-client 7 | 8 | # install phpunit 9 | RUN wget https://phar.phpunit.de/phpunit-5.7.phar -O /usr/local/bin/phpunit && chmod +x /usr/local/bin/phpunit 10 | 11 | # install composer 12 | RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer 13 | 14 | RUN pecl install xdebug-2.6.0 15 | 16 | RUN docker-php-ext-install opcache 17 | 18 | -------------------------------------------------------------------------------- /config/certs/localhost.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBuTCCASICCQCHxYY+s2NMXTANBgkqhkiG9w0BAQUFADAhMQswCQYDVQQGEwJz 3 | ZTESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTE4MDMyNTExMDk0MVoXDTE5MDMyNTEx 4 | MDk0MVowITELMAkGA1UEBhMCc2UxEjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkq 5 | hkiG9w0BAQEFAAOBjQAwgYkCgYEAnSfE+JW0DmTzCKUsfOUv1htqaVt6kGMznzxc 6 | MHXpLz5RC+oeSk7p8TlmanctBKOjpqLLveRNv5n+cz8exR3ODHF+2I/a9bPYEKnu 7 | Xy83HStQHd+cRLEa2WveZe2sIJGgXb3DC4/PKKlXDAFe9LXWF1vTEKkmrp0hTIhT 8 | n7r2wHkCAwEAATANBgkqhkiG9w0BAQUFAAOBgQA3HQbAW7lz2KzzuV+PM/w+u/tl 9 | kIJv1bRsJ24xV6xPG6rTjmPE9i9KZnNG5LTJnFdkxtQz5YWBi3evzpW/Tk94f6rr 10 | TQ3uBxLIYWRsinEi3eM+0ZMbr7yd0NVmoUke25o8XfZio41lrl5uRorwfP9WmRos 11 | l0EhZLaP51DDNhZ/uw== 12 | -----END CERTIFICATE----- 13 | -------------------------------------------------------------------------------- /config/certs/localhost.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXAIBAAKBgQCdJ8T4lbQOZPMIpSx85S/WG2ppW3qQYzOfPFwwdekvPlEL6h5K 3 | TunxOWZqdy0Eo6Omosu95E2/mf5zPx7FHc4McX7Yj9r1s9gQqe5fLzcdK1Ad35xE 4 | sRrZa95l7awgkaBdvcMLj88oqVcMAV70tdYXW9MQqSaunSFMiFOfuvbAeQIDAQAB 5 | AoGAdc4FCi72PUARKq7ejXUkCcSdXQL0+l1SqhAOL0mEFiUJjfve3ucO2QOlMTPK 6 | 7Epad6RbRCpq2bDvG6b6QtrXxDFd37GimI3B4sFRgDdVjzjTxvy2d/5QhW9pvvuu 7 | nUxKjwWqv4wL8/uYRaTllxc90hzh+aGnIHkQON9ED7jLEq0CQQDMkzgRHbTo2bLU 8 | tsOHSPR52rS+sJivCqUAafiuUAc2E6e4/zcI8IwBwpvOcbmrPczbg/0sSia4h3Lp 9 | 0XXqeE3vAkEAxKkBEqLKbcb57/AUS9vNj75a376T3IqiByXKeu25reJKE74WKQW5 10 | tUyNL88tz8NqT4NFmTc2MwsjH220gBRAFwJANoLYAr+OsCkqHMIicc7/zeR4GwPF 11 | e4bzlpumNxR+B2vPWl0vFgO62tE3YRguqDGMf8W41W9gx/TXqvQ0Xmj2IwJBAIAd 12 | MUu4rXMSeuRqXG6GxMVt1rmH5792uNM7NUsb7yhuEKAH51vWFQMc2aVZrJh6z5j5 13 | BbAonbBnAvyIdVwy1QUCQFiszfbvAnEnkAqFWo+f3XZTPQ8UCuUOLfRGg/qSgweV 14 | bHm4qX4H6POfD9k6o+wcA5Ztzw7KyRx8oRG8IfDc+98= 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Shahin Agha-Ghassem 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /config/nginx/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80 default_server; 3 | listen 443 ssl; 4 | 5 | ssl_certificate /etc/nginx/certs/localhost.crt; 6 | ssl_certificate_key /etc/nginx/certs/localhost.key; 7 | 8 | # Doesn't really matter because default server, but this way email doesn't throw errors 9 | server_name localhost; 10 | 11 | access_log /var/log/nginx/access.log; 12 | error_log /var/log/nginx/error.log; 13 | 14 | root /var/www/html; 15 | index index.php; 16 | 17 | if (!-e $request_filename) { 18 | rewrite /wp-admin$ $scheme://$host$uri/ permanent; 19 | rewrite ^(/[^/]+)?(/wp-.*) $2 last; 20 | rewrite ^(/[^/]+)?(/.*\.php) $2 last; 21 | } 22 | 23 | location / { 24 | try_files $uri $uri/ /index.php?$args; 25 | } 26 | 27 | location ~ \.php$ { 28 | try_files $uri =404; 29 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 30 | 31 | include /etc/nginx/fastcgi_params; 32 | fastcgi_pass wordpress:9000; 33 | fastcgi_index index.php; 34 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 35 | } 36 | 37 | location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ { 38 | access_log off; log_not_found off; expires max; 39 | 40 | add_header Access-Control-Allow-Origin *; 41 | } 42 | 43 | # This should match upload_max_filesize in php.ini 44 | client_max_body_size 100m; 45 | } 46 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | wordpress: 4 | build: . 5 | links: 6 | - mariadb:mysql 7 | ports: 8 | - "9000:9000" 9 | volumes: 10 | - "./wordpress:/var/www/html" 11 | - "./config/php/php.ini:/usr/local/etc/php/php.ini" 12 | - "./config/php/docker-php-ext-xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini" 13 | - ~/.ssh:/root/.ssh 14 | environment: 15 | - WORDPRESS_DB_NAME=wordpress 16 | - WORDPRESS_TABLE_PREFIX=wp_ 17 | - WORDPRESS_DB_PASSWORD=password 18 | restart: always 19 | mariadb: 20 | image: mariadb:latest 21 | volumes: 22 | - "./data/db:/var/lib/mysql" 23 | restart: always 24 | ports: 25 | - "3306:3306" 26 | environment: 27 | MYSQL_ROOT_PASSWORD: password 28 | MYSQL_DATABASE: wordpress 29 | MYSQL_USER: wordpress 30 | MYSQL_PASSWORD: password 31 | mailcatcher: 32 | image: schickling/mailcatcher 33 | restart: always 34 | ports: 35 | - "1025:1025" 36 | - "1080:1080" 37 | environment: 38 | MAILCATCHER_PORT: 1025 39 | memcached: 40 | image: memcached:latest 41 | restart: always 42 | nginx: 43 | ports: 44 | - "80:80" 45 | - "443:443" 46 | image: nginx:latest 47 | links: 48 | - wordpress 49 | volumes: 50 | - "./wordpress:/var/www/html" 51 | - "./config/nginx/default.conf:/etc/nginx/conf.d/default.conf" 52 | - "./config/certs:/etc/nginx/certs" 53 | - "./logs/nginx:/var/log/nginx" 54 | restart: always 55 | phpmyadmin: 56 | image: phpmyadmin/phpmyadmin 57 | links: 58 | - mariadb:db 59 | ports: 60 | - "8092:80" 61 | depends_on: 62 | - mariadb 63 | environment: 64 | MYSQL_ROOT_PASSWORD: password 65 | MYSQL_DATABASE: wordpress 66 | MYSQL_USER: wordpress 67 | MYSQL_PASSWORD: password 68 | phpmemcachedadmin: 69 | image: hitwe/phpmemcachedadmin 70 | ports: 71 | - "8093:80" 72 | depends_on: 73 | - memcached 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wp-docker-stack 2 | 3 | ## Features 4 | 5 | - WordPress 6 | - nginx 7 | - MariaDB 8 | - PHP-FPM 7.2 9 | - WP-CLI 10 | - MailCatcher 11 | - Composer 12 | - Memcached 13 | - phpMyAdmin 14 | - phpMemcachedAdmin 15 | - PHPUnit 16 | - Xdebug 17 | 18 | ## Folder Structure 19 | 20 | - `wordpress/` contains the WordPress files. 21 | - `config/` contains the config files. 22 | - `logs/` contains the logs. 23 | - `data/` contains the database files. 24 | 25 | ## Requirements 26 | 27 | * [Docker](https://www.docker.com/) 28 | * [docker-compose](https://docs.docker.com/compose/) 29 | 30 | ## Setup 31 | 32 | 1. `git clone https://github.com/shahin8r/wp-docker-stack.git ` 33 | 1. `cd ` 34 | 1. `docker-compose up` 35 | 1. Open [http://localhost](http://localhost) in your browser. 36 | 37 | Default MySQL connection information: 38 | 39 | ``` 40 | Database: wordpress 41 | Username: wordpress 42 | Password: password 43 | Host: mysql 44 | ``` 45 | 46 | ## Tools 47 | 48 | [phpMyAdmin](https://www.phpmyadmin.net) runs on [port 8092](http://localhost:8092). 49 | 50 | [phpMemcachedAdmin](https://github.com/elijaa/phpmemcachedadmin) runs on [port 8093](http://localhost:8093). 51 | 52 | [MailCatcher](https://github.com/alexandresalome/mailcatcher) runs on [port 1080](http://localhost:1080) 53 | 54 | ## WP-CLI 55 | 56 | Run the `wp.sh` shell script inside of `bin/`. Following command will execute as `wp plugin install advanced-custom-fields`. 57 | 58 | ``` 59 | ./bin/wp.sh plugin install advanced-custom-fields 60 | ``` 61 | 62 | ## Bash access 63 | 64 | Run the `shell.sh` shell script inside of `bin/`. 65 | 66 | ``` 67 | ./bin/shell.sh 68 | ``` 69 | By default the shell runs as `www-data` but you can also run as other users. Following command will run the shell as `root`. 70 | ``` 71 | ./bin/shell.sh root 72 | ``` 73 | 74 | ## Import DB 75 | 76 | Run the `wp_db_restore.sh` shell script inside of `bin/`. 77 | ``` 78 | ./bin/wp_db_restore.sh import.sql 79 | ``` 80 | 81 | You can also search-replace the site URL in the new database. 82 | ``` 83 | ./bin/wp_db_restore.sh import.sql '//oldsite.com' '//localhost' 84 | ``` 85 | 86 | ## Credits 87 | - [pcfreak30/wpstack](https://github.com/pcfreak30/wpstack) 88 | - [10up/wp-local-docker](https://github.com/10up/wp-local-docker/) 89 | --------------------------------------------------------------------------------