diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2eea525 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env \ No newline at end of file diff --git a/Dockerfile.wordpress_fpm b/Dockerfile.wordpress_fpm new file mode 100644 index 0000000..0ca708c --- /dev/null +++ b/Dockerfile.wordpress_fpm @@ -0,0 +1,10 @@ +# Wordpress - make a copy of wp-includes to compare with existing volumes + +# 'docker-compose exec wordpress bash -c 'cd /var/www/html/wp-includes && grep wp_version version.php' +FROM wordpress:6-fpm + +# ancient debian +#RUN apt update && apt -y install vim less + +# Using cp rather than mv so the image can easily be rebuilt +RUN cp -a /usr/src/wordpress/wp-content /var/www/html/wp-content-new diff --git a/README.md b/README.md index 1235a47..a5853fa 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,105 @@ -# WordPress +# ComposePress -A Docker-based toolkit that streamlines WordPress upgrades using official images. Provides pre-configured docker-compose files, Dockerfiles, and standardized procedures to make WordPress maintenance more predictable and reliable. \ No newline at end of file +A Docker-based toolkit that streamlines WordPress upgrades using official images. Provides pre-configured docker-compose files, Dockerfiles, and standardized procedures to make WordPress maintenance more predictable and reliable. + +## Project Configuration + +### Project Name +This project requires a project name, which should be defined in an `.env` file: +```bash +COMPOSE_PROJECT_NAME=test +``` + +### Database Host Configuration +To avoid conflicts, use the following format for the database host: +```bash +WORDPRESS_DB_HOST=${COMPOSE_PROJECT_NAME}-database-1:3306 +``` + +## Environment Variables + +### Docker Images +```bash +# Web and Database Images +IMAGE_WEB=test_web_staging +IMAGE_DATABASE=mariadb:11.5 +``` + +### Let's Encrypt Configuration +```bash +VIRTUAL_HOST=test.test.org +LETSENCRYPT_HOST=test.test.org +LETSENCRYPT_EMAIL=test@test.com +LETSENCRYPT_TEST=true +``` + +### Database Configuration +```bash +WORDPRESS_DB_HOST=${COMPOSE_PROJECT_NAME}-database-1:3306 +WORDPRESS_DB_PASSWORD=wordpress +MYSQL_ROOT_PASSWORD=wordpress +MYSQL_DATABASE=wordpress +MYSQL_USER=wordpress +MYSQL_PASSWORD=wordpress +``` + +### Volume Configuration +```bash +# External Volumes +DB_VOLUME=test_db_staging +CONTENT_VOLUME=test_content_staging + +# Recreated Volumes +HTML_VOLUME=test_html_staging +``` + +## Usage + +### Upgrade Process + +1. Stop the current containers and remove volumes: +```bash +docker compose down -v +``` + +2. Update WordPress version: + - Modify version in `Dockerfile.wordpress_fpm` + - Update `IMAGE_WEB` in `.env` file + +3. Build and test the new environment: +```bash +# Build initial configuration +docker compose -f docker-compose.first.yml build + +# Test the build +docker compose -f docker-compose.first.yml up -d + +# Stop test environment +docker compose -f docker-compose.first.yml down + +# Start production environment +docker compose up -d +``` + +4. Migrate content: +```bash +# In the wordpress service, copy new content to production +cp -a wp-content-new/* wp-content/ + +# Verify permissions on wp-content directory +chmod -R [appropriate-permissions] wp-content/ +``` + +5. Optional: Update database if needed: +```bash +./update-db +``` + +## Requirements +Docker + +## Contributing +@bike + +## License +[GNU GENERAL PUBLIC LICENSE](LICENSE) diff --git a/default.conf b/default.conf new file mode 100644 index 0000000..f2e5e90 --- /dev/null +++ b/default.conf @@ -0,0 +1,44 @@ +# https://www.nginx.com/resources/wiki/start/topics/recipes/mediawiki/ +# https://www.nginx.com/resources/wiki/start/topics/recipes/wordpress/ + +server { + + listen 80; + listen [::]:80; + server_name wordpress; + root /var/www/html; + index index.php; + + #access_log /var/log/nginx/host.access.log main; + + location / { + try_files $uri $uri/ /index.php?$args; + } + + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + + + # pass the PHP scripts to FastCGI server listening on wordpress2:9000 + # + location ~ \.php$ { + #fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass wordpress:9000; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + # fastcgi_param PHP_VALUE "upload_max_filesize=8M"; + fastcgi_param PHP_VALUE "upload_max_filesize=8M; post_max_size=128M; memory_limit=256M"; + } + + # location ~* \.(jpg|jpeg|gif|png|css|js|ico)$ { + # expires max; + # log_not_found off; + # } + +} diff --git a/docker-compose.first.yml b/docker-compose.first.yml new file mode 100644 index 0000000..a3deec5 --- /dev/null +++ b/docker-compose.first.yml @@ -0,0 +1,36 @@ +# The purpose of this docker compose is just to setup a new /var/www/html volume +# from a new version of wordpress, after 'down -v' + +services: + + wordpress: + build: + context: . + dockerfile: Dockerfile.wordpress_fpm + image: ${IMAGE_WEB:-web} + volumes: + - html:/var/www/html + environment: + - WORDPRESS_DB_HOST=${WORDPRESS_DB_HOST:-database:3306} + - WORDPRESS_DB_PASSWORD=${WORDPRESS_DB_PASSWORD:-fake} + - VIRTUAL_HOST=${VIRTUAL_HOST:-wordpress} + - LETSENCRYPT_HOST=${LETSENCRYPT_HOST:-wordpress} + - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL:-me} + - LETSENCRYPT_TEST=${LETSENCRYPT_TEST:-true} + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + restart: always + networks: + - letsencrypt + - default + +volumes: + html: + name: ${HTML_VOLUME:-html} + +networks: + letsencrypt: + external: true \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7e271f0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,103 @@ +# Buildkit to simplify the whole process of upgrading Wordpress with official images +# +# This version is designed for fpm, using a default.conf which references the wordpress service +# +# STEPS: + +# Set COMPOSE_PROJECT_NAME in .env +# docker compose down -v +# Change wordpress version as required in Dockerfile.wordpress_fpm and .env (IMAGE_FIRST) +# docker compose -f docker-compose.first.yml build +# docker compose -f docker-compose.first.yml up -d +# docker compose -f docker-compose.first.yml down +# docker compose up -d +# at this point manually copy everything from wp-content-new to wp-content: cp -a wp-content-new/* wp-content/ +# +# MAKE SURE PERMISSIONS ARE CORRECT in wp-content +# (if you need to) ./update-db + +services: + + database: + image: ${IMAGE_DATABASE:-database} + volumes: + - db:/var/lib/mysql + environment: + - MYSQL_DATABASE=${MYSQL_DATABASE:-wordpress} + - MYSQL_USER=${MYSQL_USER:-wordpress} + - MYSQL_PASSWORD=${MYSQL_PASSWORD:-fake} + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-fake} + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + restart: always + networks: + - letsencrypt + + wordpress: + # build: + # context: . + # dockerfile: Dockerfile.wordpress_fpm + image: ${IMAGE_WEB:-wordpress} + volumes: + - html:/var/www/html + - content:/var/www/html/wp-content + - ./wp-config.php:/var/www/html/wp-config.php + environment: + - WORDPRESS_DB_HOST=${WORDPRESS_DB_HOST:-database:3306} + - WORDPRESS_DB_PASSWORD=${WORDPRESS_DB_PASSWORD:-fake} + - VIRTUAL_HOST=${VIRTUAL_HOST:-wordpress} + - LETSENCRYPT_HOST=${LETSENCRYPT_HOST:-wordpress} + - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL:-me} + - LETSENCRYPT_TEST=${LETSENCRYPT_TEST:-true} + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + restart: always + command: > + bash -c "chown -R www-data:www-data /var/www/html/wp-content && php-fpm" + networks: + - letsencrypt + - default + + # nginx:latest and/or can be customized + web: + # build: + # context: . + # dockerfile: Dockerfile.nginx + image: nginx:latest + restart: always + volumes: + - html:/var/www/html/ + - content:/var/www/html/wp-content + - ./default.conf:/etc/nginx/conf.d/default.conf + - ./nginx.conf:/etc/nginx/nginx.conf + environment: + - VIRTUAL_HOST=${VIRTUAL_HOST:-wordpress} + - LETSENCRYPT_HOST=${LETSENCRYPT_HOST:-wordpress} + - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL:-me} + - LETSENCRYPT_TEST=${LETSENCRYPT_TEST:-true} + networks: + - letsencrypt + - default + +# No variable substition for volumes in this version +volumes: + db: + external: true + name: ${DB_VOLUME:-db} + html: + name: ${HTML_VOLUME:-html} + content: + external: true + name: ${CONTENT_VOLUME:-content} + +networks: + letsencrypt: + external: true + # default: + # name: ${COMPOSE_PROJECT_NAME}_default \ No newline at end of file diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..c8b2d0a --- /dev/null +++ b/nginx.conf @@ -0,0 +1,38 @@ + +user nginx; +worker_processes auto; + +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + client_max_body_size 100M; + client_body_buffer_size 100M; + proxy_buffer_size 128k; + proxy_buffers 4 256k; + proxy_busy_buffers_size 256k; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + include /etc/nginx/conf.d/*.conf; +} diff --git a/update-db b/update-db new file mode 100755 index 0000000..ac56d0c --- /dev/null +++ b/update-db @@ -0,0 +1,14 @@ +#!/bin/bash + +source ".env" + +website="https://$VIRTUAL_HOST" +command="docker-compose exec database mysql" + +echo $website + +$command -u $MYSQL_USER $MYSQL_DATABASE -p"$WORDPRESS_DB_PASSWORD" -e "UPDATE cf_options SET option_value='$website' WHERE option_name='home';" +$command -u $MYSQL_USER $MYSQL_DATABASE -p"$WORDPRESS_DB_PASSWORD" -e "UPDATE cf_options SET option_value='$website' WHERE option_name='siteurl';" + +## Add +# /usr/bin/find /var/www/html/wp-content/uploads/ -type d -exec chmod 755 {} \; -o -type f -exec chmod 644 {} \; \ No newline at end of file diff --git a/wp-config.php b/wp-config.php new file mode 100644 index 0000000..08def2d --- /dev/null +++ b/wp-config.php @@ -0,0 +1,95 @@ +D;E$}Z%PQ*S^N@UZj}02GT.ce^%MLLB#4})%P(gVKYG(J5MKl[![Y;nN^%0'); +define('SECURE_AUTH_KEY', '+-9zk5?X=JazoN|.SfnyDuq*eEha?baAO:,B!XIf+WlhEXbK%30wg/fZ>J;/%n|B'); +define('LOGGED_IN_KEY', '{#lT+Rq-zLKA?H#_Xu+az9Ae,/rOL {jT%l.o.&CY%IRB+,Jidi?M.@d`f`8NpPE'); +define('NONCE_KEY', 'uw!r}Koniy9yV}&.w#HT@(L/Wf<6mcFK[OM,Jsot.B`~%T~ShmEai#my/7_Yr}s&'); +define('AUTH_SALT', '?0(Sm)EJr6J~) $$DJ$-:jo4S}U2s@-(Rg9jROYS?/e8p1e?:t7vAH99uS)jffX~+3?v+?d+_&!J|9~8oH6wopu_5 1iW{l_XUt'); +define('LOGGED_IN_SALT', '.Hca|;r-C8c[<]Y@28KX*6&gBT=s:I:1|6Y -DNQ*SD)R-`~8