Docker Compose快速安装WordPress完整教程:详细步骤与配置指南

介绍

WordPress是一个基于MySQL数据库和PHP处理的免费开源内容管理系统(CMS)。由于其可扩展的插件架构和模板系统,大部分的管理工作可以通过Web界面完成。这就是为什么WordPress在创建各种类型的网站时都是一个受欢迎的选择,从博客到产品页面再到电子商务网站。

运行WordPress通常涉及安装LAMP(Linux、Apache、MySQL和PHP)或LEMP(Linux、Nginx、MySQL和PHP)堆栈,这可能需要花费很多时间。然而,通过使用Docker和Docker Compose等工具,您可以简化设置您所偏好的堆栈和安装WordPress的过程。与手动安装各个组件不同,您可以使用镜像,这些镜像标准化了库、配置文件和环境变量等内容。然后,在容器中运行这些镜像,容器是运行在共享操作系统上的隔离进程。此外,通过使用Compose,您可以协调多个容器之间的通信,例如应用程序和数据库。

在本教程中,您将建立一个多容器的WordPress安装。您的容器将包括一个MySQL数据库、一个Nginx Web服务器和WordPress本身。您还将通过使用Let’s Encrypt获取与您网站相关联的域名的TLS/SSL证书来保护您的安装。最后,您将设置一个定时任务来更新您的证书,以保证您的域名保持安全。

先决条件

为了按照这个教程操作,你需要准备以下物品:

  • 一台运行Ubuntu 20.04的服务器,以及一个具有sudo权限的非root用户和活动的防火墙。有关如何设置这些的指导,请阅读我们的《初始服务器设置》指南。
  • 在你的服务器上安装Docker,遵循《如何在Ubuntu 20.04上安装和使用Docker》的第1步和第2步。
  • 在你的服务器上安装Docker Compose,遵循《如何在Ubuntu 20.04上安装Docker Compose》的第1步。
  • 一个注册的域名。本教程将全程使用your_domain作为示例。你可以在Freenom免费获取一个,或使用你选择的域名注册商。
  • 为你的服务器设置以下两个DNS记录。你可以按照《硅云DNS简介》了解如何将它们添加到硅云账户的详细信息:
    一个将your_domain指向你服务器公网IP地址的A记录。
    一个将www.your_domain指向你服务器公网IP地址的A记录。

一旦你把一切都准备好了,你就可以开始第一步了。

第一步——定义Web服务器配置

在运行任何容器之前,你的第一步是为你的Nginx Web服务器定义配置。你的配置文件将包括一些WordPress特定的位置块,以及一个位置块,用于将Let’s Encrypt的验证请求指向Certbot客户端,以实现自动证书续订。

首先,为您的WordPress设置创建一个项目目录。在这个例子中,它被称为wordpress。如果您愿意,您可以给这个目录取一个不同的名字。

  1. mkdir wordpress

然后导航到目录。

  1. cd wordpress

接下来,创建一个用于存放配置文件的目录。

  1. mkdir nginx-conf

用nano或你最喜欢的编辑器打开文件。

  1. nano nginx-conf/nginx.conf

在这个文件中,添加一个服务器块,包含服务器名称和文档根目录的指令,以及用于指导Certbot客户端请求证书、PHP处理和静态资源请求的位置块。

请将以下代码添加到文件中。请确保将your_domain替换为您自己的域名。

~/wordpress/nginx-conf/nginx.conf 可以被简化为 ~/wp/nginx.conf。

server {
        listen 80;
        listen [::]:80;

        server_name your_domain www.your_domain;

        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;
        }
}

我们的服务器区块包括以下信息:

  • listen:这告诉Nginx监听端口80,这将允许您使用Certbot的webroot插件进行证书请求。请注意,您尚未包含端口443 — 在成功获取证书后,您将更新配置以包含SSL。
  • server_name:这定义了您的服务器名称和应该用于服务器请求的服务器块。请确保将此行中的your_domain替换为您自己的域名。
  • index:该指令定义了在处理服务器请求时将用作索引的文件。您在此处修改了默认的优先级顺序,将index.php移到index.html之前,以便Nginx在可能的情况下优先处理名为index.php的文件。
  • root:该指令指定服务器请求的根目录。这个目录/var/www/html是由WordPress Dockerfile中的指令在构建时创建的挂载点。这些Dockerfile指令还确保WordPress发行版中的文件被挂载到该卷。

位置区块

  • location ~ /.well-known/acme-challenge:此位置块将处理对.well-known目录的请求,Certbot将在该目录中放置临时文件以验证您域名的DNS是否解析到您的服务器。有了此配置,您将能够使用Certbot的webroot插件获取域名的证书。
  • location /:在此位置块中,使用try_files指令来检查与单个URI请求匹配的文件。但是,与默认返回404未找到状态不同,您将控制权传递给WordPress的index.php文件,并附带请求参数。
  • location ~ \.php$:此位置块将处理PHP处理并将这些请求代理到您的wordpress容器。因为您的WordPress Docker镜像将基于php:fpm镜像,您还将在此块中包含特定于FastCGI协议的配置选项。Nginx需要独立的PHP处理器来处理PHP请求。在这种情况下,这些请求将由php:fpm镜像中包含的php-fpm处理器处理。
    此外,此位置块还包括特定于FastCGI的指令、变量和选项,这些选项将请求代理到在wordpress容器中运行的WordPress应用程序,为解析的请求URI设置首选索引,并解析URI请求。
  • location ~ /\.ht:此块将处理.htaccess文件,因为Nginx不会提供这些文件。deny_all指令确保.htaccess文件永远不会提供给用户。
  • location = /favicon.ico, location = /robots.txt:这些块确保对/favicon.ico和/robots.txt的请求不会被记录。
  • location ~* \.(css|gif|ico|jpeg|jpg|js|png)$:此块关闭静态资源请求的日志记录,并确保这些资源具有高度可缓存性,因为它们通常服务成本较高。

关于FastCGI代理的更多信息,请阅读《理解和实现Nginx中的FastCGI代理》。关于服务器和位置块的信息,请查阅《理解Nginx服务器和位置块选择算法》。

在编辑完成后保存并关闭文件。如果您使用的是nano,可以通过按下CTRL+X,然后按Y,最后按下ENTER键来完成操作。

通过设置Nginx配置,您可以继续创建运行时传递给应用程序和数据库容器的环境变量。

步骤2 – 定义环境变量

第三步 – 配置环境变量保护敏感信息

在运行WordPress和数据库容器时,需要配置特定的环境变量以确保应用程序数据的持久化和可访问性。这些变量包含敏感信息(如MySQL root密码、数据库用户和密码)以及非敏感信息(如数据库名称和主机)。

为了避免在Docker Compose主文件中直接设置这些值,最佳实践是将敏感信息存储在单独的.env文件中并限制其访问权限。这种方法可以有效防止敏感数据被意外提交到项目存储库中,从而避免安全风险。

创建.env文件

在您的主项目目录~/wordpress中,创建一个名为.env的文件:

nano .env

在此文件中,您需要设置MySQL root用户的密码以及WordPress用于访问数据库的用户名和密码。请添加以下变量,并记得为每个变量提供您自己的安全值:

~/wordpress/.env

MYSQL_ROOT_PASSWORD=您的root密码
MYSQL_USER=您的WordPress数据库用户名
MYSQL_PASSWORD=您的WordPress数据库密码

编辑完成后,保存并关闭文件。

保护敏感文件

由于.env文件包含敏感信息,您需要确保它被包含在项目的.gitignore和.dockerignore文件中。这样Git和Docker就不会将这些文件复制到您的Git仓库和Docker镜像中。

配置Git忽略文件

如果您计划使用Git进行版本控制,首先将当前工作目录初始化为Git仓库:

git init

然后创建并打开.gitignore文件:

nano .gitignore

将.env文件添加到.gitignore中:

~/wordpress/.gitignore

.env

编辑完成后,保存并关闭文件。

配置Docker忽略文件

同样,将.env添加到.dockerignore文件中是一个很好的安全措施,这样在将该目录作为构建上下文时,敏感文件就不会出现在您的容器中。

打开.dockerignore文件:

nano .dockerignore

将.env文件添加到.dockerignore中:

~/wordpress/.dockerignore

.env

您还可以根据需要添加其他与应用程序开发相关的文件和目录:

~/wordpress/.dockerignore

.env
.git
docker-compose.yml
.dockerignore

编辑完成后,保存并关闭文件。

第四步 – 使用Docker Compose定义服务

您的docker-compose.yml文件将包含所有服务定义。在Docker Compose中,服务代表运行的容器,而服务定义则指定每个容器的运行配置。

通过使用Compose,您可以定义不同的服务来运行多容器应用程序,因为Compose允许您通过共享网络和卷将这些服务连接在一起。这对您的WordPress设置非常有帮助,因为您将为数据库、WordPress应用程序和Web服务器创建不同的容器。您还将创建一个容器来运行Certbot客户端,以获取用于Web服务器的SSL证书。

首先,在项目目录中创建并打开docker-compose.yml文件:

nano docker-compose.yml

将以下代码添加到您的Compose文件中,包括版本信息和db数据库服务的定义:

~/wordpress/docker-compose.yml

version: '3'

services:
  db:
    image: mysql:8.0
    container_name: db
    restart: unless-stopped
    env_file: .env
    environment:
      MYSQL_DATABASE: wordpress
    volumes:
      - dbdata:/var/lib/mysql
    command: '--default-authentication-plugin=mysql_native_password'
    networks:
      - app-network

volumes:
  dbdata:

networks:
  app-network:
    driver: bridge
version: '3'

services:
  db:
    image: mysql:8.0
    container_name: db
    restart: unless-stopped
    env_file: .env
    environment:
      - MYSQL_DATABASE=wordpress
    volumes: 
      - dbdata:/var/lib/mysql
    command: '--default-authentication-plugin=mysql_native_password'
    networks:
      - app-network

数据库服务定义包含以下选项:

  • image:这告诉Compose要拉取哪个镜像来创建容器。这里你固定使用mysql:8.0镜像,以避免随着mysql:latest镜像不断更新而产生未来的冲突。有关版本固定和避免依赖冲突的更多信息,请阅读Docker文档中关于Dockerfile最佳实践的内容。
  • container_name:这为容器指定一个名称。
  • restart:这定义了容器的重启策略。默认是no,但你已将容器设置为除非手动停止,否则会重启。
  • env_file:这个选项告诉Compose,你希望从位于构建上下文中的名为.env的文件添加环境变量。在这种情况下,构建上下文是你当前的目录。
  • environment:这个选项允许你添加额外的环境变量,超出.env文件中定义的那些。你将MYSQL_DATABASE变量设置为wordpress,为你的应用程序数据库提供一个名称。因为这是非敏感信息,你可以直接将其包含在docker-compose.yml文件中。
  • volumes:在这里,你将一个名为dbdata的命名卷挂载到容器上的/var/lib/mysql目录。这是大多数发行版上MySQL的标准数据目录。
  • command:这个选项指定一个命令来覆盖镜像的默认CMD指令。在这种特定情况下,你将向Docker镜像的标准mysqld命令添加一个选项,该命令在容器上启动MySQL服务器。这个选项–default-authentication-plugin=mysql_native_password将–default-authentication-plugin系统变量设置为mysql_native_password,指定哪种身份验证机制应该管理对服务器的新身份验证请求。由于PHP以及你的WordPress镜像不支持MySQL的较新身份验证默认值,你必须进行此调整以验证你的应用程序数据库用户。
  • networks:这指定你的应用程序服务将加入app-network网络,你将在文件底部定义该网络。

接下来,在数据库服务定义下方,增加你的WordPress应用程序服务的定义。

~/wordpress/docker-compose.yml 文件的中文意思是:

...
  wordpress:
    depends_on: 
      - db
    image: wordpress:5.1.1-fpm-alpine
    container_name: wordpress
    restart: unless-stopped
    env_file: .env
    environment:
      - WORDPRESS_DB_HOST=db:3306
      - WORDPRESS_DB_USER=$MYSQL_USER
      - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD
      - WORDPRESS_DB_NAME=wordpress
    volumes:
      - wordpress:/var/www/html
    networks:
      - app-network

在此服务定义中,您正在命名容器并定义重启策略,就像您在数据库服务中所做的一样。您还添加了一些特定于该容器的选项。

  • depends_on: 此选项确保您的容器将按照依赖顺序启动,wordpress容器将在db容器之后启动。您的WordPress应用程序依赖于应用程序数据库和用户的存在,因此表达这种依赖顺序将使您的应用程序能够正常启动。
  • image: 在此设置中,您使用的是5.1.1-fpm-alpine WordPress镜像。如步骤1中所述,使用此镜像可确保您的应用程序拥有Nginx处理PHP所需的php-fpm处理器。这也是一个alpine镜像,源自Alpine Linux项目,这将有助于保持您的整体镜像大小较小。有关使用alpine镜像的优缺点以及这对您的应用程序是否有意义的更多信息,请查看Docker Hub WordPress镜像页面的镜像变种部分下的完整讨论。
  • env_file: 同样,您指定要从.env文件中提取值,因为这是您定义应用程序数据库用户和密码的地方。
  • environment: 在这里,您使用在.env文件中定义的值,但将它们分配给WordPress镜像期望的变量名:WORDPRESS_DB_USER和WORDPRESS_DB_PASSWORD。您还定义了一个WORDPRESS_DB_HOST,它将是运行在db容器上的MySQL服务器,可通过MySQL的默认端口3306访问。您的WORDPRESS_DB_NAME将是您在MySQL服务定义中为MYSQL_DATABASE指定的相同值:wordpress。
  • volumes: 您正在将一个名为wordpress的命名卷挂载到WordPress镜像创建的/var/www/html挂载点。以这种方式使用命名卷将允许您与其他容器共享您的应用程序代码。
  • networks: 您还将wordpress容器添加到app-network网络。

接下来,在WordPress应用程序服务定义之下,添加以下定义以配置您的Web服务器Nginx服务。

文件路径表达说明:~/wordpress/docker-compose.yml 也可以表达为 ~/wordpress/容器编排文件.yml
...
  webserver:
    depends_on:
      - wordpress
    image: nginx:1.15.12-alpine
    container_name: webserver
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - wordpress:/var/www/html
      - ./nginx-conf:/etc/nginx/conf.d
      - certbot-etc:/etc/letsencrypt
    networks:
      - app-network

在这里,您为容器命名,并设置其依赖于wordpress容器以控制启动顺序。您还使用了alpine版本的Nginx映像——nginx:1.15.12-alpine。

此服务定义还包括以下选项:

  • ports: 此配置将容器的80端口暴露出来,以启用您在第一步中定义的nginx.conf文件中的配置选项。
  • volumes: 在这里,您定义了命名卷和绑定挂载的组合:
    • wordpress:/var/www/html: 这会将您的WordPress应用程序代码挂载到/var/www/html目录,该目录是您在Nginx服务器块中设置为根目录的位置。
    • ./nginx-conf:/etc/nginx/conf.d: 这会将主机上的Nginx配置目录绑定挂载到容器中的相应目录,确保您在主机上对文件所做的任何更改都会反映在容器中。
    • certbot-etc:/etc/letsencrypt: 这会将您域名的相关Let’s Encrypt证书和密钥挂载到容器中的适当目录。

您还将此容器添加到了app-network网络中。

最后,在Web服务器定义的下方,添加certbot服务的最后一个服务定义。请确保将此处列出的电子邮件地址和域名替换为您自己的信息。

建议的文件路径为:~/wordpress/docker-compose.yml

  certbot:
    depends_on:
      - webserver
    image: certbot/certbot
    container_name: certbot
    volumes:
      - certbot-etc:/etc/letsencrypt
      - wordpress:/var/www/html
    command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain

这个定义告诉Compose从Docker Hub拉取certbot/certbot镜像。它还使用了命名卷来与Nginx容器共享资源,包括certbot-etc中的域名证书和密钥,以及wordpress中的应用程序代码。

再说一遍,你使用了depends_on来指定在webserver服务运行时应启动certbot容器。

你还包含了一个命令选项,用于指定要与容器的默认certbot命令一起运行的子命令。certonly子命令将使用以下选项获取证书。

  • –webroot: 这告诉Certbot使用webroot插件将文件放置在webroot文件夹中进行身份验证。此插件依赖于HTTP-01验证方法,该方法使用HTTP请求来证明Certbot可以从响应给定域名的服务器访问资源。
  • –webroot-path: 这指定了webroot目录的路径。
  • –email: 你用于注册和恢复的首选电子邮件。
  • –agree-tos: 这表示你同意ACME的订阅者协议。
  • –no-eff-email: 这告诉Certbot你不希望与电子前沿基金会(EFF)共享你的电子邮件。如果你愿意,可以省略此选项。
  • –staging: 这告诉Certbot你想要使用Let’s Encrypt的测试环境来获取测试证书。使用此选项允许你测试配置选项并避免可能的域名请求限制。有关这些限制的更多信息,请阅读Let’s Encrypt的速率限制文档。
  • -d: 这允许你指定要应用于请求的域名。在这种情况下,你包含了your_domain和www.your_domain。请确保用你自己的域名替换这些。

在certbot服务定义的下方添加你的网络和卷定义:

...
volumes:
  certbot-etc:
  wordpress:
  dbdata:

networks:
  app-network:
    driver: bridge  

您的顶级卷键定义了卷certbot-etc、wordpress和dbdata。当Docker创建卷时,卷的内容存储在由Docker管理的主机文件系统的/var/lib/docker/volumes/目录中。然后,每个卷的内容都会从该目录挂载到使用该卷的任何容器中。通过这种方式,可以在容器之间共享代码和数据。

用户定义的桥接网络应用网络允许容器间的通信,因为它们位于同一台Docker守护进程主机上。这样可以简化应用程序内部的流量和通信,因为它在同一桥接网络上打开了所有容器之间的端口,同时不向外界公开任何端口。因此,您的数据库、WordPress和Web服务器容器可以彼此通信,您只需要暴露80端口以供应用程序的前端访问。

以下是完整的docker-compose.yml文件:

以下是docker-compose.yml文件的整个内容:

~/wordpress/docker-compose.yml可以改写为:~/wordpress/docker-compose文件。

version: '3'

services:
  db:
    image: mysql:8.0
    container_name: db
    restart: unless-stopped
    env_file: .env
    environment:
      - MYSQL_DATABASE=wordpress
    volumes: 
      - dbdata:/var/lib/mysql
    command: '--default-authentication-plugin=mysql_native_password'
    networks:
      - app-network

  wordpress:
    depends_on: 
      - db
    image: wordpress:5.1.1-fpm-alpine
    container_name: wordpress
    restart: unless-stopped
    env_file: .env
    environment:
      - WORDPRESS_DB_HOST=db:3306
      - WORDPRESS_DB_USER=$MYSQL_USER
      - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD
      - WORDPRESS_DB_NAME=wordpress
    volumes:
      - wordpress:/var/www/html
    networks:
      - app-network

  webserver:
    depends_on:
      - wordpress
    image: nginx:1.15.12-alpine
    container_name: webserver
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - wordpress:/var/www/html
      - ./nginx-conf:/etc/nginx/conf.d
      - certbot-etc:/etc/letsencrypt
    networks:
      - app-network

  certbot:
    depends_on:
      - webserver
    image: certbot/certbot
    container_name: certbot
    volumes:
      - certbot-etc:/etc/letsencrypt
      - wordpress:/var/www/html
    command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain

volumes:
  certbot-etc:
  wordpress:
  dbdata:

networks:
  app-network:
    driver: bridge  

当您编辑完毕,请保存并关闭文件。

现在,您已经有了服务定义,可以启动容器并测试证书请求了。

第四步:获取SSL证书和凭证

使用docker-compose up命令启动容器,按照您指定的顺序创建并运行容器。通过添加-d参数,该命令会在后台运行数据库、WordPress和Web服务器容器。

$ docker-compose up -d

以下输出确认您的服务已经创建成功:

输出

Creating db ... done 
Creating wordpress ... done 
Creating webserver ... done 
Creating certbot ... done

使用docker-compose ps命令,查看您的服务的状态。

$ docker-compose ps

完成后,您的数据库、WordPress和Web服务器服务将处于运行状态,并且certbot容器将以退出状态0退出。

输出

Name                 Command               State           Ports         
---------------------------------------------------------------------
certbot     certbot certonly --webroot ...   Exit 0                         
db          docker-entrypoint.sh --def ...   Up      3306/tcp, 33060/tcp   
webserver   nginx -g daemon off;             Up      0.0.0.0:80->80/tcp    
wordpress   docker-entrypoint.sh php-fpm     Up      9000/tcp

如果数据库、WordPress或Web服务器服务的”State”列中显示除”运行中”以外的任何状态,或者certbot容器的退出状态不是0,这意味着您可能需要使用docker-compose logs命令检查服务日志。

$ docker-compose logs service_name

现在您可以使用docker-compose exec命令检查您的证书是否已经挂载到Web服务器容器上。

$ docker-compose exec webserver ls -la /etc/letsencrypt/live

一旦您的证书请求成功,下面是输出内容:

输出

total 16
drwx------ 3 root root 4096 May 10 15:45 .
drwxr-xr-x 9 root root 4096 May 10 15:45 ..
-rw-r--r-- 1 root root  740 May 10 15:45 README
drwxr-xr-x 2 root root 4096 May 10 15:45 your_domain

既然您知道您的请求会成功,您可以编辑certbot服务定义,移除--staging标志。

打开 docker-compose.yml 文件。

$ nano docker-compose.yml

在文件中找到certbot服务定义的部分,并用命令选项中的--force-renewal标志替换--staging标志,这将告诉Certbot您希望使用与现有证书相同的域名请求新证书。以下是更新标志的certbot服务定义:

~/wordpress/docker-compose.yml

...
  certbot:
    depends_on:
      - webserver
    image: certbot/certbot
    container_name: certbot
    volumes:
      - certbot-etc:/etc/letsencrypt
      - certbot-var:/var/lib/letsencrypt
      - wordpress:/var/www/html
    command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
...

您现在可以运行docker-compose up来重新创建certbot容器。您还需在命令中加上–no-deps选项,告诉Compose可以跳过启动webserver服务的步骤,因为它已经在运行中。

  1. docker-compose up –force-recreate –no-deps certbot

以下输出表明您的证书请求成功:

输出

重新创建certbot ... 完成
连接到certbot
certbot | 将调试日志保存到 /var/log/letsencrypt/letsencrypt.log
certbot | 选择的插件:验证器 webroot,安装程序 无
certbot | 续订现有证书
certbot | 执行以下挑战:
certbot | 对 your_domain 的 http-01 挑战
certbot | 对 www.your_domain 的 http-01 挑战
certbot | 对所有未匹配的域名使用 webroot 路径 /var/www/html
certbot | 等待验证...
certbot | 清理挑战
certbot | 重要说明:
certbot | - 恭喜!您的证书和链已保存在:
certbot | /etc/letsencrypt/live/your_domain/fullchain.pem
certbot | 您的密钥文件已保存在:
certbot | /etc/letsencrypt/live/your_domain/privkey.pem
certbot | 您的证书将于 2019-08-08 过期。要在将来获取新的或调整的
certbot | 证书版本,只需再次运行 certbot
certbot | 要非交互式续订所有证书,请运行
certbot | "certbot renew"
certbot | - 您的帐户凭据已保存在 Certbot
certbot | 配置目录 /etc/letsencrypt 中。您现在应该制作一个
certbot | 此文件夹的安全备份。此配置目录将
certbot | 还包含由 Certbot 获取的证书和私钥,因此
certbot | 定期备份此文件夹是理想的。
certbot | - 如果您喜欢 Certbot,请考虑通过以下方式支持我们的工作:
certbot |
certbot | 向 ISRG / Let's Encrypt 捐款:https://letsencrypt.org/donate
certbot | 向 EFF 捐款:https://eff.org/donate-le
certbot |
certbot 以代码 0 退出

有了您的证书,您可以继续修改您的Nginx配置以包含SSL。

步骤五 – 修改网络服务器配置和服务定义

在您的Nginx配置中启用SSL将涉及到添加一个HTTP重定向到HTTPS,指定SSL证书和密钥的位置,以及添加安全参数和头部。

由于您将重新创建Web服务器服务以包含这些附加功能,您现在可以停止它。

  1. docker-compose stop webserver

 

在修改配置文件之前,使用curl从Certbot获取推荐的Nginx安全参数。

  1. curl -sSLo nginx-conf/options-ssl-nginx.conf https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf

 

这个命令将把这些参数保存在一个名为 options-ssl-nginx.conf 的文件中,该文件位于 nginx-conf 目录中。

接下来,删除你之前创建的Nginx配置文件。

  1. rm nginx-conf/nginx.conf

 

创建并打开文件的另一个版本。

  1. nano nginx-conf/nginx.conf

 

请将以下代码添加到文件中,以将HTTP重定向到HTTPS,并添加SSL凭据、协议和安全标头。请记得将your_domain替换为您自己的域名。

将以下内容以中文进行本地化转述,只需要一个选项:
~/wordpress/nginx-conf/nginx.conf~/wordpress/nginx-conf/nginx.conf

server {
        listen 80;
        listen [::]:80;

        server_name your_domain www.your_domain;

        location ~ /.well-known/acme-challenge {
                allow all;
                root /var/www/html;
        }

        location / {
                rewrite ^ https://$host$request_uri? permanent;
        }
}

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name your_domain www.your_domain;

        index index.php index.html index.htm;

        root /var/www/html;

        server_tokens off;

        ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/your_domain/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;
        # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        # enable strict transport security only if you understand the implications

        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;
        }
}

HTTP 服务器块指定 Certbot 更新请求的网站根目录为 `.well-known/acme-challenge` 目录。它还包括一个重写指令,将 HTTP 请求指向根目录并转换为 HTTPS。

HTTPS服务器块启用了SSL和HTTP2。要了解有关HTTP/2对HTTP协议的迭代以及其对网站性能的好处的更多信息,请阅读《如何在Ubuntu 18.04上设置支持HTTP/2的Nginx》的介绍部分。

该块还包括您SSL证书和密钥的位置,以及您保存在nginx-conf/options-ssl-nginx.conf中的已建议的Certbot安全参数。

此外,还包括一些安全头部,能够使您在SSL Labs和Security Headers服务器测试网站上获得A级评价。这些头部包括X-Frame-Options、X-Content-Type-Options、引荐政策、内容安全策略以及X-XSS-Protection。HTTP严格传输安全(HSTS)头部被注释掉了 —— 只有在您理解相关影响并评估其”preload”功能后才能启用。

您的根目录和索引指令也位于此块中,与第一步中讨论的其余WordPress特定的位置块一样。

编辑完成后,保存并关闭文件。

在重新创建网络服务器服务之前,您需要向网络服务器服务定义中添加一个443端口映射。

打开你的 docker-compose.yml 文件。

  1. nano docker-compose.yml

 

在Web服务器服务定义中,添加以下端口映射:

~/wordpress/docker-compose.yml 的翻译:
~/wordpress/docker-compose.yml

...
  webserver:
    depends_on:
      - wordpress
    image: nginx:1.15.12-alpine
    container_name: webserver
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - wordpress:/var/www/html
      - ./nginx-conf:/etc/nginx/conf.d
      - certbot-etc:/etc/letsencrypt
    networks:
      - app-network

编辑后的内容如下,这是完整的docker-compose.yml文件。

/Users/yourusername/wordpress/docker-compose.yml

version: '3'

services:
  db:
    image: mysql:8.0
    container_name: db
    restart: unless-stopped
    env_file: .env
    environment:
      - MYSQL_DATABASE=wordpress
    volumes: 
      - dbdata:/var/lib/mysql
    command: '--default-authentication-plugin=mysql_native_password'
    networks:
      - app-network

  wordpress:
    depends_on: 
      - db
    image: wordpress:5.1.1-fpm-alpine
    container_name: wordpress
    restart: unless-stopped
    env_file: .env
    environment:
      - WORDPRESS_DB_HOST=db:3306
      - WORDPRESS_DB_USER=$MYSQL_USER
      - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD
      - WORDPRESS_DB_NAME=wordpress
    volumes:
      - wordpress:/var/www/html
    networks:
      - app-network

  webserver:
    depends_on:
      - wordpress
    image: nginx:1.15.12-alpine
    container_name: webserver
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - wordpress:/var/www/html
      - ./nginx-conf:/etc/nginx/conf.d
      - certbot-etc:/etc/letsencrypt
    networks:
      - app-network

  certbot:
    depends_on:
      - webserver
    image: certbot/certbot
    container_name: certbot
    volumes:
      - certbot-etc:/etc/letsencrypt
      - wordpress:/var/www/html
    command: certonly --webroot --webroot-path=/var/www/html --email 你的邮箱@你的域名 --agree-tos --no-eff-email --force-renewal -d 你的域名 -d www.你的域名

volumes:
  certbot-etc:
  wordpress:
  dbdata:

networks:
  app-network:
    driver: bridge  

编辑完成后保存并关闭文件。

重建Web服务器服务。

  1. docker-compose up -d –force-recreate –no-deps webserver

 

请使用docker-compose ps命令检查您的服务。

  1. docker-compose ps

 

输出应指示您的数据库、WordPress和Web服务器服务正在运行。

输出
名称        命令                           状态    端口
--------------------------------------------------------------------------------
certbot     certbot certonly --webroot ...  Exit 0  
db          docker-entrypoint.sh --def ...  Up      3306/tcp, 33060/tcp
webserver   nginx -g daemon off;           Up      0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
wordpress   docker-entrypoint.sh php-fpm    Up      9000/tcp

第六步:通过网络界面完成WordPress安装

在您的容器运行时,您可以通过Web界面完成WordPress安装。在容器运行的情况下,通过WordPress的网页界面完成安装。

在您的浏览器中,导航到您服务器的域名。请记得将your_domain替换为您自己的域名:

https://your_domain

请选择您希望使用的语言:

WordPress Language Selector

点击”继续”后,您将会进入主设置页面,您需要为您的网站选择一个名称和一个用户名。在这里选择一个容易记住的用户名(而不是”admin”)和一个强密码是一个好主意。您可以使用WordPress自动生成的密码,也可以自己创建密码。

最后,您需要输入您的电子邮件地址,并决定是否要阻止搜索引擎对您的网站进行索引。

WordPress Main Setup Page

点击页面底部的”安装WordPress”按钮会带您到登录界面。

WordPress Login Screen

一旦登录,您将可以访问WordPress管理仪表板。

WordPress Main Admin Dashboard

完成WordPress安装后,您可以采取措施确保您的SSL证书能够自动更新。

步骤 7 — 更新Let’s Encrypt证书

Let’s Encrypt证书有效期为90天。您可以设置自动更新流程以确保其不过期。其中一种方法是使用cron定时工具创建一个任务。在下面的示例中,您将创建一个cron任务,定期运行一个脚本来更新您的证书并重新加载您的Nginx配置。

首先,创建一个名为 ssl_renew.sh 的脚本:

nano ssl_renew.sh

将以下代码添加到脚本中,以更新您的证书并重新加载您的Web服务器配置。请记住将示例用户名sammy替换为您自己的非根用户名:

#!/bin/bash

COMPOSE="/usr/local/bin/docker-compose --no-ansi"
DOCKER="/usr/bin/docker"

cd /home/sammy/wordpress/
$COMPOSE run certbot renew --dry-run && $COMPOSE kill -s SIGHUP webserver
$DOCKER system prune -af

这个脚本的工作原理如下:

  • 首先,将docker-compose二进制文件路径指定给COMPOSE变量,并添加–no-ansi选项以禁用ANSI控制字符。
  • 然后,将docker二进制文件路径指定给DOCKER变量。
  • 接着,切换到~/wordpress项目目录,并执行以下操作:
  • 使用docker-compose run命令启动certbot容器并运行renew子命令,该命令会更新即将到期的证书。–dry-run选项用于测试脚本。
  • 使用docker-compose kill命令向webserver容器发送SIGHUP信号,以重新加载Nginx配置。
  • 最后,运行docker system prune命令来移除所有未使用的容器和镜像。

编辑完成后保存并关闭文件。使用以下命令使其可执行:

chmod +x ssl_renew.sh

接下来,打开您的根crontab文件,以在指定的时间间隔运行续订脚本:

sudo crontab -e

如果这是您第一次编辑此文件,您将被要求选择一个编辑器:

输出
no crontab for root - using an empty one
Select an editor.  To change later, run 'select-editor'.
  1. /bin/nano        <---- easiest
  2. /usr/bin/vim.basic
  3. /usr/bin/vim.tiny
  4. /bin/ed
Choose 1-4 [1]: 

在这个文件的最底部,添加如下一行,以设置定时任务:

定时任务表
...\n*/5 * * * * /home/sammy/wordpress/ssl_renew.sh >> /var/log/cron.log 2>&1\n

\n这将把任务间隔设置为每五分钟一次,这样你就可以测试你的续订请求是否按预期工作。一个名为cron.log的日志文件将被创建来记录任务的相关输出。\n\n五分钟后,检查cron.log文件以确认续约请求是否成功。\n

\n

    \n

  1. tail -f /var/log/cron.log
  2. \n

\n

\n \n

\n下面的输出证实了成功续订。\n

\n

输出

\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ** 试运行:模拟证书到期时的'certbot renew'操作 **(下面的测试证书尚未保存。)恭喜,所有续订均已成功。以下证书已续订:/etc/letsencrypt/live/your_domain/fullchain.pem(成功)** 试运行:模拟证书到期时的'certbot renew'操作 **(上面的测试证书尚未保存。)- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n

\n在命令行中输入CTRL+C,以退出。\n\n你可以修改定时任务表文件来设置每日的间隔。例如,要在每天中午运行脚本,你可以修改文件的最后一行为以下内容。\n

定时任务表

...\n0 12 * * * /home/sammy/wordpress/ssl_renew.sh >> /var/log/cron.log 2>&1\n

\n您还需要从您的ssl_renew.sh脚本中移除--dry-run选项。\n

请为以下内容提供中文的同义表达,只需要一种选择:\n~/wordpress/ssl_renew.sh可以表达为:"~/wordpress/ssl_renew.sh"

#!/bin/bash\n\nCOMPOSE="/usr/local/bin/docker-compose --no-ansi"\nDOCKER="/usr/bin/docker"\n\ncd /home/sammy/wordpress/\n$COMPOSE run certbot renew && $COMPOSE kill -s SIGHUP webserver\n$DOCKER system prune -af\n

\n你的定时任务将确保你的Let's Encrypt证书在符合条件时进行续订,以防止过期。你还可以使用日志轮转工具设置日志轮转并压缩日志文件。\n

结论

在这个教程中,你使用Docker Compose来创建一个带有Nginx web服务器的WordPress安装。作为工作流的一部分,你获取了与你的WordPress网站关联的域名的TLS/SSL证书。此外,你创建了一个定时任务,在需要时更新这些证书。\n\n为进一步提高网站性能和冗余度,您可以参考以下有关WordPress资源传递和备份的文章。\n

    \n

  • 如何使用Silicon Cloud Spaces CDN加速WordPress资源传递。
  • \n

  • 如何将WordPress网站备份到Spaces。
  • \n

  • 如何在Silicon Cloud Spaces上存储WordPress资源。
  • \n

\n如果你对使用Kubernetes进行容器化工作流感兴趣,你还可以查看:\n

    \n

  • 如何使用Helm在Kubernetes上设置WordPress与MySQL。
  • \n

bannerAds