0、概述
使用Docker容器化部署应用就不多说了吧,这是低运维成本和高效率的完美选择。按照docker的设计思路,应尽量将每个服务放至独立的docker容器中,如此即便相互之间会有依赖关系,但运行时不会相互影响导致整个容器挂掉。所以对于一些复杂应用可能需要多个容器共同完成,这里我们可以使用docker-compose来协助编排、管理、运行一组容器。
简单的说,docker-compose是一个用来把 docker命令自动化的部署命令,通过编写docker-compose.yml脚本,docker-compose会读取此脚本中的配置,将其转换为对应的docker命令逐条执行,最终完成所有部署。
基于docker部署WordPress需要用到3个容器:1、用于接收HTTP/HTTPS请求的Nginx;2、数据库服务mysql或者MariaDB;3、php运行环境。由于我在外层有单独的nginx服务统一用于流量转发和代理,所以本次就不编排单独的nginx容器了,直接通过外部nginx转发到php运行容器暴露的端口即可。
但是遇到了一个WordPress N年来跟nginx兼容性不好的坑:外层HTTPS链接经过nginx解析后反向代理到WordPress服务,此时WordPress会出现 ERR_TOO_MANY_REDIRECTS 无限重定向报错。

网上太多数的解决方案是屏蔽掉WordPress本身的template_redirect、redirect_canonical,但是如果这样可能会导致主题的css样式无法加载。不能从根本上解决问题。
经过搜索分析,其实真正的原因是,nginx将https请求解析后,用http反向代理到的apache php-fpm,但是因为WordPress配置了强制开启https,但此时反代过来的链接是http,所有才想客户端发出了302重定向到https,而客户端已经是https了再访问一遍也会出现同样情况,从而导致无限循环的重定向。那么我们只需要告诉后面的apache和WordPress已经启用了https即可。
在nginx中设置http头部 X-Forwarded-Proto
,这个头部的作用是用于识别协议(HTTP 或 HTTPS),主要针对内部访问重定向时的协议。因此,只要在反向代理时添加以下配置就好了:
proxy_set_header X-Forwarded-Proto $scheme;
$scheme
是nginx的内部变量,表明当前访问的协议,当前如果是https,那么转发到后台服务的时候就是https。这样问题就解决了。
1、安装
安装docker
sudo yum repolist # 检查是否有 extras repo
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine # 卸载旧版本 docker(如果有)
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
sudo yum update
sudo yum install docker-ce docker-ce-cli containerd.io -y
# 启动 docker
sudo systemctl start docker
sudo systemctl enable docker
安装docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# 检查 docker-compose 是否已经安装成功
docker-compose version
2、配置docker-compose
新建docker-compose.yml文件,填入以下内容(记得修改数据库名称用户和密码,以及创建 ./db 和 ./html 两个目录):
version: '3.3'
services:
db:
image: mariadb:latest
volumes:
- ./db:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: dbROOTpassword
MYSQL_DATABASE: dbname
MYSQL_USER: dbname
MYSQL_PASSWORD: dbpassword
wordpress:
depends_on:
- db
image: wordpress:latest
volumes:
- ./html:/var/www/html
ports:
- "8080:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: dbuser
WORDPRESS_DB_PASSWORD: dbpassword
WORDPRESS_DB_NAME: dbname
WORDPRESS_TABLE_PREFIX: dbprefix
yml配置的大致含义是:使用了wordpress:latest 容器和 mariadb:latest容器,直接最新版就可以了,然后把它分别命名为wordpress db。同时他们分别将./html和./db目录映射到容器内的存储,这样就能解决数据持久化的问题了。wordpress容器使用了db容器的3306端口,同时把外部8080端口转发到wordpress容器的80。这样我们只需要访问8080端口,就能访问容器里的wordpress了。
运行 docker-compose up -d
启动,等待镜像下载完成就可以了。
停止命令对应的是: docker-compose down
3、配置反向代理
在 nginx 配置文件目录 /etc/nginx/conf.d
下新增一个 www.conf
文件,写入以下内容:
# 80 redirect
server {
listen 80;
listen [::]:80;
server_name your.domain.name;
root /var/www/html_nocontent;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
# 301 redirect to https
rewrite ^(.*)$ https://$host$1 permanent;
}
}
# 443 wiki proxy
server {
listen 443;
server_name your.domain.name;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
root /var/www/html_nocontent;
ssl on;
ssl_certificate /your/ssl/crt/file;
ssl_certificate_key /your/ssl/key/file;
client_max_body_size 1000m; # for big file upload
location / {
proxy_pass http://localhost:8080; # proxy to local docker's wordpress port
proxy_set_header Host $host;
proxy_redirect off;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme; # proxy with https header
}
}
80端口开了301重定向,强制把http跳转到https访问。
443端口使用HTTPS,开启HSTS全站强制HTTPS访问,将请求代理到本地的8080端口(对应上一节中wordpress容器外部端口),同时HTTP header加上了之前的访问协议类型HTTPS,避免文章开头提到的无限重定向问题。
注意修改server_name ssl_certificate ssl_certificate_key 参数的值为实际情况。
然后执行 nginx -t
检测是否有问题,没有问题执行 nginx -s reload
加载配置文件,就大功告成了。
0 条评论