Configure HTTPS for Wordpress on Docker using NGINX as a reverse proxy
Konstantinos Kritikakis
Posted on July 24, 2024
If you want to host Wordpress in a Docker container but have trouble configuring HTTPS, the steps below might help you!
Composing the docker-compose.yml
file
Let's create a docker-compose.yml
file to define the services we are going to need.
First, we are going to add the db
to the services.
db:
image: mysql:5.7
container_name: db
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: notanotheruser
MYSQL_PASSWORD: 1234
MYSQL_ROOT_PASSWORD: root1234
volumes:
- db_data:/var/lib/mysql
- We are exposing the
port 3306
in case we want to connect to the database with MySQL Workbench to take a better look. - We are passing the
environment variables
needed to init the MySQL server as per documentation - We are creating a
volume
to keep the state of the MySQL server even after we shut down the service container.
After we have set up the db, we are going to add wordpress
to the services.
wordpress:
depends_on:
- db
image: wordpress:latest
container_name: wordpress
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: notanotheruser
WORDPRESS_DB_PASSWORD: 1234
WORDPRESS_DB_NAME: wordpress
volumes:
- ./wordpress/wp-config.php:/var/www/html/wp-config.php
- We are adding the
depends_on: db
because we want the db service to be started prior to the wordpress service. - We are passing the
environment variables
needed to init Wordpress as per documentation - We need to overwrite the
wp-config.php
file in the wordpress installation with our own only to add one line that is going to allow us to use https, and that is:$_SERVER['HTTPS'] = 'on';
A wp-config.php
file locally should look like this:
<?php
/**
* The base configuration for WordPress
*
* The wp-config.php creation script uses this file during the installation.
* You don't have to use the website, you can copy this file to "wp-config.php"
* and fill in the values.
*
* This file contains the following configurations:
*
* * Database settings
* * Secret keys
* * Database table prefix
* * ABSPATH
*
* This has been slightly modified (to read environment variables) for use in Docker.
*
* @link https://developer.wordpress.org/advanced-administration/wordpress/wp-config/
*
* @package WordPress
*/
// IMPORTANT: this file needs to stay in-sync with https://github.com/WordPress/WordPress/blob/master/wp-config-sample.php
// (it gets parsed by the upstream wizard in https://github.com/WordPress/WordPress/blob/f27cb65e1ef25d11b535695a660e7282b98eb742/wp-admin/setup-config.php#L356-L392)
// a helper function to lookup "env_FILE", "env", then fallback
if (!function_exists('getenv_docker')) {
// https://github.com/docker-library/wordpress/issues/588 (WP-CLI will load this file 2x)
function getenv_docker($env, $default) {
if ($fileEnv = getenv($env . '_FILE')) {
return rtrim(file_get_contents($fileEnv), "\r\n");
}
else if (($val = getenv($env)) !== false) {
return $val;
}
else {
return $default;
}
}
}
// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', getenv_docker('WORDPRESS_DB_NAME', 'wordpress') );
/** Database username */
define( 'DB_USER', getenv_docker('WORDPRESS_DB_USER', 'example username') );
/** Database password */
define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', 'example password') );
/**
* Docker image fallback values above are sourced from the official WordPress installation wizard:
* https://github.com/WordPress/WordPress/blob/1356f6537220ffdc32b9dad2a6cdbe2d010b7a88/wp-admin/setup-config.php#L224-L238
* (However, using "example username" and "example password" in your database is strongly discouraged. Please use strong, random credentials!)
*/
/** Database hostname */
define( 'DB_HOST', getenv_docker('WORDPRESS_DB_HOST', 'mysql') );
/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', getenv_docker('WORDPRESS_DB_CHARSET', 'utf8') );
/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', getenv_docker('WORDPRESS_DB_COLLATE', '') );
/**#@+
* Authentication unique keys and salts.
*
* Change these to different unique phrases! You can generate these using
* the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}.
*
* You can change these at any point in time to invalidate all existing cookies.
* This will force all users to have to log in again.
*
* @since 2.6.0
*/
define( 'AUTH_KEY', getenv_docker('WORDPRESS_AUTH_KEY', 'a04e06eaef05d9dc187680cdccb8aae37d90bfcd') );
define( 'SECURE_AUTH_KEY', getenv_docker('WORDPRESS_SECURE_AUTH_KEY', 'f1d35321ba3ff820430674efc877f53b64bdb50e') );
define( 'LOGGED_IN_KEY', getenv_docker('WORDPRESS_LOGGED_IN_KEY', '5d880df893cba59fed67def1acac2c61e46c4671') );
define( 'NONCE_KEY', getenv_docker('WORDPRESS_NONCE_KEY', '2fe4fdf4ff93153db924369eb7bbd823f446577c') );
define( 'AUTH_SALT', getenv_docker('WORDPRESS_AUTH_SALT', '326143348bb31e5451cf0e838048043ea39e5351') );
define( 'SECURE_AUTH_SALT', getenv_docker('WORDPRESS_SECURE_AUTH_SALT', '33aa7ae0aa39497d0d13e84413061e0168eadea3') );
define( 'LOGGED_IN_SALT', getenv_docker('WORDPRESS_LOGGED_IN_SALT', 'f032c820677ec84f4ef05a6d2e4c2547be1e7b1b') );
define( 'NONCE_SALT', getenv_docker('WORDPRESS_NONCE_SALT', '506e5adc0340e19f13b1018ecb7b7776e92b0a73') );
// (See also https://wordpress.stackexchange.com/a/152905/199287)
/**#@-*/
/**
* WordPress database table prefix.
*
* You can have multiple installations in one database if you give each
* a unique prefix. Only numbers, letters, and underscores please!
*/
$table_prefix = getenv_docker('WORDPRESS_TABLE_PREFIX', 'wp_');
/**
* For developers: WordPress debugging mode.
*
* Change this to true to enable the display of notices during development.
* It is strongly recommended that plugin and theme developers use WP_DEBUG
* in their development environments.
*
* For information on other constants that can be used for debugging,
* visit the documentation.
*
* @link https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/
*/
define( 'WP_DEBUG', !!getenv_docker('WORDPRESS_DEBUG', '') );
/* Add any custom values between this line and the "stop editing" line. */
// If we're behind a proxy server and using HTTPS, we need to alert WordPress of that fact
// see also https://wordpress.org/support/article/administration-over-ssl/#using-a-reverse-proxy
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) {
$_SERVER['HTTPS'] = 'on';
}
// (we include this by default because reverse proxying is extremely common in container environments)
if ($configExtra = getenv_docker('WORDPRESS_CONFIG_EXTRA', '')) {
eval($configExtra);
}
/* That's all, stop editing! Happy publishing. */
/** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';
$_SERVER['HTTPS'] = 'on';
Keep in mind that the Wordpress image by itself doesn't support HTTPS. Thus the need for a reverse proxy.
Finally we need to add webserver
to the services.
webserver:
depends_on:
- wordpress
image: nginx:latest
container_name: webserver
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- ./nginx/certs:/etc/nginx/certs
- We are adding the
depends_on: wordpress
because we want the wordpress service to be started prior to the webserver service. - We are exposing both
port 80
and443
. - We need to pass a
nginx.conf
file that allows for the reverse proxy to be possible as well as.crt
and.key
files for the SSL.
A nginx.conf
file locally should look like this:
server {
listen 80;
location / {
proxy_pass http://wordpress;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 443 ssl;
ssl_certificate /etc/nginx/certs/nginx.crt;
ssl_certificate_key /etc/nginx/certs/nginx.key;
location / {
proxy_pass http://wordpress;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
In order to serve HTTPS content, an SSL certificate is required.
For development purposes I used this online tool to generate my self-signed certificate (.crt
and .key
files). Feel free to use certbot or openssl
Finally, fingers crossed, we are ready to run docker-compose up
!
After the setup process, if you go to Settings you will see that the https
has been added to the WordPress Address
and the Site Address
That's it!
I had trouble myself to setup https for wordpress so I thought once I figured it out I should share. Feel free to share any feedback! Thanks and have a great day!
Here is the GitHub repo with the code used.
Posted on July 24, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.