What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Run WordPress on one machine with Docker Compose: place WordPress and MariaDB or MySQL in separate services, mount named volumes at /var/www/html and /var/lib/mysql, supply database settings through environment variables or secret files, and start the stack with docker compose up -d. The containers can be replaced; the volumes hold your site.
Antihost offers managed WordPress hosting with free migration, one-click staging and a 14-day free trial.
Move to Kubernetes only when you need cluster scheduling, persistent-volume provisioning, ingress, or horizontal web capacity. A cluster does not automatically make WordPress highly available. You must design storage for uploads, database backup and failover, media delivery, secrets, TLS, and recovery.
As an Amazon Associate I earn from qualifying purchases.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Choose the deployment that matches your problem
Docker Compose is the practical default for local development, testing, a small site, or a single server. It gives you a repeatable two-service application without requiring a control plane. Kubernetes is an orchestration platform for multiple nodes: it can reschedule Pods, expose Services, attach PersistentVolumes, and coordinate ingress and certificates, but each of those capabilities needs an explicit configuration.
| Concern | Docker Compose | Kubernetes |
|---|---|---|
| Operational scope | One Docker host and its local storage | A cluster of nodes with a scheduler and control plane |
| State storage | Named volumes such as wp_data and db_data |
PersistentVolumeClaims backed by a storage class, managed disk, or another provisioner |
| Web exposure | Host port mapping, reverse proxy, or load balancer outside Compose | Service plus Ingress or a cloud load balancer |
| Rescheduling | Containers restart on the same host unless you operate another host yourself | Pods can be restarted or moved; storage must be attachable where the Pod runs |
| Secrets | Compose secrets and secret files, kept out of ordinary configuration | Kubernetes Secrets or an external secret manager |
| Scaling | Manual scaling on the host; shared storage and routing are your responsibility | Deployments, Services, and autoscaling can add web Pods, but database and media architecture still require separate work |
| Recovery | Back up the host volumes and verify a restore | Back up PVC data, database state, cluster configuration, and any external media store |
Use the smallest platform that meets the requirement. A second WordPress container is not a substitute for shared uploads, a consistent database, or a tested failover path.
#1 Best Overall
What must persist when a container disappears
A container’s writable layer is disposable. WordPress needs two different kinds of state:
- Database state: posts, pages, users, settings, comments, plugin data, and metadata in MariaDB or MySQL.
- Filesystem state: the WordPress installation, themes, plugins, and especially uploaded media under
wp-content/uploads.
Mount database storage at /var/lib/mysql and WordPress storage at /var/www/html (or at a deliberately selected subdirectory). If a Pod or container is deleted without those mounts, the application may start as a new installation even though the image is unchanged.
Recommended Free Tools
Prerequisites for a Compose deployment
- Docker Engine with the Compose v2 plugin, so the command is
docker compose. - A directory reserved for this stack and enough disk space for the database, core files, plugins, themes, and uploads.
- A tested image tag policy. Use a specific WordPress and database tag in production rather than silently pulling a moving
latesttag; the example useslatestonly to keep the demonstration independent of a particular release. - A plan for HTTPS and DNS. Compose publishes a port; it does not by itself issue certificates or terminate TLS.
Build a two-service WordPress stack with Docker Compose
1. Create the project and secret files
Create a directory such as wordpress-stack, then create a secrets subdirectory. Put a long, unique database password in secrets/db_password.txt and a different root password in secrets/db_root_password.txt. Restrict those files to the account that runs Docker and keep them out of version control.
The Compose model separates services, networks, volumes, configs, and secrets. The database and WordPress services below share only an internal application network; the database has no published host port.
2. Define the services and named volumes
services:
db:
image: mariadb:latest
restart: unless-stopped
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD_FILE: /run/secrets/db_password
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
volumes:
- db_data:/var/lib/mysql
secrets:
- db_password
- db_root_password
networks:
- backend
wordpress:
image: wordpress:latest
restart: unless-stopped
depends_on:
- db
ports:
- '8080:80'
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_password
volumes:
- wp_data:/var/www/html
secrets:
- db_password
networks:
- backend
volumes:
db_data:
wp_data:
networks:
backend:
driver: bridge
secrets:
db_password:
file: ./secrets/db_password.txt
db_root_password:
file: ./secrets/db_root_password.txt
The official WordPress image supports _FILE variants for sensitive settings. That lets the container read a mounted secret instead of placing a password directly in the Compose file. The same pattern is used for the MariaDB credentials.
3. Validate and start the stack
- From the project directory, run
docker compose config. Fix indentation, missing secret files, or invalid variable expansions before starting. - Start both services in the background with
docker compose up -d. - Check status with
docker compose ps. A healthy result shows both containers running; an initialization delay for the database is normal on the first start. - Inspect startup output with
docker compose logs -f db wordpress. Stop following logs withCtrl-C; that does not stop the containers. - Open
http://localhost:8080and complete the WordPress installer. On a remote host, use its DNS name and put an HTTPS reverse proxy in front of the published port.
depends_on controls startup order, not database readiness. If WordPress starts before MariaDB is accepting connections, the container normally retries or can be restarted; verify the logs rather than assuming that a running process means the application is ready.
Rank #2
4. Stop, remove, and preserve data correctly
Run docker compose down when you want to remove the containers and the default network while retaining the named volumes. The database and WordPress files remain available for the next docker compose up -d.
Do not use docker compose down --volumes unless you intentionally want to erase the named volumes and start over. That command removes the stored database and WordPress data along with the containers. Treat it as a destructive reset, not as ordinary shutdown.
Secure and maintain the Compose installation
Pin images and rebuild regularly
Choose a WordPress tag and database tag that you have tested together, record them in version control, and update them deliberately. Rebuild or pull the images on a schedule so WordPress core, PHP, the database engine, and operating-system packages receive security fixes. Test updates against a copy of the volumes before changing the live stack.
Reduce writable paths when the site is managed centrally
The official image documents a read-only deployment pattern. A hardened service can set read_only: true, provide temporary writable filesystems for /tmp and /run, and mount a persistent volume only where runtime writes are required, commonly wp-content/uploads. This prevents web requests from modifying core files, but it also disables normal dashboard-based plugin, theme, and core updates. Perform those changes by building and deploying a new image, and test the exact image with your plugins before enabling the restriction.
Free tools Windows power users keep installed
One-click scans. No signup required.
wordpress:
read_only: true
tmpfs:
- /tmp
- /run
volumes:
- wp_uploads:/var/www/html/wp-content/uploads
A read-only design is not a drop-in addition to every existing Compose file. Confirm that the image, PHP runtime, cache directories, and plugins do not require another writable path; add only narrowly scoped mounts for paths you have verified.
Back up before changing anything
A volume is persistence, not a backup. Back up the database with a consistent database dump and back up the WordPress files, including uploads and any custom plugins or themes. Store copies outside the Docker host, retain more than one recovery point, and perform a restore into a separate stack. A backup that has never been restored is an assumption, not a recovery plan.
Rank #3
Move the application to Kubernetes
Kubernetes changes the failure model: a Pod can be evicted, restarted, rescheduled to another node, or deleted during an upgrade. A PersistentVolume (PV) represents storage, and a PersistentVolumeClaim (PVC) requests that storage for a workload. Kubernetes documentation describes PVs and PVCs as surviving Pod restart, rescheduling, and deletion, provided the underlying storage and reclaim policy are configured correctly.
Kubernetes’ instructional WordPress/MySQL example is explicitly educational. It warns that the example “is not suitable for production use cases, as it uses single instance WordPress and MySQL Pods.” Treat it as a way to learn object relationships, not as a high-availability design.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteThe minimum Kubernetes object set
- A database workload and a PVC for its data directory.
- A WordPress Deployment and a PVC for the application files, or a read-only image with a separate persistent media mount.
- A ClusterIP Service for database traffic and a Service for WordPress traffic.
- Secrets for database credentials, preferably synchronized from an external secret manager.
- An Ingress and TLS certificate resources when the site must be reachable by a hostname.
Create credentials without putting them in the Deployment
Set shell variables from a protected secret store, then create a Kubernetes Secret. The command below avoids writing literal passwords into a manifest; your shell history and CI logs must still be protected.
kubectl create secret generic wp-db
--from-literal=username=wordpress
--from-literal=password=$WP_DB_PASSWORD
--from-literal=root-password=$MYSQL_ROOT_PASSWORD
Use the same key names in the database and WordPress manifests. In a team or production cluster, use the platform’s approved external-secret workflow so credentials can be rotated without committing them to Git.
Provision claims before deploying workloads
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wordpress-files
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
The capacity values are examples, not sizing guidance. Select a storage class and capacity based on the database, media library, retention policy, and growth rate. A claim can remain Pending when the cluster has no matching provisioner or available volume; inspect it with kubectl describe pvc mysql-data.
Deploy MariaDB and expose it internally
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mariadb:latest
env:
- name: MYSQL_DATABASE
value: wordpress
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: wp-db
key: username
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: wp-db
key: password
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: wp-db
key: root-password
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-data
---
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
The Service name mysql becomes the DNS name used by WordPress. Keep this database Service internal; exposing port 3306 to the internet creates an unnecessary attack surface.
Rank #4
Deploy WordPress and its Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
spec:
replicas: 1
selector:
matchLabels:
app: wordpress
template:
metadata:
labels:
app: wordpress
spec:
containers:
- name: wordpress
image: wordpress:latest
env:
- name: WORDPRESS_DB_HOST
value: mysql:3306
- name: WORDPRESS_DB_NAME
value: wordpress
- name: WORDPRESS_DB_USER
valueFrom:
secretKeyRef:
name: wp-db
key: username
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: wp-db
key: password
ports:
- containerPort: 80
volumeMounts:
- name: wordpress-files
mountPath: /var/www/html
volumes:
- name: wordpress-files
persistentVolumeClaim:
claimName: wordpress-files
---
apiVersion: v1
kind: Service
metadata:
name: wordpress
spec:
selector:
app: wordpress
ports:
- port: 80
targetPort: 80
type: ClusterIP
Apply the manifests with kubectl apply -f and then check kubectl get pods,pvc,svc. If a Pod is Pending, inspect scheduling and storage events with kubectl describe pod. If it is restarting, read kubectl logs and verify the Secret keys, database hostname, and mounted claim.
For a temporary non-production check, use kubectl port-forward service/wordpress 8080:80 and open http://localhost:8080. For a real hostname, keep the Service internal and configure an Ingress controller, DNS, and a certificate issuer.
Storage choices and the node-affinity trap
Cloud or enterprise clusters commonly use a CSI-backed storage class that can attach a disk to the node running a Pod. Confirm its access mode: ReadWriteOnce generally permits one node to mount a volume, while a multi-reader requirement may need an ReadWriteMany filesystem or a different design.
Local volumes are tied to a particular node. Kubernetes requires node affinity so the scheduler places the Pod where that disk exists. Local storage can be useful for learning or a constrained single-node installation, but it does not become portable merely because it is referenced by a PVC. Losing the node can make the workload unavailable until that storage is recovered.
Keep the database’s durable files separate from WordPress uploads. A storage class that is acceptable for media may not provide the latency, durability, snapshots, or locking behavior required by a transactional database.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Why adding WordPress replicas is not high availability
Setting replicas: 2 creates two web Pods, but it does not solve the shared-state problems:
Best Value
- Both Pods must see the same uploads. Otherwise an image written to one Pod can return a 404 when a request reaches the other.
- Both Pods must use one authoritative database, with backups and a failover plan. Running two independent database Pods against separate disks creates divergent sites.
- Plugins that write local caches or generated files need a shared, disposable cache strategy or a configuration that writes to object storage.
- A Service can load-balance requests, but it does not repair inconsistent files or promote a failed database.
A scalable design commonly keeps WordPress core, themes, and plugins in an immutable image, stores media in an object-storage service or a proven shared filesystem, runs the database on a managed or deliberately replicated platform, and adds Redis object caching where the application and plugin stack support it. These are separate architecture decisions, not automatic results of deploying a container.
Autoscale only after the bottleneck is understood
Horizontal Pod Autoscaling can add web capacity from CPU, memory, or application metrics, but it cannot make a single-writer database scale safely. Establish resource requests and limits, measure PHP and database saturation, and confirm that media and sessions behave correctly before enabling autoscaling. A sudden increase in web Pods can otherwise increase database contention without improving response time.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Ingress, TLS, and operational visibility
Expose WordPress through an Ingress or a managed load balancer, redirect HTTP to HTTPS, and renew certificates automatically. Set the external URL consistently so WordPress does not generate mixed-content links after the move. Do not expose the database Service.
Monitor at three layers:
- Cluster: Pod restarts, scheduling failures, node pressure, PVC attachment errors, and available capacity.
- Web runtime: HTTP error rate, latency, PHP worker saturation, and ingress responses.
- Data: database connections, replication or failover health where applicable, disk growth, backup completion, and restore-test results.
Centralize logs and retain enough history to correlate an application error with a Pod replacement, storage event, or database restart. Add readiness and liveness probes only after defining what “ready” means for your image; a probe that checks only that a process exists can send traffic to a site whose database is unavailable.
Upgrade and rollback procedure
- Record the current image digests, manifests, plugin and theme versions, and database backup point.
- Restore a recent backup into an isolated environment and test the candidate WordPress and database images there.
- Build or select the new immutable WordPress image, keeping the old image available for rollback.
- Apply the Deployment change and watch rollout status with
kubectl rollout status deployment/wordpress, or usedocker compose up -dafter changing the pinned tag in Compose. - Check application logs, login, media uploads, scheduled jobs, and critical plugin functions.
- If the new web image is faulty, use
kubectl rollout undo deployment/wordpressor restore the previous Compose tag. Do not roll back a database schema blindly; database migrations may require a tested reverse procedure or restoration from backup.
Failure scenarios and fixes
| Symptom | Likely cause | What to check |
|---|---|---|
| WordPress shows the installation screen after a restart | The database volume was not mounted, was deleted, or the container points at a new database | Inspect volume mounts, docker compose ps or kubectl get pvc, and the database hostname and credentials |
| Uploads disappear when a Pod changes | Uploads were written to a container layer or node-local path | Verify the mount at wp-content/uploads and choose shared or external media storage |
| PVC remains Pending | No compatible storage class, capacity, access mode, or topology is available | Run kubectl describe pvc and inspect storage-provisioner events |
| Pods cannot start on another node | The volume is local or restricted to one attachment | Review PV node affinity and the storage class access mode; plan a portable backend |
| WordPress cannot connect to MySQL | Wrong Service name, Secret key, port, or database initialization state | Read both containers’ logs and test DNS and credentials from inside the WordPress Pod |
| Dashboard updates fail after hardening | The image or filesystem is read-only by design | Publish a new image containing the tested update, or provide only the narrowly required writable mount |
| Two web Pods return different media | Each Pod has private local files | Use object storage or a shared filesystem before increasing replicas |
A practical progression from laptop to cluster
- Development: Use Compose with WordPress, MariaDB or MySQL, named volumes, an internal network, and a local port mapping.
- Hardened image: Pin tested tags, use secret files, minimize writable paths, and rebuild for security updates.
- Initial Kubernetes deployment: Create a WordPress Deployment, a database workload, Services, and PVCs. Keep it single-instance while learning and label it non-production.
- Production cluster: Select portable or managed storage, establish database backup and availability, externalize media when appropriate, add ingress and TLS, instrument the stack, and rehearse recovery.
This progression keeps platform complexity proportional to the requirement. Compose solves packaging and repeatability on one host; Kubernetes solves scheduling and service coordination across nodes, while persistence, database reliability, media delivery, and recovery remain deliberate engineering work.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errors

