Modern SME websites increasingly combine content management, eCommerce, digital marketing, customer engagement, analytics and business integration. Joomla and WordPress remain strong CMS platforms, while WooCommerce provides a mature eCommerce layer for WordPress.
A development team should therefore avoid treating each website as an isolated server installation. A better approach is to establish a repeatable Docker-based development, testing, staging and production methodology.
This paper presents such a methodology.
The proposed platform uses:
- Docker Engine
- Docker Compose
- Joomla
- WordPress
- WooCommerce
- PHP-FPM
- Nginx
- Varnish
- Redis
- MariaDB
- Git
- automated testing
- staging environments
- VPS deployment
- backups and disaster recovery
- security controls
- performance testing
- CI/CD
The architecture separates application, web, caching and database services:
INTERNET │ ▼ HTTPS / NGINX │ ▼ VARNISH │ ▼ NGINX │ ▼ PHP-FPM │ ┌────────────┴────────────┐ │ │ REDIS MARIADB │ │ ▼ ▼ Application Cache Persistent Data │ ▼ ┌──────────────────────────────┐ │ Joomla │ │ WordPress │ │ WordPress + WooCommerce │ └──────────────────────────────┘
The objective is not merely to "put Joomla or WordPress into Docker."
The objective is to create a repeatable DevOps platform capable of moving a project safely through:
Development ↓ Testing ↓ Git ↓ Staging ↓ Acceptance ↓ Production VPS ↓ Monitoring ↓ Backup / Recovery
Technical Research & Implementation White Paper
Docker-Based Web Development and Production Platform for Joomla, WordPress, WooCommerce and SME eCommerce
Version: 1.0
Date: August 2026
Audience: SME Owners, CTOs, IT Managers, Digital Transformation Managers, Web Developers, DevOps Engineers and System Administrators
Executive Summary
Modern SME websites increasingly combine content management, eCommerce, digital marketing, customer engagement, analytics and business integration. Joomla and WordPress remain strong CMS platforms, while WooCommerce provides a mature eCommerce layer for WordPress.
A development team should therefore avoid treating each website as an isolated server installation. A better approach is to establish a repeatable Docker-based development, testing, staging and production methodology.
This paper presents such a methodology.
The proposed platform uses:
- Docker Engine
- Docker Compose
- Joomla
- WordPress
- WooCommerce
- PHP-FPM
- Nginx
- Varnish
- Redis
- MariaDB
- Git
- automated testing
- staging environments
- VPS deployment
- backups and disaster recovery
- security controls
- performance testing
- CI/CD
The architecture separates application, web, caching and database services:
INTERNET │ ▼ HTTPS / NGINX │ ▼ VARNISH │ ▼ NGINX │ ▼ PHP-FPM │ ┌────────────┴────────────┐ │ │ REDIS MARIADB │ │ ▼ ▼ Application Cache Persistent Data │ ▼ ┌──────────────────────────────┐ │ Joomla │ │ WordPress │ │ WordPress + WooCommerce │ └──────────────────────────────┘
The objective is not merely to "put Joomla or WordPress into Docker."
The objective is to create a repeatable DevOps platform capable of moving a project safely through:
Development ↓ Testing ↓ Git ↓ Staging ↓ Acceptance ↓ Production VPS ↓ Monitoring ↓ Backup / Recovery
1. Introduction
SMEs increasingly depend on their websites for:
- lead generation
- product presentation
- eCommerce
- customer communication
- SEO
- marketing
- online ordering
- customer accounts
- payments
- shipping
- digital transformation
A website failure can therefore become a business failure.
Traditional deployments often look like:
Ubuntu ├── Apache/Nginx ├── PHP ├── MariaDB ├── Redis ├── Joomla └── WordPress
This can work, but it becomes difficult to reproduce and maintain.
A Docker-based architecture instead treats each service as an independently managed component.
2. Business Objectives
The platform should provide:
Development
Developers should be able to create an identical environment quickly.
Testing
Changes should be tested before deployment.
Staging
Production-like testing should occur before release.
Production
The VPS should run a controlled, secure environment.
Recovery
A failed VPS should be recoverable from Git and backups.
Scalability
The architecture should be capable of supporting larger sites later.
3. Platform Scope
This paper covers three application categories.
3.1 Joomla
Suitable for:
- corporate websites
- portals
- content-heavy websites
- associations
- government/non-profit sites
- structured content
3.2 WordPress
Suitable for:
- SME websites
- blogs
- marketing websites
- landing pages
- content marketing
- SEO-driven sites
3.3 WooCommerce
Suitable for:
- online stores
- B2C commerce
- B2B commerce
- product catalogs
- subscriptions and extensions
- order management
The same infrastructure methodology can support all three.
4. Reference Architecture
The reference architecture is:
USERS │ ▼ DNS / DOMAIN │ ▼ HTTPS FRONTEND │ ▼ NGINX │ ▼ VARNISH │ ▼ NGINX │ ▼ PHP-FPM │ ┌───────────────┼────────────────┐ │ │ │ ▼ ▼ ▼ JOOMLA WORDPRESS WOOCOMMERCE │ │ │ └───────────────┼────────────────┘ │ APPLICATION LAYER │ ┌───────────┴───────────┐ ▼ ▼ REDIS MARIADB
5. Why Nginx?
Nginx performs several important functions:
- HTTP server
- static file delivery
- reverse proxy
- PHP-FPM communication
- request filtering
- security headers
- upload limits
- connection management
Nginx should not be responsible for application logic.
Its role is:
Request ↓ Nginx ↓ PHP-FPM
6. Why PHP-FPM?
Joomla and WordPress are PHP applications.
PHP-FPM provides a process manager for PHP.
The architecture becomes:
Browser ↓ Nginx ↓ PHP-FPM ↓ CMS
This separates the web server from the PHP execution environment.
7. Why Varnish?
Varnish is an HTTP accelerator.
Without Varnish:
Browser ↓ Nginx ↓ PHP ↓ Database
With Varnish:
Browser ↓ Varnish │ ├── HIT → response │ └── MISS ↓ Nginx ↓ PHP ↓ Database
The objective is to reduce:
- PHP execution
- database queries
- CPU consumption
- response time
8. Why Redis?
Redis provides an in-memory data store.
It can be used for:
- object cache
- application cache
- sessions
- temporary state
The architecture becomes:
Application │ ▼ Redis │ └── Cache hit │ ▼ Response
If data isn't available:
Application ↓ Redis MISS ↓ MariaDB ↓ Application ↓ Redis
9. Why MariaDB?
MariaDB provides persistent relational storage.
It stores:
Joomla
- articles
- users
- configuration
- extensions
- categories
WordPress
- posts
- pages
- users
- metadata
- plugin configuration
WooCommerce
- products
- orders
- customers
- inventory
- settings
- transactional information
The database is therefore a critical production asset.
10. Development Environment
A recommended project structure is:
projects/ │ ├── joomla-docker/ │ ├── wordpress-docker/ │ └── woocommerce-docker/
Each project contains:
compose.yaml compose.prod.yaml .env .env.example docker/ scripts/ tests/ database/
This allows independent lifecycle management.
11. Joomla Docker Environment
11.1 Directory
mkdir -p ~/projects/joomla-docker cd ~/projects/joomla-docker
Create:
mkdir -p \ docker/nginx \ docker/varnish \ docker/php \ scripts \ tests \ database/backups
12. Joomla Environment Variables
.env:
COMPOSE_PROJECT_NAME=joomla JOOMLA_SITE_NAME=Joomla Development JOOMLA_ADMIN_USER=Administrator JOOMLA_ADMIN_USERNAME=admin JOOMLA_ADMIN_PASSWORD=CHANGE_ME JOOMLA_ADMIN_EMAIL=
Never commit production credentials to Git.
13. Joomla Docker Compose
compose.yaml:
services: joomla: image: joomla:6.1.2-php8.4-fpm container_name: joomla-dev restart: unless-stopped environment: JOOMLA_DB_HOST: db JOOMLA_DB_USER: ${DB_USER} JOOMLA_DB_PASSWORD: ${DB_PASSWORD} JOOMLA_DB_NAME: ${DB_NAME} JOOMLA_SITE_NAME: ${JOOMLA_SITE_NAME} JOOMLA_ADMIN_USER: ${JOOMLA_ADMIN_USER} JOOMLA_ADMIN_USERNAME: ${JOOMLA_ADMIN_USERNAME} JOOMLA_ADMIN_PASSWORD: ${JOOMLA_ADMIN_PASSWORD} JOOMLA_ADMIN_EMAIL: ${JOOMLA_ADMIN_EMAIL} volumes: - joomla_data:/var/www/html depends_on: db: condition: service_healthy redis: condition: service_healthy networks: - backend nginx: image: nginx:1.29-alpine container_name: joomla-nginx-dev restart: unless-stopped volumes: - joomla_data:/var/www/html:ro - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - joomla networks: - frontend - backend varnish: image: varnish:7.7-alpine container_name: joomla-varnish-dev restart: unless-stopped volumes: - ./docker/varnish/default.vcl:/etc/varnish/default.vcl:ro command: - varnishd - -F - -f - /etc/varnish/default.vcl - -s - malloc,256m ports: - "8080:80" depends_on: - nginx networks: - frontend redis: image: redis:7-alpine container_name: joomla-redis-dev restart: unless-stopped command: - redis-server - --appendonly - "yes" volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 networks: - backend db: image: mariadb:11.4 container_name: joomla-db-dev restart: unless-stopped environment: MARIADB_DATABASE: ${DB_NAME} MARIADB_USER: ${DB_USER} MARIADB_PASSWORD: ${DB_PASSWORD} MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} volumes: - db_data:/var/lib/mysql healthcheck: test: [ "CMD", "healthcheck.sh", "--connect", "--innodb_initialized" ] interval: 10s timeout: 5s retries: 10 networks: - backend phpmyadmin: image: phpmyadmin:latest container_name: joomla-phpmyadmin-dev restart: unless-stopped environment: PMA_HOST: db PMA_PORT: 3306 ports: - "8081:80" depends_on: db: condition: service_healthy networks: - frontend - backend volumes: joomla_data: db_data: redis_data: networks: frontend: driver: bridge backend: driver: bridge internal: true
14. Joomla Nginx
server { listen 80; server_name _; root /var/www/html; index index.php index.html; client_max_body_size 64M; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { try_files $uri =404; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param HTTP_PROXY ""; fastcgi_pass joomla:9000; } location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|webp)$ { expires 30d; add_header Cache-Control "public"; access_log off; } location ~ /\. { deny all; } }
15. Joomla Varnish
vcl 4.1; backend default { .host = "nginx"; .port = "80"; } sub vcl_recv { if (req.url ~ "^/administrator") { return (pass); } if (req.request != "GET" && req.request != "HEAD") { return (pass); } if (req.http.Cookie ~ "joomla_user_state") { return (pass); } if (req.http.Cookie ~ "joomla_remember_me") { return (pass); } if (req.http.Authorization) { return (pass); } return (hash); } sub vcl_backend_response { if (beresp.status >= 400) { set beresp.ttl = 0s; set beresp.uncacheable = true; return (deliver); } set beresp.ttl = 5m; set beresp.grace = 30m; return (deliver); } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; } else { set resp.http.X-Cache = "MISS"; } }
16. WordPress Docker Environment
Create:
mkdir -p ~/projects/wordpress-docker cd ~/projects/wordpress-docker
Create the same basic structure:
wordpress-docker/ ├── compose.yaml ├── compose.prod.yaml ├── .env ├── docker/ ├── scripts/ ├── tests/ └── database/
17. WordPress Environment
COMPOSE_PROJECT_NAME=wordpress WORDPRESS_DB_NAME=wordpress WORDPRESS_DB_USER=wordpress WORDPRESS_DB_PASSWORD=CHANGE_ME WORDPRESS_DB_ROOT_PASSWORD=CHANGE_ME WORDPRESS_TABLE_PREFIX=wp_ WORDPRESS_DEBUG=true TZ=America/Winnipeg
18. WordPress Compose
services: wordpress: image: wordpress:php8.4-fpm restart: unless-stopped environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: ${WORDPRESS_DB_USER} WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD} WORDPRESS_DB_NAME: ${WORDPRESS_DB_NAME} WORDPRESS_TABLE_PREFIX: ${WORDPRESS_TABLE_PREFIX} WORDPRESS_DEBUG: ${WORDPRESS_DEBUG} volumes: - wordpress_data:/var/www/html depends_on: db: condition: service_healthy redis: condition: service_healthy networks: - backend nginx: image: nginx:1.29-alpine restart: unless-stopped volumes: - wordpress_data:/var/www/html:ro - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - wordpress networks: - frontend - backend varnish: image: varnish:7.7-alpine restart: unless-stopped volumes: - ./docker/varnish/default.vcl:/etc/varnish/default.vcl:ro command: - varnishd - -F - -f - /etc/varnish/default.vcl - -s - malloc,256m ports: - "8080:80" depends_on: - nginx networks: - frontend redis: image: redis:7-alpine restart: unless-stopped command: - redis-server - --appendonly - "yes" volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 networks: - backend db: image: mariadb:11.4 restart: unless-stopped environment: MARIADB_DATABASE: ${WORDPRESS_DB_NAME} MARIADB_USER: ${WORDPRESS_DB_USER} MARIADB_PASSWORD: ${WORDPRESS_DB_PASSWORD} MARIADB_ROOT_PASSWORD: ${WORDPRESS_DB_ROOT_PASSWORD} volumes: - db_data:/var/lib/mysql healthcheck: test: [ "CMD", "healthcheck.sh", "--connect", "--innodb_initialized" ] interval: 10s timeout: 5s retries: 10 networks: - backend volumes: wordpress_data: db_data: redis_data: networks: frontend: driver: bridge backend: driver: bridge internal: true
19. WordPress Nginx
server { listen 80; server_name _; root /var/www/html; index index.php index.html; client_max_body_size 128M; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { try_files $uri =404; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param HTTP_PROXY ""; fastcgi_pass wordpress:9000; } location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|webp)$ { expires 30d; add_header Cache-Control "public"; access_log off; } location ~ /\. { deny all; } }
20. WooCommerce
WooCommerce runs as a WordPress plugin.
Therefore:
WordPress │ └── WooCommerce │ ├── Products ├── Cart ├── Checkout ├── Customers ├── Orders ├── Payments └── Shipping
The development environment must therefore test WordPress and WooCommerce separately.
21. WooCommerce Varnish
This is one of the most important additions.
Never blindly cache:
/cart /checkout /my-account wp-admin wp-login.php
Also bypass:
wc-ajax
and relevant WooCommerce cookies.
Example:
sub vcl_recv { if (req.url ~ "^/wp-admin") { return (pass); } if (req.url ~ "^/wp-login.php") { return (pass); } if (req.url ~ "^/wp-cron.php") { return (pass); } if (req.url ~ "^/cart") { return (pass); } if (req.url ~ "^/checkout") { return (pass); } if (req.url ~ "^/my-account") { return (pass); } if (req.url ~ "wc-ajax") { return (pass); } if (req.request != "GET" && req.request != "HEAD") { return (pass); } if (req.http.Cookie ~ "wordpress_logged_in") { return (pass); } if (req.http.Cookie ~ "woocommerce_items_in_cart") { return (pass); } if (req.http.Cookie ~ "woocommerce_cart_hash") { return (pass); } if (req.http.Cookie ~ "wp_woocommerce_session") { return (pass); } return (hash); }
This configuration must be tested against the actual WooCommerce theme, extensions and payment/shipping plugins used by the site.
22. Redis Architecture for WooCommerce
Use Redis for object/application caching.
WooCommerce │ ▼ Redis │ ├── Cached objects ├── Frequently used data └── Application cache │ ▼ MariaDB
Varnish performs a different job:
Varnish ↓ HTTP response caching
Therefore:
Browser ↓ Varnish ↓ WordPress ↓ Redis ↓ MariaDB
23. WordPress Development Method
Use:
Git │ ├── main │ ├── develop │ └── feature/*
Example:
git checkout develop git checkout -b feature/woocommerce-product-template
Test locally.
Then:
git add . git commit -m "Add WooCommerce product template" git push origin feature/woocommerce-product-template
24. WordPress Theme Development
Do not modify a third-party theme directly.
Use:
Child Theme
or develop a custom theme.
Example:
wp-content/ └── themes/ └── keen-theme/ ├── style.css ├── functions.php ├── templates/ ├── assets/ └── inc/
25. WooCommerce Development Areas
Test:
Catalog
Products Categories Attributes Variations Images Pricing Inventory Coupons
Customers
Registration Login Account Addresses Password reset
Commerce
Cart Checkout Payment Order Refund Email
Operations
Shipping Tax Inventory Order status Customer notification
26. Payment Testing
Use payment-provider sandbox/test environments during development.
Test:
Successful transaction Failed transaction Cancelled transaction Refund Webhook Duplicate webhook Timeout Order status Email notification
Never use live payment credentials during ordinary development.
27. Shipping Testing
Test:
Canada USA International
and:
Free shipping Flat rate Local pickup Weight-based shipping Threshold-based shipping
28. Common Development Test Suite
For Joomla:
[ ] Homepage [ ] Administrator [ ] Login [ ] SEO URLs [ ] Forms [ ] Extensions [ ] Template [ ] Redis [ ] Database [ ] Varnish
For WordPress:
[ ] Homepage [ ] wp-admin [ ] Login [ ] Search [ ] Forms [ ] Theme [ ] Plugins [ ] Redis [ ] Database [ ] Varnish
For WooCommerce:
[ ] Product [ ] Category [ ] Variation [ ] Cart [ ] Checkout [ ] Coupon [ ] Shipping [ ] Tax [ ] Payment sandbox [ ] Order [ ] Refund [ ] Email
29. Common Testing Script
Create:
nano scripts/test.sh #!/usr/bin/env bash set -e echo "====================================" echo " Docker CMS Test Suite" echo "====================================" echo echo "Container status" docker compose ps echo echo "HTTP test" curl \ --fail \ --silent \ --show-error \ http://localhost:8080/ \ > /dev/null echo "HTTP: PASS" echo echo "Redis test" RESULT=$(docker compose exec -T redis redis-cli ping) if [ "$RESULT" = "PONG" ]; then echo "Redis: PASS" else echo "Redis: FAIL" exit 1 fi echo echo "Database test" docker compose exec -T db \ mariadb \ -u"${DB_USER:-${WORDPRESS_DB_USER}}" \ -p"${DB_PASSWORD:-${WORDPRESS_DB_PASSWORD}}" \ "${DB_NAME:-${WORDPRESS_DB_NAME}}" \ -e "SELECT 1;" \ > /dev/null echo "Database: PASS" echo echo "====================================" echo " TESTS PASSED" echo "===================================="
30. Development → Staging → Production
The recommended deployment lifecycle is:
Git Repository │ ▼ DEVELOPMENT │ ▼ Automated Tests │ ▼ STAGING │ ▼ Acceptance Testing │ ▼ PRODUCTION │ ▼ VPS
Never make significant changes directly on production.
31. VPS Production Architecture
Production should expose only:
80/tcp 443/tcp
and SSH should preferably be restricted to trusted administrative access.
Never expose:
3306 6379 9000 phpMyAdmin
publicly.
32. Production Directory
Use:
/opt/sites/ │ ├── client-a-joomla/ │ ├── client-b-wordpress/ │ ├── client-c-woocommerce/ └── client-d-magento/
Each site gets:
Docker Compose Database Redis Volumes Environment Backups Logs
This provides isolation between clients.
33. Production Deployment
On the VPS:
cd /opt/sites/client-c-woocommerce
Pull the latest approved version:
git pull origin main
Then:
docker compose \ -f compose.yaml \ -f compose.prod.yaml \ pull
Start:
docker compose \ -f compose.yaml \ -f compose.prod.yaml \ up -d
Verify:
docker compose ps
34. Production Security
Implement:
SSH keys UFW Fail2ban HTTPS Security headers Strong passwords Secret management Regular updates Image pinning Backups Monitoring
Disable:
Joomla debug WordPress debug PHP display_errors Public phpMyAdmin Public Redis Public MariaDB
35. Backup Strategy
Use the 3-2-1 approach:
3 copies 2 storage types 1 off-site
For a WooCommerce site, backups are particularly important because orders and customer data represent business records.
Backup:
Database Uploaded media Themes Custom plugins/extensions Configuration Deployment configuration
Do not rely on the database alone.
36. Database Backup
For Joomla:
docker compose exec -T db \ mariadb-dump \ -ujoomla \ -p"${DB_PASSWORD}" \ joomla \ | gzip > database/backups/joomla.sql.gz
For WordPress:
docker compose exec -T db \ mariadb-dump \ -u"${WORDPRESS_DB_USER}" \ -p"${WORDPRESS_DB_PASSWORD}" \ "${WORDPRESS_DB_NAME}" \ | gzip > database/backups/wordpress.sql.gz
37. Disaster Recovery
The recovery process should be:
New VPS ↓ Docker ↓ Git repository ↓ Environment configuration ↓ Application volumes ↓ Database backup ↓ Restore ↓ Start containers ↓ DNS ↓ HTTPS ↓ Testing
The ultimate goal is:
A new production server can be reconstructed without depending on undocumented manual configuration.
38. Performance Engineering
Performance should be measured rather than assumed.
Test:
Page response time Time to first byte Requests/second Varnish HIT ratio PHP response time Database queries Redis hit ratio CPU RAM Disk I/O
Tools include:
curl ApacheBench wrk k6 Browser developer tools Docker stats
Example:
wrk -t4 -c20 -d30s https://example.com/
39. Cache Architecture
The complete cache model is:
Browser │ ▼ Browser Cache │ ▼ Varnish │ ▼ Nginx │ ▼ PHP-FPM │ ▼ Redis │ ▼ MariaDB
Each layer has a different purpose.
|
Layer |
Purpose |
|---|---|
|
Browser |
Static assets |
|
Varnish |
Public HTTP responses |
|
Redis |
Application/object cache |
|
MariaDB |
Persistent data |
40. Critical WooCommerce Cache Rule
WooCommerce introduces a major architectural distinction.
Public product content can often be cached.
But:
Cart Checkout My Account Customer-specific data Payment Order status AJAX
must be treated as dynamic.
Therefore:
Product page ↓ Potentially CACHE Cart ↓ PASS Checkout ↓ PASS My Account ↓ PASS
This distinction should be part of every WooCommerce deployment checklist.
41. CI/CD
A mature platform should eventually implement:
Git Push │ ▼ CI │ ├── YAML validation ├── PHP checks ├── Security scan ├── Docker validation ├── Application tests └── Smoke tests │ ▼ Build │ ▼ Staging │ ▼ Acceptance │ ▼ Production
Production should deploy only from an approved branch or release.
42. Recommended Git Strategy
main │ ├── release/* │ └── develop │ ├── feature/joomla-template ├── feature/wp-theme ├── feature/woocommerce ├── feature/payment ├── feature/shipping └── feature/seo
43. Joomla Development Lifecycle
Requirement ↓ Architecture ↓ Docker Development ↓ Template / Extension ↓ Functional Test ↓ Performance Test ↓ Security Test ↓ Staging ↓ Acceptance ↓ Production
44. WordPress Development Lifecycle
Requirement ↓ Theme/Plugin Design ↓ Docker Development ↓ WordPress Test ↓ Plugin Compatibility ↓ Performance ↓ Security ↓ Staging ↓ Production
45. WooCommerce Development Lifecycle
Product Model ↓ Catalog ↓ Cart ↓ Checkout ↓ Payment Sandbox ↓ Shipping ↓ Tax ↓ Order ↓ Email ↓ Refund ↓ Performance ↓ Security ↓ Staging ↓ Production
46. Production Deployment Checklist
[ ] Git release approved [ ] Database backup completed [ ] Files backed up [ ] Staging tests passed [ ] Payment sandbox tests passed [ ] WooCommerce tests passed [ ] Varnish rules tested [ ] Redis tested [ ] Database tested [ ] HTTPS tested [ ] Firewall checked [ ] Production credentials verified [ ] Debug disabled [ ] Deployment completed [ ] Homepage tested [ ] Admin tested [ ] Checkout tested [ ] Order tested [ ] Email tested [ ] Monitoring enabled
47. Troubleshooting Methodology
Do not restart every container immediately.
Trace the request.
Browser ↓ DNS ↓ HTTPS ↓ Varnish ↓ Nginx ↓ PHP-FPM ↓ Application ↓ Redis ↓ MariaDB
Test each layer independently.
Docker
docker compose ps
Logs
docker compose logs --tail=100
Redis
docker compose exec redis redis-cli ping
Database
docker compose exec db \ mariadb \ -uUSER \ -pPASSWORD \ DATABASE \ -e "SELECT 1;"
HTTP
curl -I http://localhost:8080
Varnish
curl -I http://localhost:8080/
48. Recommended Multi-Platform Standard
For an SME-focused IT company, the infrastructure can become a standardized service:
SME WEB PLATFORM │ ┌────────────────┼─────────────────┐ │ │ │ Joomla WordPress Magento │ │ │ │ WooCommerce │ │ │ │ └────────────────┼─────────────────┘ │ Docker / VPS │ ┌──────────────┼───────────────┐ │ │ │ Nginx Varnish Redis │ │ └──────────────┬───────────────┘ │ MariaDB
This is particularly useful for a managed SME service provider because the operational knowledge becomes reusable across clients.
49. Platform Standardization
The following should be standardized across projects:
Infrastructure
Docker Docker Compose Nginx Redis MariaDB Git
Development
Feature branches Environment variables Automated testing Local Docker Code review
Deployment
Staging Production Rollback Backups Monitoring
Security
Firewall HTTPS Secrets Least privilege Updates Backups
Platform-specific items remain separate:
Joomla extensions Joomla caching WordPress plugins WooCommerce sessions Magento cache Magento indexing
50. Recommended Directory Model for a VPS
/opt/sites/ │ ├── joomla-company-a/ │ ├── compose.yaml │ ├── compose.prod.yaml │ ├── .env │ └── docker/ │ ├── wordpress-company-b/ │ ├── compose.yaml │ ├── compose.prod.yaml │ ├── .env │ └── docker/ │ ├── woocommerce-company-c/ │ ├── compose.yaml │ ├── compose.prod.yaml │ ├── .env │ └── docker/ │ └── monitoring/
Each customer environment remains isolated.
51. Strategic Value for an SME
The Docker approach provides more than technical convenience.
It creates a repeatable business process:
Standard Architecture ↓ Lower Development Risk ↓ Faster Deployment ↓ Repeatable Testing ↓ Predictable Maintenance ↓ Better Security ↓ Better Disaster Recovery ↓ Scalable SME IT Service
Instead of selling only:
"We build websites."
the organization can offer:
Managed, containerized, tested and monitored digital commerce platforms.
52. Recommended Technology Roadmap
Phase 1 — Development
Docker Joomla WordPress WooCommerce Nginx Redis MariaDB Varnish Git
Phase 2 — Testing
Automated smoke tests Performance testing Security testing Backup/restore testing
Phase 3 — Staging
Production-like VPS HTTPS Monitoring Realistic data Payment sandbox
Phase 4 — Production
HTTPS Firewall Backups Monitoring Varnish Redis Database
Phase 5 — DevOps
GitHub Actions CI/CD Automated deployments Security scanning Automated backups Rollback
Phase 6 — Advanced Platform
Central monitoring Prometheus Grafana Log aggregation Container registry Infrastructure as Code Automated VPS provisioning
53. Final Reference Architecture
The completed SME platform can be represented as:
CLIENT │ ▼ DNS │ ▼ ┌──────────────┐ │ HTTPS / TLS │ └──────┬───────┘ │ ▼ ┌───────┐ │ NGINX │ └───┬───┘ │ ▼ ┌─────────┐ │ VARNISH │ └────┬────┘ │ ▼ ┌───────┐ │ NGINX │ └───┬───┘ │ ▼ PHP-FPM │ ┌───────────────┼────────────────┐ │ │ │ ▼ ▼ ▼ JOOMLA WORDPRESS WOOCOMMERCE │ │ │ └───────────────┼────────────────┘ │ ┌──────┴──────┐ ▼ ▼ REDIS MARIADB │ │ └──────┬──────┘ ▼ APPLICATION
54. Conclusion
A professional Joomla, WordPress and WooCommerce environment should be designed as a software delivery platform, not simply as a collection of installed packages.
Docker Compose provides the foundation for reproducibility.
Nginx provides the web-serving and PHP-FPM integration layer.
Varnish provides public HTTP caching.
Redis provides application/object caching.
MariaDB provides persistent relational storage.
Git provides version control.
Staging provides a controlled pre-production environment.
Automated testing provides release confidence.
Backups and disaster recovery protect business data.
A VPS provides a cost-effective production platform for many SME workloads.
The most important architectural principle is separation:
Development ≠ Staging ≠ Production
and:
Public HTTP Cache ≠ Application Cache ≠ Persistent Database
For Joomla:
Varnish → public Joomla content Redis → application/object cache MariaDB → Joomla data
For WordPress:
Varnish → public WordPress pages Redis → object/application cache MariaDB → WordPress data
For WooCommerce:
Varnish → safe anonymous public pages Redis → object/application cache MariaDB → products/orders/customers
while:
Cart Checkout My Account Payment Order processing AJAX Customer-specific information
remain dynamic and must bypass inappropriate HTTP caching.
The resulting methodology provides a foundation for a professional SME web and eCommerce DevOps service, where Joomla, WordPress/WooCommerce and future platforms such as Magento/Hyvä can be developed locally, tested systematically, promoted to staging and deployed reproducibly to VPS infrastructure.
For an organization such as KeenComputer, this approach can become a standardized delivery framework for SME digital transformation: website development + eCommerce + DevOps + performance + security + backup + managed VPS operations, rather than treating each customer website as an individually configured server.