使用 nginx 和 certbot 为 wordpress 开启 https
前段时间 wordpress 搭建完成,但是没有 https 总感觉少了点什么。由于 docker 还不熟悉,nginx 也不懂,前后折腾许久踩了很多坑,但是好在找到了一篇文章,很详细的描述了如何使用 docker-compose 来搭建 https 的 wordpress。
参考:https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-with-docker-compose
首先是 wordpress 的搭建,可以参考另一篇。
创建 nginx 文件夹和配置文件
创建的文件夹最好和 docker-compose.yml 在同一个文件夹下,方便编写配置和管理。
这个文件夹将用来绑定 nginx 容器的 volume。
~/www/wordpress$ mkdir nginx-conf ~/www/wordpress$ vi nginx-conf/nginx.conf
写入:
server { listen 80; server_name linyqiang.com www.mingof.top; index index.php index.html index.htm; root /var/www/html; location ~ /.well-known/acme-challenge { allow all; root /var/www/html; } location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri = 404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass wordpress:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { log_not_found off; access_log off; allow all; } location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { expires max; log_not_found off; } }
我对 nginx 不是很了解,只是 Ctrl
+C
, Ctrl
+V
。知道大概有什么用处就好了。注意这一块:
location ~ /.well-known/acme-challenge { allow all; root /var/www/html; }
这一块代码的作用就是让 certbot 在访问 linyqiang.com/.well-known/acme-challenge 时能通过。certbot 申请证书的时候需要。
改写 docker-compose.yml
原来的 compose file 是这样的:
version: '3.7' services: wordpress: image: wordpress depends_on: - mysql volumes: - wordpress:/var/www/html environment: WORDPRESS_DB_HOST: mysql:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: 12345 WORDPRESS_DB_NAME: wordpress # docker-compose 不支持 deploy,在使用 docker stack deploy 时可以用到 deploy: resources: limits: cpus: "0.5" ports: - 4000:80 mysql: image: mysql volumes: - mysql:/var/lib/mysql environment: MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: 12345 MYSQL_RANDOM_ROOT_PASSWORD: '1' ports: - 3306:3306 volumes: wordpress: mysql:
这里需要添加两个 service,一个是 nginx,一个是 certbot。
version: '3.7' services: wordpress: image: wordpress:5.2.3-fpm-alpine depends_on: - mysql volumes: - wordpress:/var/www/html environment: WORDPRESS_DB_HOST: mysql:3306 WORDPRESS_DB_USER: your_wordpress_dbuser WORDPRESS_DB_PASSWORD: your_secret WORDPRESS_DB_NAME: wordpress # 使用 docker-compose 会自动忽略 deploy deploy: replicas: 5 resources: limits: cpus: "0.5" restart_policy: condition: on-failure mysql: image: mysql:5.7 deploy: restart_policy: condition: on-failure ports: - 3306:3306 volumes: - mysql:/var/lib/mysql environment: MYSQL_DATABASE: wordpress MYSQL_USER: your_wordpress_dbuser MYSQL_PASSWORD: your_secret MYSQL_RANDOM_ROOT_PASSWORD: "1" # nginx 依赖 wordpress nginx: depends_on: - wordpress image: nginx:1.17.4-alpine restart: unless-stopped ports: - "80:80" - "443:443" volumes: - wordpress:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot:/etc/letsencrypt # certbot 依赖 nginx certbot: depends_on: - nginx image: certbot/certbot container_name: certbot volumes: - certbot:/etc/letsencrypt - wordpress:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email [email protected] --agree-tos --no-eff-email --force-renewal -d linyqiang.com -d www.mingof.top --server https://acme-v02.api.letsencrypt.org/directory volumes: certbot: wordpress: mysql:
把上面的 your_wordpress_dbuser 和 you_secret 换成你自定义的 mysql 用户和密码,域名换成自己域名就好。上面的镜像的依赖关系大概就是这个样子。
certbot -> nginx <- wordpress <- mysql
certbot 服务中指定了 ‘command’, 这个 command 后面的命令会在服务建立后自动运行。这个命令会帮助我们申请到证书。
使用 docker-compose 创建容器并自动获取证书
使用 docker-compose up
来试运行一下,成功后就可以使用 https 访问了。此时使用 docker volume ls
可以看到3个 volume。mysql 和 wordpress 的 volume 就不用说了,这里还多了一个 volume 叫做 wordpress_certbot。上面的 docker-compose.yml 可以看到这个 volume 同时绑定了 nginx 容器的 /etc/lesencrypt 文件夹 和 certbot 容器的 /etc/letsencrypt 文件夹。这样在 nginx 容器中就可以访问 certbot 容器下创建的 letsencrypt 证书文件了。
DRIVER VOLUME NAME
local wordpress_certbot
local wordpress_mysql
local wordpress_wordpress
现在还不可以使用 https 访问,要开启 https 还有改写一下 nginx.conf。让 nignx 监听 443 端口,并且加入证书配置。
改写 nignx.conf 让其支持 https
~/www/wordpress$ vi nginx-conf/nginx.conf
改写为:
server { listen 80; server_name linyqiang.com www.mingof.top; location ~ /.well-known/acme-challenge { allow all; root /var/www/html; } location / { rewrite ^ https://$host$request_uri? permanent; } } server { listen 443 ssl http2; #listen 80; server_name linyqiang.com www.mingof.top; index index.php index.html index.htm; root /var/www/html; server_tokens off; ssl_certificate /etc/letsencrypt/live/linyqiang.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/linyqiang.com/privkey.pem; include /etc/nginx/conf.d/options-ssl-nginx.conf; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri = 404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass wordpress:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { log_not_found off; access_log off; allow all; } location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { expires max; log_not_found off; } }
再次使用 docker-compose 试运行
docker-compose up
现在应该可以使用 https 访问了。
使用 docker stack deploy 代替 docker-compose
docker stack deploy 毕竟是 docker 官方的,能用官方推荐就用官方推荐吧。
docker stack deploy -c docker-compose.yml wordpress
docker stack deploy 和 docker-compose 还是有一点区别的。
Docker stack 会忽略一些指令,如 build 指令。 无法使用stack命令构建新镜像。 它是需要镜像是预先已经构建好的。
Docker stack 运行在 swarm mode 下。
Docker stack 还支持 deploy 指令
还有一个重要的一点就是我在使用 docker-compose 的时候会把 volume 的用户改为 root ,这个改动容易导致一些权限问题。