Hosting Secure Cloud WordPress with Caddy & Docker

Hosting Secure Cloud WordPress with Caddy & Docker

Some notes from implementing Wordpress with Caddy and Docker


There are a few prerequisites before Caddy will be able to negotiate a certificate from Let's Encrypt:

  1. Valid domain name that you own
  2. DNS configured to point your domain to your server
  3. DNS propagated

For more information on how to set up Caddy you can refer to the Caddy documentation or my articles on the subject SSL reverse proxy with Caddy, Docker and Let's Encrypt, Caddy Won't Generate a Certificate/Doesn't Load

Step 1, Docker & Wordpress

There are plenty of instructional articles on how to get WordPress set up with Docker. Take your pick here and run with it. The one I used is from Jack Wallen at Tech Republic:

For posterity, I've included the main bash script below. The script pulls the latest container templates for MariaDB and Wordpress. It builds some directories, then creates the containers using the templates and directories.

sudo docker pull mariadb
sudo mkdir /opt/wordpress
​sudo mkdir -p /opt/wordpress/database
​sudo mkdir -p /opt/wordpress/html
docker run -e MYSQL_ROOT_PASSWORD=XXX -e MYSQL_USER=wpuser -e MYSQL_PASSWORD=XXX -e MYSQL_DATABASE=wordpress_db -v /opt/wordpress/database:/var/lib/mysql --name wordpressdb -d mariadb
docker pull wordpress:latest
docker run -e WORDPRESS_DB_USER=wpuser -e WORDPRESS_DB_PASSWORD=XXX -e WORDPRESS_DB_NAME=wordpress_db -p 8081:80 -v /opt/wordpress/html:/var/www/html --link wordpressdb:mysql --name wpcontainer -d wordpress

Grab the WordPress container IP address and save it for later. You can get this with docker inspect wpcontainer

Step 2 - WordPress Initial Setup

If you've followed the prerequisites and the script/blog you should now be able to see your WordPress site in action by visiting From here you'll need to walk through the initial configuration wizard for WordPress. The wizard will ask you for a logon username and password, and also credentials to connect to your Database. Once the wizard is complete you can log into WordPress and start publishing content.

Step 3, Caddy

Next to configure Caddy as a reverse proxy so WordPress is served over SSL. Caddy will need its own set of folders for hosting content.

mkdir ~/docker/caddy/.caddyCerts  # SSL Certificates
mkdir ~/docker/caddy/config       # Caddy Config File storage
mkdir ~/docker/caddy/logs         # Web Server logs
mkdir ~/docker/caddy/srv          # Area to host files for site (optional - good for debugging)
touch ~/docker/caddy/config/Caddyfile  #Stub for the Caddy config file

Update the Caddy file to proxy your WordPress site:

<your domain> {
 proxy / <IP Address of WordPress Container>:80 {
 log /logs/access.log {
  rotate_size 1       # Rotate after 2 MB
  rotate_age  14      # Keep log files for 14 days
  rotate_keep 10      # Keep at most 10 log files

And then build the Caddy container:

sudo docker run -d -v /your/path/to/srv:/srv -v /your/path/to/Caddyfile:/etc/Caddyfile -v /your/path/to/.caddyCerts:/etc/caddycerts -v /your/path/to/logs:/logs --volumes-from wpcontainer -p 80:80 -p 443:443 --name caddydocker abiosoft/caddy

Step 4, WordPress Configuration

Caddy should be set up now and routing traffic from :443 to your WordPress container. WordPress now needs to be set up to accept and route traffic on :443 to take advantage of the Caddy reverse proxy.

Access the WordPress dashboard by visiting (this is a direct connection to the WordPress container) and logging in. Navigate to Settings > General. The WordPress Address and Site Address fields need to be changed from their default (with :8081) to using HTTPS:

HTTP (default) HTTP Default

HTTPS UpdateHTTPS update

If everything is configured correctly, clicking save will make your WordPress container available via the Caddy reverse proxy (and unavailable otherwise).

Gotchas, Takeaways


Lots of things can go wrong with this configuration. The beauty of Docker is when something goes wrong it is very easy and fast to delete the container and try again. Take advantage of this!

Modify the URL fields directly in the database

If you're like me and you manage to mess up the URL settings you will quickly find that WordPress is no longer accessible by any URL. Fortunately, you can modify the WordPress config by directly updating the backend database

mysql -u wpuser -h IP_ADDRESS_OF_DB_CONTAINER -p
connect wordpress_db
select * from wp_options where option_name = 'home' #Check to see what the setting is currently
UPDATE wp_options SET option_value = replace(option_value, '', '') WHERE option_name = 'home' OR option_name = 'siteurl';

Thanks to WP Beaches for the assist on this

A Note on Optimization

This method of hosting WordPress is likely not the most memory/CPU efficient since both the WordPress and Caddy containers will be hosting web servers.


Use your cloud host to firewall any port to your server other than SSH (22), HTTP (80) and HTTPS (443). This is also a good opportunity to rebuild your WordPress container without surfacing the 8081 port (stop/remove the container and rebuild it without the -p flag. You will not lose progress so far since the config database is stored outside of the container(s))


You should now have a functional WordPress site secured with HTTPS using the Let's Encrypt authority. If you run into any issues or have questions or comments on the blog please feel free to reach out over email or in the comments below.

Title Image: Wordpress by Cristian Labarca / CC BY-NC 2.0