Set up docker Wordpress behind docker NGINX with SSL

Little short story
I launched my first EC2 instance about 3 years ago. All was runnig well until i had only PHP sites so every applications with the same environment needed. Later i started developing applications with heterogeneous environments, like Python, Go or simply Wordpress blogs.
And so? Docker was the way!
Intro
The intent of this post is to show how to set up an SSL secure Wordpress site using Docker.
I suppose that you have docker-compose installed in your server and bought a domain name that i will call yourdomain.com
.
Wordpress Container
WORKSPACE/mywordpresssite/docker-compose.yml
version: '3' | |
services: | |
wp: | |
image: wordpress | |
ports: | |
- 9009:80 | |
volumes: | |
- ./config/php.conf.uploads.ini:/usr/local/etc/php/conf.d/uploads.ini | |
- ./wp-app:/var/www/html # Full wordpress project | |
#- ./plugin-name/trunk/:/var/www/html/wp-content/plugins/plugin-name # Plugin development | |
#- ./theme-name/trunk/:/var/www/html/wp-content/themes/theme-name # Theme development | |
environment: | |
WORDPRESS_DB_HOST: [DBHOST]:[DBPORT] | |
WORDPRESS_DB_NAME: [DBNAME] | |
WORDPRESS_DB_USER: [DBUSER] | |
WORDPRESS_DB_PASSWORD: [DBPASSWORD] |
WORKSPACE/mywordpresssite/config/php.conf.uploads.ini
file_uploads = On | |
max_execution_time = 600 | |
memory_limit = 512M | |
post_max_size = 32M | |
upload_max_filesize = 32M |
Correctly enable SSL
On the top of your WORKSPACE/mywordpresssite/wp-app/wp-config.php
add these lines:
/** | |
* For WordPress, force the protocol scheme to be HTTPS | |
* when is_ssl() doesn't work, e.g. on a reverse proxied server | |
* where _SERVER['HTTPS'] and _SERVER['SERVER_PORT'] don't | |
* indicate that SSL is being used. | |
*/if ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') | |
$_SERVER['HTTPS'] = '1'; | |
if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { | |
$_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST']; | |
} |
(it avoids the redirects loop once the NGINX reverse proxy container is up)
Generate free SSL cert
Go to https://www.sslforfree.com/ and type your domain name. After that, you have to decide how to verifiy your domain (i generally do the manual verification).
Unzip the downloaded folder and upload ca_bundle.crt , certificate.crt and the private.key inside WORKSPACE/nginx/keys/yourdomain.com/
folder.
NGINX Container
WORKSPACE/nginx/docker-compose.yml
version: '3' | |
services: | |
nginx: | |
image: nginx:latest | |
container_name: nginx | |
volumes: | |
- ./nginx.conf:/etc/nginx/nginx.conf | |
#- ./.htpasswd:/etc/nginx/.htpasswd | |
- ./certs:/etc/nginx/certs | |
ports: | |
- 80:80 | |
- 443:443 |
WORKSPACE/nginx/docker-compose.yml
worker_processes 2; | |
pid /var/run/nginx.pid; | |
worker_rlimit_nofile 65535; | |
# [ debug | info | notice | warn | error | crit ] | |
error_log /var/log/nginx.error_log info; | |
events { | |
worker_connections 2000; | |
# use [ kqueue | epoll | /dev/poll | select | poll ]; | |
# use kqueue; | |
} | |
http { | |
include mime.types; | |
default_type application/octet-stream; | |
log_format main '$remote_addr - $remote_user [$time_local] ' | |
'"$request" $status $bytes_sent ' | |
'"$http_referer" "$http_user_agent" ' | |
'"$gzip_ratio"'; | |
log_format download '$remote_addr - $remote_user [$time_local] ' | |
'"$request" $status $bytes_sent ' | |
'"$http_referer" "$http_user_agent" ' | |
'"$http_range" "$sent_http_content_range"'; | |
client_header_timeout 3m; | |
client_body_timeout 3m; | |
send_timeout 3m; | |
client_header_buffer_size 1k; | |
large_client_header_buffers 4 4k; | |
gzip on; | |
gzip_min_length 1100; | |
gzip_buffers 4 8k; | |
gzip_types text/plain; | |
output_buffers 1 32k; | |
postpone_output 1460; | |
sendfile on; | |
tcp_nopush on; | |
tcp_nodelay on; | |
send_lowat 12000; | |
keepalive_timeout 75 20; | |
#lingering_time 30; | |
#lingering_timeout 10; | |
#reset_timedout_connection on; | |
server { | |
listen 80; | |
listen 443 ssl; | |
ssl_certificate /etc/nginx/certs/yourdomain.com/certificate.crt; | |
ssl_certificate_key /etc/nginx/certs/yourdomain.com/private.key; | |
server_name www.yourdomain.com yourdomain.com; | |
client_max_body_size 500M ; | |
location / { | |
proxy_pass http://[YOURSERVERIP]:9009; | |
proxy_redirect off; | |
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-Host $server_name; | |
#proxy_set_header X-Forwarded-Proto https; | |
#proxy_http_version 1.1; | |
#proxy_set_header Upgrade $http_upgrade; | |
#proxy_set_header Connection "upgrade"; | |
#proxy_read_timeout 86400; | |
} | |
} |
Finally
We have only the last 2 things to do:
- Update record A on your domain DNS zone in order to point to your server IP.
- [Only if you are running on an Amazon EC2 istance] Add the 9009 port on Outgoing tab of the EC2 security group. Grant this port access only to your ec2 IPs.