
Want a fast, secure, and cheap way to run your own WordPress site? This Docker Compose WordPress setup on a VPS shows you how to build one in under an hour. You will learn each step in plain English. No big words. No confusing jargon. Just clear commands you can follow one by one.
Quick Overview – What You’ll Build With This Docker Compose WordPress Setup
By the end of this guide, you will have a live WordPress site. It will run on a VPS with three containers working together. The setup is fast, safe, and ready for real users.
Architecture Diagram (WordPress + MySQL + Nginx)
Here is a simple view of how the parts fit:
| Layer | Role | Port |
|---|---|---|
| User Browser | Visits your domain | 443/80 |
| Nginx Container | Handles traffic and SSL | 80 / 443 |
| WordPress Container | Runs the site logic | 9000 (internal) |
| MySQL Container | Stores posts and users | 3306 (internal) |
| Docker Volume | Keeps your files safe | — |
Estimated Completion Time
A first-time user can finish in 45 to 60 minutes. If you have used Linux a bit, it may take only 20 minutes.
What Makes This Guide Different in 2026
Most tutorials show a toy setup. This Docker Compose WordPress setup on a VPS uses current best practices for 2026. We use the docker compose plugin, strong passwords, non-root users, and Let’s Encrypt SSL. You get a real site, not a demo.
Prerequisites for Docker Compose WordPress Setup on a VPS
Before you type any commands, check this list. You need a few things in place. None of them are hard or expensive to get.
VPS & System Requirements
- One Ubuntu 24.04 LTS VPS with at least 2 GB RAM and 2 CPU cores.
- At least 30 GB of disk space. SSD is best.
- Root access (or a user with sudo rights).
- A public IPv4 address.
Domain Registration & DNS Preparation
Buy a domain from any registrar. Then add an A record in your DNS panel. Point the A record to your VPS IP. Wait up to 15 minutes for it to go live. Test it with the command ping yourdomain.com.
Required Tools (Terminal, SSH Client)
- On Windows: use PuTTY or the Windows Terminal. PowerShell also works.
- On Mac or Linux: open the built-in Terminal app.
- A text editor on the VPS, like nano or vim.
Step 1: Prepare Your VPS for a Secure WordPress Deployment
A raw VPS is not safe. Bad bots scan the internet all day. Before we run this Docker Compose WordPress setup, we must lock the door first.
Secure SSH Access (Key-Based Authentication)
On your local machine, create a key pair:
ssh-keygen -t ed25519 -C “your_email@example.com”
Copy the public key to the VPS:
ssh-copy-id user@your_vps_ip
Then edit /etc/ssh/sshd_config on the VPS. Change these lines:
PasswordAuthentication no
PermitRootLogin no
Save the file and restart SSH with sudo systemctl restart sshd.
Configure Firewall With UFW
Run these commands to turn on the firewall:
sudo ufw allow OpenSSH
sudo ufw allow ‘Nginx Full’
sudo ufw enable
sudo ufw status
Only port 22, 80, and 443 will stay open.
Create a Non-Root User for Docker Operations
Routine work should never run as root. Make a new user:
sudo adduser wpadmin
sudo usermod -aG sudo wpadmin
Later, we will add this user to the docker group too.
Step 2: Install Docker and Docker Compose Plugin on VPS
The next part of our Docker Compose WordPress setup is to install the engine itself. We will use the official Docker repo, not the old Ubuntu packages.
Remove Legacy Docker Versions
Old Docker builds can clash. Remove them first:
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
Add Docker’s Official GPG Key and Repository
Run these commands in order:
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
Then add the repo source:
echo “deb [arch=$(dpkg –print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo “$VERSION_CODENAME”) stable” | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Install Docker CE and docker-compose-plugin
Now install the engine and the compose plugin:
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Verify Docker Compose Installation
Check that both pieces work:
docker –version
docker compose version
You should see Docker version 27.x or newer, and the compose plugin version 2.x.
Let your wpadmin user run docker without sudo:
sudo usermod -aG docker wpadmin
newgrp docker
Step 3: Build the Docker Compose WordPress Project Structure
Now we build the core of this Docker Compose WordPress setup: the folder tree, credentials file, and the compose stack file.
Create Project Directories
Run these commands to make a clean tree:
mkdir -p ~/wordpress-site/nginx
mkdir -p ~/wordpress-site/letsencrypt
cd ~/wordpress-site
Generate a Secure .env File for Credentials
The .env file holds your secrets. Never commit it to Git. Generate random passwords with:
openssl rand -base64 18
Create .env using nano:
nano .env
Fill it with these keys:
MYSQL_ROOT_PASSWORD=your_long_root_pass
MYSQL_DATABASE=wordpress
MYSQL_USER=wpuser
MYSQL_PASSWORD=your_user_pass
WORDPRESS_DB_HOST=db:3306
Write the Production-Ready docker-compose.yml
Create the main file with nano docker-compose.yml and add:
| services: |
| db: |
| image: mysql:8.4 |
| restart: unless-stopped |
| env_file: .env |
| volumes: [db_data:/var/lib/mysql] |
| networks: [wp-net] |
| wordpress: |
| image: wordpress:6.7-php8.3-fpm |
| restart: unless-stopped |
| env_file: .env |
| depends_on: [db] |
| volumes: [wp_data:/var/www/html] |
| networks: [wp-net] |
| nginx: |
| image: nginx:1.27-alpine |
| restart: unless-stopped |
| ports: [“80:80″,”443:443”] |
| volumes: [./nginx:/etc/nginx/conf.d,./letsencrypt:/etc/letsencrypt,wp_data:/var/www/html] |
| depends_on: [wordpress] |
| networks: [wp-net] |
| volumes: |
| db_data: |
| wp_data: |
| networks: |
| wp-net: |
Understand Containers, Networks, and Volumes
- Containers are isolated apps. Each one has a single job.
- Networks let the containers talk to each other but hide them from the open internet.
- Volumes store your database and files on the host, so they survive a container restart.
Step 4: Configure Nginx Reverse Proxy for WordPress Containers
The WordPress image we picked uses PHP-FPM. Nginx sits in front of it to serve the site. This is how a modern Docker Compose WordPress setup on a VPS should look.
Create the Nginx Configuration File
Make the file ~/wordpress-site/nginx/wordpress.conf. Paste this content:
| server { |
| listen 80; |
| server_name yourdomain.com www.yourdomain.com; |
| root /var/www/html; |
| index index.php index.html; |
| client_max_body_size 32M; |
| location / { |
| try_files $uri $uri/ /index.php?$args; |
| } |
| location ~ \.php$ { |
| fastcgi_pass wordpress:9000; |
| fastcgi_index index.php; |
| fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; |
| include fastcgi_params; |
| } |
| } |
Enable HTTP/2 and Gzip Compression
Inside the same file, add near the top (before server):
gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;
You will turn on HTTP/2 in Step 6 after SSL is in place.
Activate Site and Reload Nginx
After we start the stack, Nginx will read this file on its own. No extra symlink is needed because we mounted the whole folder inside the container.
Step 5: Launch All Containers and Complete WordPress Setup
Everything is in place. Now let’s run this Docker Compose WordPress setup and see it come to life.
Run docker compose up -d
Make sure you are inside the project folder and run:
cd ~/wordpress-site
docker compose up -d
Docker will pull the images. This can take a few minutes the first time.
Verify Container Health and Status
Check that all three containers are up:
docker compose ps
You should see wordpress-site-nginx-1, wordpress-site-wordpress-1, and wordpress-site-db-1, all marked Up.
Run the WordPress Installation Wizard
Open your browser and go to http://yourdomain.com. You will see the WordPress setup screen. Pick a language, set a site title, choose an admin username, and create a strong password. Click Install WordPress. You are now live.
Step 6: Secure Your WordPress VPS With Free SSL/TLS
A site without HTTPS is unsafe. This Docker Compose WordPress setup on a VPS uses a free Let’s Encrypt cert to lock the traffic.
Obtain a Let’s Encrypt Certificate via Certbot
On the host, install certbot:
sudo apt-get install -y certbot
Then get the cert with the webroot method:
sudo certbot certonly –webroot -w /var/www/html -d yourdomain.com -d www.yourdomain.com –email you@yourdomain.com –agree-tos –non-interactive
If certbot can’t find the webroot, stop the nginx container briefly, run certbot with –standalone, then start it again.
Configure Nginx for HTTPS
Replace the contents of wordpress.conf with:
| server { |
| listen 80; |
| server_name yourdomain.com www.yourdomain.com; |
| return 301 https://$host$request_uri; |
| } |
| server { |
| listen 443 ssl http2; |
| server_name yourdomain.com www.yourdomain.com; |
| ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; |
| ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; |
| root /var/www/html; |
| index index.php; |
| client_max_body_size 32M; |
| location / { try_files $uri $uri/ /index.php?$args; } |
| location ~ \.php$ { fastcgi_pass wordpress:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } |
| } |
Reload nginx with docker compose exec nginx nginx -s reload.
Set Up Automatic Certificate Renewal
Certs last 90 days. Add a cron job to renew them:
sudo crontab -e
Add this line at the bottom:
15 3 * * * certbot renew –quiet && docker compose -f /home/wpadmin/wordpress-site/docker-compose.yml exec nginx nginx -s reload
Step 7: Maintain Your Docker Compose WordPress Setup Long-Term
A live site needs care. These three habits keep your Docker Compose WordPress setup on a VPS healthy for years.
Automate Database and File Backups
Create a small script called /home/wpadmin/backup.sh:
TIMESTAMP=$(date +%F-%H%M)
mkdir -p /home/wpadmin/backups
docker exec wordpress-site-db-1 mysqldump -u wpuser -p”$MYSQL_PASSWORD” wordpress > /home/wpadmin/backups/db-$TIMESTAMP.sql
docker run –rm -v wordpress-site_wp_data:/data -v /home/wpadmin/backups:/backup alpine tar czf /backup/files-$TIMESTAMP.tgz -C /data .
Add a weekly cron entry: 0 2 * * 0 /home/wpadmin/backup.sh
Safely Update WordPress and Container Images
Run this when a new image ships:
docker compose pull
docker compose up -d –remove-orphans
docker image prune -f
Always back up first. Never skip that step.
Monitor Container Logs and System Health
To watch live logs, use:
docker compose logs -f wordpress
For a quick health check, run docker compose ps. For deeper data, run docker stats to see CPU and memory use. Tools like Uptime Kuma can ping your site and alert you if it goes down.
Troubleshooting Common Docker Compose WordPress Issues on VPS
Sometimes things break. Here are the most common issues with a Docker Compose WordPress setup on a VPS and how to fix them.
Port Already in Use Errors
If Nginx on the host is already using port 80 or 443, Docker will complain. Run sudo ss -tulpn | grep :80 to find the process. Stop it with sudo systemctl stop nginx, then remove it from autostart using sudo systemctl disable nginx.
Database Connection Failures
If WordPress shows “Error establishing a database connection”, check the .env file. The MYSQL_USER, MYSQL_PASSWORD, and MYSQL_DATABASE values must match what WordPress expects. Also verify WORDPRESS_DB_HOST is db:3306, not localhost.
Permission Denied on WordPress Files
Plugins that write files (like cache plugins) may fail. Fix the permissions by running:
docker exec wordpress-site-wordpress-1 chown -R www-data:www-data /var/www/html/wp-content
Containers Failing to Start
If a container exits, look at its log with docker compose logs db. Common causes are low memory, a bad .env file, or an old image that conflicts with your volume. In the worst case, stop the stack with docker compose down, delete the bad volume with docker volume rm, and start fresh.
FAQ: Docker Compose WordPress Setup on a VPS
Is Docker Compose suitable for WordPress production?
Yes. Many small to medium sites run just fine with this Docker Compose WordPress setup on a VPS. It is easy to back up, move, and scale up. For huge sites, you may later move to Kubernetes or a managed platform.
How do I backup a WordPress site running in Docker?
Back up two things: the database (docker exec the mysql container and run mysqldump) and the volume (tar the wp_data volume). Automate both with a cron job, as shown in Step 7.
Can I run multiple WordPress sites with one Docker Compose setup?
Yes. Copy the project folder, give each stack a different project name with docker compose -p, and make Nginx listen on different host ports or use separate domains via server blocks.
What’s the difference between docker-compose and docker compose in 2026?
docker-compose was a separate Python program. It is now old. docker compose (with a space) is the modern Go plugin, faster and part of the Docker CLI. Always use the new version.
Final Checklist: Production-Ready Docker Compose WordPress Setup
Before you tell the world about your new site, run through this list:
- VPS is on Ubuntu 24.04 and fully updated.
- SSH uses key-based login. Passwords are off.
- UFW allows only 22, 80, and 443.
- A non-root user wpadmin owns the project.
- The .env file holds strong, random passwords.
- docker compose ps shows all three containers Up.
- HTTPS works and the cert is valid.
- Automatic backups run and store data off-site.
- You can read live logs with docker compose logs.
- A renewal cron job keeps the SSL cert fresh.
You have now built a fast, safe, and cheap WordPress site from scratch. The Docker Compose WordPress setup on a VPS you built today will grow with you. Share it, test it, add a cache plugin, and enjoy the freedom of owning your own stack.
