本文不介绍 Docker Wordpress 部署过程,也不介绍怎么申请 SSL 证书,只介绍 Docker Wordpress 如何启用 HTTPS。
由于 docker 官方的 wordpress 镜像跑的是 apache2 ,所以我们只需要按照 Apache 配置 SSL 证书的方式引用证书就可以了,不过在此之前需要将 SSL 证书导入到 WordPress 容器内。
大多数启动 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 证书
# 方便容器内绑定证书
进入 wordpress 容器,输入 openssl
,查看是否安装 ssl ,如果出现下面图情况说明已经安装过了
[root@test home]# docker exec -it blog bash
root@d38c40e54806:/var/www/html# openssl
OpenSSL>
# 输入 exit 退出 OpenSSL
输入 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#
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
编辑 /etc/apache2/sites-available/000-default.conf
在
标签中增加下面的配置
RewriteEngine on
RewriteBase /
# FORCE HTTPS
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
效果如下
# 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
RewriteEngine on
RewriteBase /
# FORCE HTTPS
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
# 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
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
修改完之后,重启 wordpress 容器,一切都变成了 https
docker restart wordpress
虽然已经配置 SSL 证书,并且开启了 https 协议,但是站点还是无法用 https 访问的,因为 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 配置可供参考
docker run --name wordpress \
-p 8080:80 \
-p 8443:443 \
-v /home/wordpress:/var/www/html \
-v /etc/letsencrypt:/etc/letsencrypt \
-d wordpress:latest
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://
?