Docker 安装 Wordpress 并开启 HTTPS,还有ng存在的情况

原文地址

本文不介绍 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:// ?

posted @ 2020-11-24 16:59  镇魂帆-张  阅读(959)  评论(0编辑  收藏  举报