├── .env ├── .github ├── issue_template.md └── workflows │ └── workflow.yml ├── .gitignore ├── LICENSE.md ├── Makefile ├── README.md ├── compose.override.yml ├── compose.yml ├── docker.mk ├── tests ├── .env ├── compose.yml ├── run.sh └── tests.sh └── traefik.yml /.env: -------------------------------------------------------------------------------- 1 | ### Documentation available at https://wodby.com/docs/stacks/wordpress/local 2 | ### Changelog can be found at https://github.com/wodby/docker4wordpress/releases 3 | ### Images tags format explained at https://github.com/wodby/docker4wordpress#images-tags 4 | 5 | ### PROJECT SETTINGS 6 | 7 | PROJECT_NAME=my_wordpress_project 8 | PROJECT_BASE_URL=wp.docker.localhost 9 | 10 | DB_NAME=wordpress 11 | DB_USER=wordpress 12 | DB_PASSWORD=wordpress 13 | DB_ROOT_PASSWORD=password 14 | DB_HOST=mariadb 15 | DB_CHARSET=utf8 16 | 17 | # You can generate these using the https://roots.io/salts.html Roots.io secret-key service 18 | # Supported by vanilla WP image only, see compose.override.yml 19 | # If not specified, generated automatically 20 | #WP_AUTH_KEY='generateme' 21 | #WP_AUTH_SALT='generateme' 22 | #WP_SECURE_AUTH_KEY='generateme' 23 | #WP_SECURE_AUTH_SALT='generateme' 24 | #WP_LOGGED_IN_KEY='generateme' 25 | #WP_LOGGED_IN_SALT='generateme' 26 | #WP_NONCE_KEY='generateme' 27 | #WP_NONCE_SALT='generateme' 28 | 29 | # Accepted values are 'direct', 'ssh2', 'ftpext', 'ftpsockets', or 'false' to omit the 30 | # constant letting WordPress determine the best method. Defaults to 'direct' if undefined. 31 | FS_METHOD=direct 32 | 33 | ### --- MARIADB ---- 34 | 35 | MARIADB_TAG=11.4-3.32.0 36 | #MARIADB_TAG=10.11-3.32.0 37 | #MARIADB_TAG=10.6-3.32.0 38 | #MARIADB_TAG=10.5-3.32.0 39 | 40 | ### --- VANILLA WORDPRESS ---- 41 | 42 | WORDPRESS_TAG=6-4.96.6 43 | 44 | ### --- PHP ---- 45 | 46 | # Linux (uid 1000 gid 1000) 47 | 48 | PHP_TAG=8.4-dev-4.64.9 49 | #PHP_TAG=8.3-dev-4.64.9 50 | #PHP_TAG=8.2-dev-4.64.9 51 | #PHP_TAG=8.1-dev-4.64.9 52 | 53 | # macOS (uid 501 gid 20) 54 | 55 | #PHP_TAG=8.3-dev-macos-4.64.9 56 | #PHP_TAG=8.2-dev-macos-4.64.9 57 | #PHP_TAG=8.1-dev-macos-4.64.9 58 | 59 | ### --- NGINX ---- 60 | 61 | NGINX_TAG=1.28-5.43.0 62 | #NGINX_TAG=1.27-5.43.0 63 | 64 | ### --- VALKEY --- 65 | 66 | VALKEY_TAG=8-1.0.1 67 | #VALKEY_TAG=7-1.0.1 68 | 69 | ### --- NODE --- 70 | 71 | NODE_TAG=22-dev-1.51.0 72 | #NODE_TAG=20-dev-1.51.0 73 | #NODE_TAG=18-dev-1.51.0 74 | 75 | ### --- VARNISH --- 76 | 77 | VARNISH_TAG=6.0-4.21.0 78 | 79 | ### --- SOLR --- 80 | 81 | SOLR_TAG=9-5.1.6 82 | 83 | ### --- OPENSEARCH --- 84 | 85 | OPENSEARCH_TAG=2 86 | OPENSEARCH_ADMIN_PASSWORD=VERY%@bad123password 87 | 88 | ### OTHERS 89 | 90 | ADMINER_TAG=5-4.2.4 91 | APACHE_TAG=2.4-4.15.3 92 | MEMCACHED_TAG=1-2.19.1 93 | OPENSMTPD_TAG=7-1.26.0 94 | RSYSLOG_TAG=latest 95 | WEBGRIND_TAG=1-1.36.7 96 | XHPROF_TAG=3.14.7 97 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | ### Codebase 2 | Built-in vanilla WordPress or mounted codebase 3 | 4 | ### Host OS 5 | e.g. macOS Sierra 6 | 7 | ### Docker info output 8 | ``` 9 | # Run "docker info" on the host machine and paste output here 10 | ``` 11 | 12 | ### Docker compose file 13 | Make sure you remove all commented services. 14 | ```yml 15 | # Content of your compose.yml file. Make sure you remove all sensible information you might have there. 16 | ``` 17 | 18 | ### Logs output 19 | ``` 20 | # Run "docker compose logs [service]". Let's say you get 500 error for some reason then it'll be helpful to provide logs for php and http server (nginx/apache) services. 21 | ``` 22 | -------------------------------------------------------------------------------- /.github/workflows/workflow.yml: -------------------------------------------------------------------------------- 1 | name: Run tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | tags: 9 | - "*" 10 | 11 | pull_request: 12 | 13 | jobs: 14 | test: 15 | strategy: 16 | matrix: 17 | php_ver: ["8.4", "8.3", "8.2", "8.1"] 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v4 21 | - name: test 22 | env: 23 | PHP_VER: ${{ matrix.php_ver }} 24 | run: make test 25 | release: 26 | runs-on: ubuntu-latest 27 | if: startsWith(github.ref, 'refs/tags/') 28 | needs: test 29 | steps: 30 | - uses: actions/checkout@v4 31 | - name: prepare artifact 32 | run: cp docker.mk Makefile && tar -czf docker4wordpress.tar.gz compose.yml compose.override.yml Makefile .env traefik.yml 33 | - name: get tag name 34 | id: vars 35 | run: echo tag=${GITHUB_REF#refs/*/} >> $GITHUB_OUTPUT 36 | - uses: xresloader/upload-to-github-release@v1 37 | id: upload_artifact 38 | env: 39 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 40 | with: 41 | file: docker4wordpress.tar.gz 42 | overwrite: true 43 | tags: true 44 | draft: false 45 | tag_name: ${{ steps.vars.outputs.tag }} 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | mutagen.yml.lock 3 | .vscode -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Wodby, Inc. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include docker.mk 2 | 3 | .PHONY: test 4 | 5 | PHP_VER ?= 8.4 6 | 7 | test: 8 | cd ./tests && PHP_VER=$(PHP_VER) ./run.sh 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker-based WordPress Stack 2 | 3 | [![Build Status](https://github.com/wodby/docker4wordpress/workflows/Run%20tests/badge.svg)](https://github.com/wodby/docker4wordpress/actions) 4 | 5 | ## Introduction 6 | 7 | Docker4WordPress is a set of docker images optimized for WordPress. Use `compose.yml` file from this repository to spin 8 | up a local environment for WordPress on Linux, macOS and Windows. 9 | 10 | * Read the docs on [**how to use**](https://wodby.com/docs/stacks/wordpress/local#usage) 11 | * Ask questions on [Discord](http://discord.wodby.com/) 12 | * Ask questions on [Slack](http://slack.wodby.com/) 13 | * Follow [@wodbycloud](https://twitter.com/wodbycloud) for future announcements 14 | 15 | ## Stack 16 | 17 | The WordPress stack consist of the following containers: 18 | 19 | | Container | Versions | Image | ARM64 support | Enabled by default | 20 | |-----------------------|------------------------|-------------------------------------------|---------------|--------------------| 21 | | [Nginx] | 1.28, 1.27 | [wodby/nginx] | ✓ | ✓ | 22 | | [Apache] | 2.4 | [wodby/apache] | ✓ | | 23 | | [WordPress] | 6 | [wodby/wordpress] | ✓ | ✓ | 24 | | [PHP] | 8.4, 8.3, 8.2, 8.1 | [wodby/wordpress-php] | ✓ | | 25 | | Crond | | [wodby/wordpress-php] | ✓ | ✓ | 26 | | [MariaDB] | 11.4, 10.6, 10.5, 10.4 | [wodby/mariadb] | ✓ | ✓ | 27 | | [Valkey] | 8, 7 | [wodby/valkey] | ✓ | | 28 | | [Memcached] | 1 | [wodby/memcached] | ✓ | | 29 | | [Varnish] | 6.0 | [wodby/varnish] | ✓ | | 30 | | [Node.js] | 22, 20, 18 | [wodby/node] | ✓ | | 31 | | [Solr] | 9 | [wodby/solr] | ✓ | | 32 | | OpenSearch | 2 | [opensearchproject/opensearch] | ✓ | | 33 | | OpenSearch Dashboards | 2 | [opensearchproject/opensearch-dashboards] | ✓ | | 34 | | Gotenberg | latest | [gotenberg/gotenberg] | ✓ | | 35 | | Mailpit | latest | [axllent/mailpit] | ✓ | ✓ | 36 | | [OpenSMTPD] | 7 | [wodby/opensmtpd] | ✓ | | 37 | | [Rsyslog] | latest | [wodby/rsyslog] | ✓ | | 38 | | [Webgrind] | 1 | [wodby/webgrind] | ✓ | | 39 | | [XHProf viewer] | latest | [wodby/xhprof] | ✓ | | 40 | | Adminer | 5 | [wodby/adminer] | ✓ | | 41 | | phpMyAdmin | latest | [phpmyadmin/phpmyadmin] | | | 42 | | Traefik | latest | [_/traefik] | ✓ | ✓ | 43 | 44 | ## Documentation 45 | 46 | Full documentation is available at https://wodby.com/docs/stacks/wordpress/local. 47 | 48 | ## Images' tags 49 | 50 | Images tags format is `[VERSION]-[STABILITY_TAG]` where: 51 | 52 | `[VERSION]` is the _version of an application_ (without patch version) running in a container, 53 | e.g. `wodby/nginx:1.15-x.x.x` where Nginx version is `1.15` and `x.x.x` is a stability tag. For some images we include 54 | both major and minor version like PHP `7.2`, for others we include only major like Valkey `7`. 55 | 56 | `[STABILITY_TAG]` is the _version of an image_ that corresponds to a git tag of the image repository, 57 | e.g. `wodby/mariadb:10.2-3.3.8` has MariaDB `10.2` and stability 58 | tag [`3.3.8`](https://github.com/wodby/mariadb/releases/tag/3.3.8). New stability tags include patch updates for 59 | applications and image's fixes/improvements (new env vars, orchestration actions fixes, etc). Stability tag changes 60 | described in the corresponding a git tag description. Stability tags follow [semantic versioning](https://semver.org/). 61 | 62 | We highly encourage to use images only with stability tags. 63 | 64 | ## Maintenance 65 | 66 | We regularly update images used in this stack and release them together, 67 | see [releases page](https://github.com/wodby/docker4wordpress/releases) for full changelog and update instructions. Most 68 | of routine updates for images and this project performed by [the bot](https://github.com/wodbot) via scripts located 69 | at [wodby/images](https://github.com/wodby/images). 70 | 71 | ## Beyond local environment 72 | 73 | Docker4WordPress is a project designed to help you spin up local environment with Docker Compose. If you want to deploy 74 | a consistent stack with orchestrations to your own server, check 75 | out [![WordPress stack on Wodby](https://www.google.com/s2/favicons?domain=wodby.com) Wodby](https://wodby.com/stacks/wordpress). 76 | 77 | ## Other Docker4x projects 78 | 79 | * [docker4php](https://github.com/wodby/docker4php) 80 | * [docker4drupal](https://github.com/wodby/docker4drupal) 81 | * [docker4ruby](https://github.com/wodby/docker4ruby) 82 | * [docker4python](https://github.com/wodby/docker4python) 83 | 84 | ## License 85 | 86 | This project is licensed under the MIT open source license. 87 | 88 | [Apache]: https://wodby.com/docs/stacks/wordpress/containers#apache 89 | 90 | [MariaDB]: https://wodby.com/docs/stacks/wordpress/containers#mariadb 91 | 92 | [Memcached]: https://wodby.com/docs/stacks/wordpress/containers#memcached 93 | 94 | [Nginx]: https://wodby.com/docs/stacks/wordpress/containers#nginx 95 | 96 | [Node.js]: https://wodby.com/docs/stacks/wordpress/containers#nodejs 97 | 98 | [OpenSMTPD]: https://wodby.com/docs/stacks/wordpress/containers#opensmtpd 99 | 100 | [PHP]: https://wodby.com/docs/stacks/wordpress/containers#php 101 | 102 | [Rsyslog]: https://wodby.com/docs/stacks/wordpress/containers#rsyslog 103 | 104 | [Solr]: https://wodby.com/docs/stacks/solr 105 | 106 | [Varnish]: https://wodby.com/docs/stacks/wordpress/containers#varnish 107 | 108 | [Valkey]: https://wodby.com/docs/stacks/wordpress/containers#valkey 109 | 110 | [Webgrind]: https://wodby.com/docs/stacks/wordpress/containers#webgrind 111 | 112 | [Wordpress]: https://wodby.com/docs/stacks/wordpress/containers#php 113 | 114 | [XHProf viewer]: https://wodby.com/docs/stacks/php/containers#xhprof-viewer 115 | 116 | [_/traefik]: https://hub.docker.com/_/traefik 117 | 118 | [gotenberg/gotenberg]: https://hub.docker.com/r/gotenberg/gotenberg 119 | 120 | [axllent/mailpit]: https://hub.docker.com/r/axllent/mailpit 121 | 122 | [phpmyadmin/phpmyadmin]: https://hub.docker.com/r/phpmyadmin/phpmyadmin 123 | 124 | [wodby/adminer]: https://github.com/wodby/adminer 125 | 126 | [wodby/apache]: https://github.com/wodby/apache 127 | 128 | [wodby/mariadb]: https://github.com/wodby/mariadb 129 | 130 | [wodby/memcached]: https://github.com/wodby/memcached 131 | 132 | [wodby/nginx]: https://github.com/wodby/nginx 133 | 134 | [wodby/node]: https://github.com/wodby/node 135 | 136 | [wodby/opensmtpd]: https://github.com/wodby/opensmtpd 137 | 138 | [wodby/valkey]: https://github.com/wodby/valkey 139 | 140 | [wodby/rsyslog]: https://github.com/wodby/rsyslog 141 | 142 | [wodby/solr]: https://github.com/wodby/solr 143 | 144 | [wodby/varnish]: https://github.com/wodby/varnish 145 | 146 | [wodby/webgrind]: https://hub.docker.com/r/wodby/webgrind 147 | 148 | [wodby/wordpress-php]: https://github.com/wodby/wordpress-php 149 | 150 | [wodby/wordpress]: https://github.com/wodby/wordpress 151 | 152 | [wodby/xhprof]: https://github.com/wodby/xhprof 153 | 154 | [opensearchproject/opensearch]: https://hub.docker.com/r/opensearchproject/opensearch 155 | 156 | [opensearchproject/opensearch-dashboards]: https://hub.docker.com/r/opensearchproject/opensearch-dashboards 157 | -------------------------------------------------------------------------------- /compose.override.yml: -------------------------------------------------------------------------------- 1 | services: 2 | php: 3 | image: wodby/wordpress:$WORDPRESS_TAG 4 | environment: 5 | PHP_FPM_CLEAR_ENV: "no" 6 | WP_AUTH_KEY: $WP_AUTH_KEY 7 | WP_AUTH_SALT: $WP_AUTH_SALT 8 | WP_SECURE_AUTH_KEY: $WP_SECURE_AUTH_KEY 9 | WP_SECURE_AUTH_SALT: $WP_SECURE_AUTH_SALT 10 | WP_LOGGED_IN_KEY: $WP_LOGGED_IN_KEY 11 | WP_LOGGED_IN_SALT: $WP_LOGGED_IN_SALT 12 | WP_NONCE_KEY: $WP_NONCE_KEY 13 | WP_NONCE_SALT: $WP_NONCE_SALT 14 | volumes: 15 | - codebase:/var/www/html 16 | 17 | crond: 18 | image: wodby/wordpress:$WORDPRESS_TAG 19 | environment: 20 | PHP_FPM_CLEAR_ENV: "no" 21 | volumes: 22 | - codebase:/var/www/html 23 | 24 | nginx: 25 | volumes: 26 | - codebase:/var/www/html 27 | 28 | # webgrind: 29 | # volumes: 30 | # - codebase:/mnt/codebase 31 | 32 | volumes: 33 | codebase: 34 | -------------------------------------------------------------------------------- /compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | mariadb: 3 | image: wodby/mariadb:$MARIADB_TAG 4 | container_name: "${PROJECT_NAME}_mariadb" 5 | stop_grace_period: 30s 6 | environment: 7 | MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD 8 | MYSQL_DATABASE: $DB_NAME 9 | MYSQL_USER: $DB_USER 10 | MYSQL_PASSWORD: $DB_PASSWORD 11 | # volumes: 12 | # - ./mariadb-init:/docker-entrypoint-initdb.d # Place init .sql file(s) here. 13 | # - /path/to/mariadb/data/on/host:/var/lib/mysql # I want to manage volumes manually. 14 | 15 | php: 16 | image: wodby/wordpress-php:$PHP_TAG 17 | container_name: "${PROJECT_NAME}_php" 18 | environment: 19 | # By default xdebug extension also disabled. 20 | PHP_EXTENSIONS_DISABLE: xhprof,spx 21 | PHP_MAIL_MIXED_LF_AND_CRLF: "On" 22 | # Mailpit: 23 | MSMTP_HOST: mailpit 24 | MSMTP_PORT: 1025 25 | # # OpenSMTPD: 26 | # MSMTP_HOST: opensmtpd 27 | # MSMTP_PORT: 25 28 | DB_HOST: $DB_HOST 29 | DB_USER: $DB_USER 30 | DB_PASSWORD: $DB_PASSWORD 31 | DB_NAME: $DB_NAME 32 | PHP_FPM_USER: wodby 33 | PHP_FPM_GROUP: wodby 34 | # # Read instructions at https://wodby.com/docs/stacks/wordpress/local#xdebug 35 | # PHP_XDEBUG_MODE: debug 36 | # PHP_XDEBUG_MODE: profile 37 | # PHP_XDEBUG_USE_COMPRESSION: false 38 | # PHP_IDE_CONFIG: serverName=my-ide 39 | # PHP_XDEBUG_IDEKEY: "my-ide" 40 | # PHP_XDEBUG_LOG: /tmp/php-xdebug.log 41 | volumes: 42 | - ./:/var/www/html:cached 43 | ## Alternative for macOS users: Mutagen https://wodby.com/docs/stacks/wordpress/local#docker-for-mac 44 | # - wordpress:/var/www/html 45 | # # For XHProf and Xdebug profiler traces 46 | # - files:/mnt/files 47 | 48 | crond: 49 | image: wodby/wordpress-php:$PHP_TAG 50 | init: true 51 | container_name: "${PROJECT_NAME}_crond" 52 | environment: 53 | CRONTAB: "0 * * * * wp cron event run --due-now --path=/var/www/html" 54 | command: sudo crond -f -d 0 55 | volumes: 56 | - ./:/var/www/html:cached 57 | ## Alternative for macOS users: Mutagen https://wodby.com/docs/stacks/wordpress/local#docker-for-mac 58 | # - wordpress:/var/www/html 59 | 60 | nginx: 61 | image: wodby/nginx:$NGINX_TAG 62 | container_name: "${PROJECT_NAME}_nginx" 63 | depends_on: 64 | - php 65 | environment: 66 | NGINX_STATIC_OPEN_FILE_CACHE: "off" 67 | NGINX_ERROR_LOG_LEVEL: debug 68 | NGINX_BACKEND_HOST: php 69 | NGINX_VHOST_PRESET: wordpress 70 | #NGINX_SERVER_ROOT: /var/www/html/subdir 71 | volumes: 72 | - ./:/var/www/html:cached 73 | ## Alternative for macOS users: Mutagen https://wodby.com/docs/stacks/wordpress/local#docker-for-mac 74 | # - wordpress:/var/www/html 75 | labels: 76 | - "traefik.http.routers.${PROJECT_NAME}_nginx.rule=Host(`${PROJECT_BASE_URL}`)" 77 | 78 | mailpit: 79 | image: axllent/mailpit 80 | container_name: "${PROJECT_NAME}_mailpit" 81 | labels: 82 | - "traefik.http.services.${PROJECT_NAME}_mailpit.loadbalancer.server.port=8025" 83 | - "traefik.http.routers.${PROJECT_NAME}_mailpit.rule=Host(`mailpit.${PROJECT_BASE_URL}`)" 84 | 85 | # apache: 86 | # image: wodby/apache:$APACHE_TAG 87 | # container_name: "${PROJECT_NAME}_apache" 88 | # depends_on: 89 | # - php 90 | # environment: 91 | # APACHE_LOG_LEVEL: debug 92 | # APACHE_BACKEND_HOST: php 93 | # APACHE_VHOST_PRESET: php 94 | # volumes: 95 | # - ./:/var/www/html:cached 96 | ## Alternative for macOS users: Mutagen https://wodby.com/docs/stacks/wordpress/local#docker-for-mac 97 | # - wordpress:/var/www/html 98 | # labels: 99 | # - "traefik.http.routers.${PROJECT_NAME}_apache.rule=Host(`${PROJECT_BASE_URL}`)" 100 | 101 | # varnish: 102 | # image: wodby/varnish:$VARNISH_TAG 103 | # container_name: "${PROJECT_NAME}_varnish" 104 | # depends_on: 105 | # - nginx 106 | # environment: 107 | # VARNISH_SECRET: secret 108 | # VARNISH_BACKEND_HOST: nginx 109 | # VARNISH_BACKEND_PORT: 80 110 | # VARNISH_CONFIG_PRESET: wordpress 111 | # VARNISH_ALLOW_UNRESTRICTED_PURGE: 1 112 | # labels: 113 | # - "traefik.http.services.${PROJECT_NAME}_varnish.loadbalancer.server.port=6081" 114 | # - "traefik.http.routers.${PROJECT_NAME}_varnish.rule=Host(`varnish.${PROJECT_BASE_URL}`)" 115 | 116 | # valkey: 117 | # container_name: "${PROJECT_NAME}_valkey" 118 | # image: wodby/valkey:$VALKEY_TAG 119 | 120 | # adminer: 121 | # container_name: "${PROJECT_NAME}_adminer" 122 | # image: wodby/adminer:$ADMINER_TAG 123 | # init: true 124 | # environment: 125 | # ADMINER_DEFAULT_DB_HOST: $DB_HOST 126 | # ADMINER_DEFAULT_DB_NAME: $DB_NAME 127 | # labels: 128 | # - "traefik.http.routers.${PROJECT_NAME}_adminer.rule=Host(`adminer.${PROJECT_BASE_URL}`)" 129 | 130 | # webgrind: 131 | # image: wodby/webgrind:$WEBGRIND_TAG 132 | # container_name: "${PROJECT_NAME}_webgrind" 133 | # environment: 134 | # WEBGRIND_PROFILER_DIR: /mnt/files/xdebug 135 | # labels: 136 | # - "traefik.http.routers.${PROJECT_NAME}_webgrind.rule=Host(`webgrind.${PROJECT_BASE_URL}`)" 137 | # volumes: 138 | # - files:/mnt/files 139 | # - ./:/mnt/codebase:cached 140 | 141 | # pma: 142 | # image: phpmyadmin/phpmyadmin 143 | # container_name: "${PROJECT_NAME}_pma" 144 | # environment: 145 | # PMA_HOST: $DB_HOST 146 | # PMA_USER: $DB_USER 147 | # PMA_PASSWORD: $DB_PASSWORD 148 | # PHP_UPLOAD_MAX_FILESIZE: 1G 149 | # PHP_MAX_INPUT_VARS: 1G 150 | # labels: 151 | # - "traefik.http.routers.${PROJECT_NAME}_pma.rule=Host(`pma.${PROJECT_BASE_URL}`)" 152 | 153 | # gotenberg: 154 | # image: gotenberg/gotenberg 155 | # container_name: "${PROJECT_NAME}_gotenberg" 156 | 157 | # solr: 158 | # image: wodby/solr:$SOLR_TAG 159 | # container_name: "${PROJECT_NAME}_solr" 160 | # environment: 161 | # SOLR_HEAP: 1024m 162 | # labels: 163 | # - "traefik.http.services.${PROJECT_NAME}_solr.loadbalancer.server.port=8983" 164 | # - "traefik.http.routers.${PROJECT_NAME}_solr.rule=Host(`solr.${PROJECT_BASE_URL}`)" 165 | 166 | # opensearch: 167 | # image: opensearchproject/opensearch:$OPENSEARCH_TAG 168 | # environment: 169 | # "discovery.type": "single-node" 170 | # "plugins.security.disabled": true 171 | # OPENSEARCH_INITIAL_ADMIN_PASSWORD: $OPENSEARCH_ADMIN_PASSWORD 172 | # 173 | # opensearch-dashboards: 174 | # image: opensearchproject/opensearch-dashboards:$OPENSEARCH_TAG 175 | # environment: 176 | # OPENSEARCH_HOSTS: '["http://opensearch:9200"]' 177 | # DISABLE_SECURITY_DASHBOARDS_PLUGIN: true 178 | # depends_on: 179 | # - opensearch 180 | # labels: 181 | # - "traefik.http.services.${PROJECT_NAME}_opensearch.loadbalancer.server.port=5601" 182 | # - "traefik.http.routers.${PROJECT_NAME}_opensearch.rule=Host(`opensearch.${PROJECT_BASE_URL}`)" 183 | 184 | # node: 185 | # image: wodby/node:$NODE_TAG 186 | # container_name: "${PROJECT_NAME}_node" 187 | # working_dir: /app 188 | # labels: 189 | # - "traefik.http.services.${PROJECT_NAME}_node.loadbalancer.server.port=3000" 190 | # - "traefik.http.routers.${PROJECT_NAME}_node.rule=Host(`node.${PROJECT_BASE_URL}`)" 191 | # expose: 192 | # - "3000" 193 | # volumes: 194 | # - ./path/to/your/single-page-app:/app 195 | # command: sh -c 'npm install && npm run start' 196 | 197 | # memcached: 198 | # container_name: "${PROJECT_NAME}_memcached" 199 | # image: wodby/memcached:$MEMCACHED_TAG 200 | 201 | # opensmtpd: 202 | # container_name: "${PROJECT_NAME}_opensmtpd" 203 | # image: wodby/opensmtpd:$OPENSMTPD_TAG 204 | 205 | # rsyslog: 206 | # container_name: "${PROJECT_NAME}_rsyslog" 207 | # image: wodby/rsyslog:$RSYSLOG_TAG 208 | 209 | # xhprof: 210 | # image: wodby/xhprof:$XHPROF_TAG 211 | # restart: always 212 | # volumes: 213 | # - files:/mnt/files 214 | # labels: 215 | # - "traefik.http.routers.${PROJECT_NAME}_xhprof.rule=Host(`xhprof.${PROJECT_BASE_URL}`)" 216 | 217 | traefik: 218 | image: traefik:v2.0 219 | container_name: "${PROJECT_NAME}_traefik" 220 | command: --api.insecure=true --providers.docker 221 | ports: 222 | - '8000:80' 223 | # - '8080:8080' # Dashboard 224 | volumes: 225 | - /var/run/docker.sock:/var/run/docker.sock 226 | 227 | #x-mutagen: 228 | # sync: 229 | # defaults: 230 | # ignore: 231 | # vcs: true 232 | # paths: 233 | # - .DS_Store 234 | # - .history 235 | # - .idea 236 | # wordpress: 237 | # alpha: "." 238 | # beta: "volume://wordpress" 239 | # configurationBeta: 240 | # permissions: 241 | # defaultFileMode: 0644 242 | # defaultDirectoryMode: 0755 243 | # defaultOwner: "id:501" 244 | # defaultGroup: "id:20" 245 | 246 | #volumes: 247 | ## For macOS users (Mutagen) 248 | # wordpress: 249 | ## For Xdebug profiler 250 | # files: 251 | -------------------------------------------------------------------------------- /docker.mk: -------------------------------------------------------------------------------- 1 | include .env 2 | 3 | .PHONY: up down stop prune ps shell wp logs mutagen 4 | 5 | default: up 6 | 7 | WP_ROOT ?= /var/www/html/ 8 | 9 | ## help : Print commands help. 10 | help : docker.mk 11 | @sed -n 's/^##//p' $< 12 | 13 | ## up : Start up containers. 14 | up: 15 | @echo "Starting up containers for $(PROJECT_NAME)..." 16 | docker compose pull 17 | docker compose up -d --remove-orphans 18 | 19 | mutagen: 20 | mutagen-compose up 21 | 22 | ## down : Stop containers. 23 | down: stop 24 | 25 | ## start : Start containers without updating. 26 | start: 27 | @echo "Starting containers for $(PROJECT_NAME) from where you left off..." 28 | @docker compose start 29 | 30 | ## stop : Stop containers. 31 | stop: 32 | @echo "Stopping containers for $(PROJECT_NAME)..." 33 | @docker compose stop 34 | 35 | ## prune : Remove containers and their volumes. 36 | ## You can optionally pass an argument with the service name to prune single container 37 | ## prune mariadb : Prune `mariadb` container and remove its volumes. 38 | ## prune mariadb solr : Prune `mariadb` and `solr` containers and remove their volumes. 39 | prune: 40 | @echo "Removing containers for $(PROJECT_NAME)..." 41 | @docker compose down -v $(filter-out $@,$(MAKECMDGOALS)) 42 | 43 | ## ps : List running containers. 44 | ps: 45 | @docker ps --filter name='$(PROJECT_NAME)*' 46 | 47 | ## shell : Access `php` container via shell. 48 | ## You can optionally pass an argument with a service name to open a shell on the specified container 49 | shell: 50 | docker exec -ti -e COLUMNS=$(shell tput cols) -e LINES=$(shell tput lines) $(shell docker ps --filter name='$(PROJECT_NAME)_$(or $(filter-out $@,$(MAKECMDGOALS)), 'php')' --format "{{ .ID }}") sh 51 | 52 | ## wp : Executes `wp cli` command in a specified `WP_ROOT` directory (default is `/var/www/html/`). 53 | ## Doesn't support --flag arguments. 54 | wp: 55 | docker exec $(shell docker ps --filter name='^/$(PROJECT_NAME)_php' --format "{{ .ID }}") wp --path=$(WP_ROOT) $(filter-out $@,$(MAKECMDGOALS)) 56 | 57 | ## logs : View containers logs. 58 | ## You can optinally pass an argument with the service name to limit logs 59 | ## logs php : View `php` container logs. 60 | ## logs nginx php : View `nginx` and `php` containers logs. 61 | logs: 62 | @docker compose logs -f $(filter-out $@,$(MAKECMDGOALS)) 63 | 64 | # https://stackoverflow.com/a/6273809/1826109 65 | %: 66 | @: 67 | -------------------------------------------------------------------------------- /tests/.env: -------------------------------------------------------------------------------- 1 | PROJECT_BASE_URL=wordpress.test 2 | 3 | DB_NAME=wordpress 4 | DB_USER=wordpress 5 | DB_PASSWORD=wordpress 6 | DB_ROOT_PASSWORD=password 7 | DB_HOST=mariadb 8 | 9 | MARIADB_TAG=11.4-3.32.0 10 | NGINX_TAG=1.27-5.43.0 11 | VALKEY_TAG=8-1.0.1 12 | VARNISH_TAG=6.0-4.21.0 13 | 14 | WORDPRESS_STABILITY_TAG=4.96.6 -------------------------------------------------------------------------------- /tests/compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | mariadb: 3 | image: wodby/mariadb:$MARIADB_TAG 4 | environment: 5 | MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD 6 | MYSQL_DATABASE: $DB_NAME 7 | MYSQL_USER: $DB_USER 8 | MYSQL_PASSWORD: $DB_PASSWORD 9 | 10 | php: 11 | image: "wodby/wordpress:6-${PHP_VER}-${WORDPRESS_STABILITY_TAG}" 12 | environment: 13 | DB_HOST: $DB_HOST 14 | DB_NAME: $DB_NAME 15 | DB_USER: $DB_USER 16 | DB_PASSWORD: $DB_PASSWORD 17 | DEBUG: 1 18 | WP_VERSION: 6 19 | PHP_SENDMAIL_PATH: '/bin/true' 20 | BASE_URL: http://$PROJECT_BASE_URL 21 | PHP_FPM_USER: wodby 22 | PHP_FPM_GROUP: wodby 23 | volumes: 24 | - codebase:/var/www/html/ 25 | - ./tests.sh:/usr/local/bin/tests.sh 26 | 27 | nginx: 28 | image: wodby/nginx:$NGINX_TAG 29 | environment: 30 | NGINX_STATIC_OPEN_FILE_CACHE: "off" 31 | NGINX_ERROR_LOG_LEVEL: debug 32 | NGINX_BACKEND_HOST: php 33 | NGINX_VHOST_PRESET: wordpress 34 | volumes: 35 | - codebase:/var/www/html/ 36 | depends_on: 37 | - php 38 | 39 | varnish: 40 | image: wodby/varnish:$VARNISH_TAG 41 | depends_on: 42 | - nginx 43 | environment: 44 | VARNISH_SECRET: secret 45 | VARNISH_BACKEND_HOST: nginx 46 | VARNISH_BACKEND_PORT: 80 47 | VARNISH_CONFIG_PRESET: wordpress 48 | 49 | valkey: 50 | image: wodby/valkey:$VALKEY_TAG 51 | 52 | volumes: 53 | codebase: -------------------------------------------------------------------------------- /tests/run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | if [[ -n "${DEBUG}" ]]; then 6 | set -x 7 | fi 8 | 9 | docker compose up -d 10 | docker compose exec -T mariadb make check-ready max_try=12 wait_seconds=5 delay_seconds=5 -f /usr/local/bin/actions.mk 11 | docker compose exec -T nginx make check-ready max_try=5 wait_seconds=3 -f /usr/local/bin/actions.mk 12 | docker compose exec -T php make check-ready max_try=5 wait_seconds=3 -f /usr/local/bin/actions.mk 13 | docker compose exec -T varnish make check-ready max_try=5 -f /usr/local/bin/actions.mk 14 | docker compose exec -T php tests.sh 15 | docker compose down 16 | -------------------------------------------------------------------------------- /tests/tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | if [[ -n "${DEBUG}" ]]; then 6 | set -x 7 | fi 8 | 9 | WP_DOMAIN="$( echo "${BASE_URL}" | sed 's/https\?:\/\///' )" 10 | 11 | make init -f /usr/local/bin/actions.mk 12 | 13 | wp core install --url="${BASE_URL}" --title="WordPress 6" \ 14 | --admin_user=admin --admin_password=admin --admin_email=admin@example.com 15 | 16 | # TODO: test redis and varnish. 17 | wp plugin install redis-cache --activate 18 | wp plugin install vcaching --activate 19 | 20 | echo -n "Checking WordPress homepage... " 21 | curl -s -H "host: ${WP_DOMAIN}" "nginx" | grep -q "WordPress 6" 22 | echo "OK" 23 | -------------------------------------------------------------------------------- /traefik.yml: -------------------------------------------------------------------------------- 1 | services: 2 | traefik: 3 | image: traefik:v2.0 4 | command: --api.insecure=true --providers.docker 5 | networks: 6 | - project1 7 | - project2 8 | ports: 9 | - '80:80' 10 | - '8080:8080' 11 | volumes: 12 | - /var/run/docker.sock:/var/run/docker.sock 13 | 14 | networks: 15 | project1: 16 | external: true 17 | name: project1-dir_default 18 | project2: 19 | external: true 20 | name: project2-dir_default 21 | --------------------------------------------------------------------------------