本文不介紹 Docker Wordpress 部署過程,也不介紹怎么申請 SSL 證書,只介紹 Docker Wordpress 如何啟用 HTTPS。
由於 docker 官方的 wordpress 鏡像跑的是 apache2 ,所以我們只需要按照 Apache 配置 SSL 證書的方式引用證書就可以了,不過在此之前需要將 SSL 證書導入到 WordPress 容器內。
重新啟動 wordpress 容器,追加443端口映射
大多數啟動 wordpress 容器只映射了80端口,開啟 https,需要追加 443 端口映射,否則還怎么玩,同時也要把申請的 SSL 證書拷貝到容器內,或者將證書掛載到容器內。
# 舉個例子
docker run --name wordpress \
-p 80:80 \
-p 443:443 \
--link mysql:mysql \
-v /home/blog/wordpress:/var/www/html \
-v /etc/letsencrypt:/etc/letsencrypt \
-d wordpress:latest
# 這里我為什么要掛載`/etc/letsencrypt`路徑呢?
# 因為我申請的是 Let’s Encrypt SSL 證書
# 方便容器內綁定證書
加載 OpenSSL 模塊
進入 wordpress 容器,輸入 openssl ,查看是否安裝 ssl ,如果出現下面圖情況說明已經安裝過了
[root@test home]# docker exec -it blog bash
root@d38c40e54806:/var/www/html# openssl
OpenSSL>
# 輸入 exit 退出 OpenSSL
加載 Apache SSL 模塊
輸入 a2enmod ssl,第一次加載,會提示重啟 Apache,簡單粗暴直接重啟 wordpress 容器
root@d38c40e54806:/var/www/html# a2enmod ssl
Considering dependency setenvif for ssl:
Module setenvif already enabled
Considering dependency mime for ssl:
Module mime already enabled
Considering dependency socache_shmcb for ssl:
Enabling module socache_shmcb.
Enabling module ssl.
See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates.
To activate the new configuration, you need to run:
service apache2 restart
root@d38c40e54806:/var/www/html#
修改 SSL 配置文件,綁定證書及打開 443 端口
Apache 加載 SSL 模塊后,會在 /etc/apache2/sites-available 下生成 default-ssl.conf 文件,編輯該文件
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
上述兩行配置就是證書的存放位置,我們只需要把第三方第三方可信CA簽發的證書相應的文件進行替換
從 apache 的配置文件 apache2.conf 可以看到,apache 只會讀取 /etc/apache2/sites-enabled 目錄的配置文件,所以需要把 /etc/apache2/sites-available 下的 default-ssl.conf 文件鏈接到 /etc/apache2/sites-enabled 目錄下。
ln -s /etc/apache2/sites-available/default-ssl.conf \
/etc/apache2/sites-enabled/default-ssl.conf
http 請求強制跳轉到 https
編輯 /etc/apache2/sites-available/000-default.conf
在 <VirtualHost *:80> </VirtualHost> 標簽中增加下面的配置
<Directory "/var/www/html">
RewriteEngine on
RewriteBase /
# FORCE HTTPS
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
</Directory>
效果如下
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
<Directory "/var/www/html">
RewriteEngine on
RewriteBase /
# FORCE HTTPS
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
</Directory>
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
</VirtualHost>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
修改完之后,重啟 wordpress 容器,一切都變成了 https
docker restart wordpress
收尾
雖然已經配置 SSL 證書,並且開啟了 https 協議,但是站點還是無法用 https 訪問的,因為 wordpress 還需要修改配置,及數據庫路徑地址修改。
修改 wordpress 訪問地址
注意:一定要保證 https 和 http 兩種方式都能正常訪問網站,才能改這個配置,否則可能導致網站無法訪問。
直接登陸后台,通過 “設置” → \rightarrow→ “常規” 里面把 WordPress 地址(URL)、站點地址(URL) 兩個地址的 http 修改為 https 並保存。
修改數據庫的絕對路徑地址
同時為了保證 WordPress 站點之前添加的各個鏈接或者多媒體文件把 http 協議改成 https 協議,我們還需要通過數據庫 SQL 查詢執行一條替換命令。
# 將 `example.com` 換成自己的域名
update wp_posts set post_content = replace(post_content, 'http://example.com','https://example.com');
Over!
后記
通常我們不會只在服務器上裝一個應用/容器,一般的解決方案都是裝一個 nginx (占用 80、443 端口),將請求轉發到各個服務。
如果你像我一樣,wordpress 容器非 80 、443端口,那么下面一段 nginx 配置可供參考
運行 wordpress 容器
docker run --name wordpress \
-p 8080:80 \
-p 8443:443 \
-v /home/wordpress:/var/www/html \
-v /etc/letsencrypt:/etc/letsencrypt \
-d wordpress:latest
nginx 配置
upstream wordpress {
server localhost:8443;
}
server {
listen 80;
server_name www.example.com;
# 跳轉到 https 站點
rewrite ^(.*)$ https://$host$request_uri;
}
## Normal HTTP host
server {
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem; # 證書文件路徑
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem; # 證書文件路徑
server_name www.example.com; ## 修改成自己的域名
# 配置服務器可使用的加密算法
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4:!DH:!DHE;
# 指定服務器密碼算法在優先於客戶端密碼算法時,使用 SSLv3 和 TLS 協議
ssl_prefer_server_ciphers on;
# ssl 版本 可用 SSLv2,SSLv3,TLSv1,TLSv1.1,TLSv1.2
# ie6 只支持 SSLv2,SSLv3 但是存在安全問題, 故不支持
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
## See app/controllers/application_controller.rb for headers set
## Individual nginx logs for this GitLab vhost
access_log /var/log/nginx/access.log; # 根據實際情況修改
error_log /var/log/nginx/error.log; # 根據實際情況修改
location / {
proxy_redirect off; # 禁止跳轉
proxy_set_header Host $host; # 域名轉發
proxy_set_header X-Real-IP $remote_addr; # IP轉發
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://wordpress;
}
}
問題
Bad Request
Your browser sent a request that this server could not understand.
Reason: You're speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please.
這是由於使用 http 協議去訪問一個 https 的端口造成的,如果使用 nginx,那么請認真檢查一下 proxy_pass http:// or proxy_pass https:// ?
