介绍
WordPress 是目前最受欢迎的内容管理系统 (CMS) 之一。据统计,它驱动了超过 39% 的所有网站,即您在万维网上看到的那些。它之所以成为热门选择,是因为它可以通过插件进行扩展,并且拥有灵活的模板系统。它允许您在几秒钟内更改其外观。此外,它的管理可以通过 Web 界面完成,不需要太多的技术知识。
此外,WordPress 是免费且开源的,它构建在 MySQL 数据库之上,并使用 PHP 进行处理。您可以 在 LAMP 架构(Linux、Apache、MySQL 和 PHP)上部署 WordPress 或 LEMP 架构(Linux、Nginx、MySQL 和 PHP)。然而,事实证明,每次想要部署时都搭建该架构非常耗时。
幸运的是,现代软件交付方法,例如 云计算, Docker,以及 Docker Compose 优化了整体开发体验。这些工具通过避免每次部署应用程序时安装和配置单个组件的额外开销,简化了搭建任何技术栈的过程。相反,您只需编写配置文件,这些文件将用于拉取和创建镜像,并在 Docker 容器中运行它们,从而让您只需一个命令即可部署应用程序。
容器是轻量级、虚拟化、可移植且软件定义的标准化环境,使该软件能够与物理宿主机上运行的其他软件隔离运行。Docker Compose 允许您管理多个容器并确保它们进行通信。例如,应用程序源代码和数据库必须进行通信。
在本教程中,我们将 构建一个多容器化的 WordPress 应用程序。一个完整的 WordPress 应用需要三个容器:MySQL 数据库、Nginx 服务器和 WordPress 源代码。 安全性是现代网站的重中之重,我们将获取 SSL 证书,来自 Let’s Encrypt 以保护您的安装。然后,我们将设置一个 cron 任务来定期检查和更新证书,以便持续维护您网站的安全。
前提条件
- 由于这是一个动手实践教程,您应该安装 Ubuntu 20.04 作为初始运行环境。您还需要一个 具有 sudo 权限的非 root 用户。这里有一个 分步教程,帮助您设置 Ubuntu 服务器.
- 您还需要安装 Docker。您可以参考这篇关于 如何在 Ubuntu 18.04 上安装和操作 Docker.
- 安装 Docker Compose。您可以按照步骤 1 的 教程 如何在 Ubuntu 20.04 上安装和配置 Docker Compose.
- 需要一个已注册的域名才能获取 来自 Let’s Encrypt 的 TLS/SSL 证书。在本教程中,我们将使用
example.com. - 设置 DNS 记录以将流量指向您的 VPS。您需要两条 DNS 记录:
- 一条 A 记录,其中
example.com指向您服务器的公网 IP 地址。 - 一条 A 记录,其中
www.example.com指向您服务器的公网 IP 地址。
- 一条 A 记录,其中
步骤 1:定义 Web 服务器的配置
Web 服务器保存着您的网站文件,并允许用户访问您的 Web 应用程序。因此,在第一步中,我们定义 Web 服务器的配置是再合适不过的了。我们将定义一个 Nginx 服务器配置 文件,其中将包含特定于 WordPress 的 location 块。我们还将包含 location 块,以将 Let’s Encrypt 验证请求引导至 Certbot 客户端,从而实现证书的自动续订。
让我们首先为该项目创建一个目录。您可以选择您喜欢的目录名称。我们将使用 wordpress_docker 用于本教程。输入以下命令以创建目录并进入该目录:
|
1 |
mkdir wordpress_docker && cd wordpress_docker |
接下来,使用以下命令创建一个用于存放 Nginx 配置文件的目录:
|
1 |
mkdir nginx-conf |
使用 nano 并通过以下命令打开文件:
|
1 |
nano nginx-conf/nginx.conf |
在此文件中,我们将为 Nginx 服务器块配置定义基本指令。这些包括服务器名称、文档根目录和位置块的指令,用于引导 Certbot 插件对证书、静态文件和 PHP 处理的请求。您可以阅读我们的教程 如何使用 Let’s Encrypt 保护 Nginx 以了解更多信息。将以下代码添加到文件中,并将 example.com 替换为您注册的域名:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
server { listen 80; listen [::]:80; server_name example.com www.example.com; 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; } 位置 ~ \.php$ { 尝试_文件 $uri =404; fastcgi_分割_路径_信息 ^(.+\.php)(/.+)$; fastcgi_传递 应用:9000; fastcgi_索引 索引.php; 包含 fastcgi_参数; fastcgi_参数 脚本_文件名 $文档_根$fastcgi_脚本_名称; fastcgi_参数 路径_信息 $fastcgi_路径_信息; } 位置 ~ /\.ht { 拒绝 所有; } 位置 = /favicon.ico { 日志_未_找到 关闭; 访问_日志 关闭; } 位置 = /robots.txt { 日志_未_找到 关闭; 访问_日志 关闭; 允许 所有; } 位置 ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { 过期 最大; 日志_未_找到 关闭; } } |
让我们定义您添加的部分:
-
指令:
listen:它告诉 Nginx 监听端口80。这允许使用 Certbot 的 webroot 插件来发起证书请求。一旦我们获得了 SSL 证书,我们将更新此配置以使用端口443.server_name:这定义了 域名 名称,该配置应处理此名称。指向此处定义的域名的流量将被定向到这个特定的服务器块,从而指向文档root.root: 它定义了对上述域名请求的根目录。它通常是存放我们实际网站文件的目录。我们已将该目录设置为/var/www/html. 它将被创建为一个 Docker 挂载点(在容器构建期间)。我们将在 WordPress Dockerfile 中定义此过程的指令。.index: 它定义了在处理请求时用作索引或 Web 服务器入口点的文件。我们已将 index.php 移至 index.html 之前,以便 Nginx 优先处理index.php.
-
Location 块:
location ~ /.well-known/acme-challenge: 处理指向 well-known 目录的请求,Certbot 会在此目录中添加一个临时文件,以验证指定域名的 DNS 是否指向我们请求 SSL 证书的特定服务器。这就是为什么您应该在此步骤中添加一个有效的域名,而不是使用我们在本教程中使用的example.com。location /: 匹配 URI 请求并将控制权交给 WordPressindex.php以请求参数进行处理。location ~ \.php$:处理 PHP 处理并将请求传递给 WordPress 容器(我们将在后面的步骤中为此定义一个配置文件)。我们在此处定义了专门针对 FastCGI 协议的配置,因为 WordPress Docker 镜像将基于 php:fpm 镜像。Nginx 使用独立的 PHP 处理器来处理特定于 PHP 的请求。我们将使用php-fpm处理器,它随附于php:fpmDocker 镜像。location ~ /\.ht:处理.htaccess文件,Nginx 不使用这些文件。deny all指令确保这些文件永远不会提供给网站访问者。location = /favicon.ico, location = /robots.txt: 正如定义中所示,这可以防止记录对/favicon.ico和/robots.txt文件的请求。location ~* \.(css|gif|ico|jpeg|jpg|js|png)$: 关闭对静态文件请求的日志记录,并确保它们被缓存以减轻服务器的负载。
您现在可以通过按 CTRL+X, Y,然后 ENTER。这就完成了第一步。
第 2 步:定义环境变量
环境变量对于促进 WordPress 应用程序与数据库之间的通信是必需的。它们还可以确保应用程序数据得到持久化。环境变量包括敏感信息(如数据库凭据)和非敏感信息(如数据库名称和主机)。
出于安全考虑,最好不要将敏感信息添加到项目仓库中。因此,我们不在 Docker Compose 文件中设置这些敏感值,而是会在以下文件中定义 MySQL 凭据:.env 文件,这些文件不会被提交到项目仓库,并存在公开泄露的风险。在项目 根目录 ~/wordpress_docker 中,打开 .env 文件:
|
1 |
nano .env |
|
1 2 3 |
MYSQL_ROOT_PASSWORD=your_strong_root_password MYSQL_USER=your_wordpress_database_user MYSQL_PASSWORD=strong_wordpress_database_password |
接下来您必须做的是将 .env 文件添加到 .gitignore 和 .dockerignore 文件中,以确保它分别不会被添加到您的仓库或 Docker 镜像中。
这对于本教程来说不是必需的,但如果您想使用 Git 进行版本控制,请输入以下命令将当前目录初始化为 git 仓库:
|
1 |
git init |
打开 .gitignore,使用 nano:
|
1 |
nano .gitignore |
添加以下行:
|
1 |
.env |
保存并关闭文件。接下来,打开 .dockerignore,使用 nano:
|
1 |
nano .dockerignore |
添加以下行:
|
1 |
.env |
顺便,您也可以选择添加与应用程序开发相关的其他文件和目录:
|
1 2 3 |
.env .git docker-compose.yml |
完成后保存并关闭文件。这一步就完成了。让我们继续进行 Docker Compose 定义。
第 3 步:使用 Docker Compose 配置服务
Docker Compose 使用一个 docker-compose.yml 用于构建镜像的文件。该文件包含用于应用程序完整设置的服务定义。服务定义基本上是容器运行方式的指令。服务是一个实际运行的容器。
Docker Compose 通过将各种服务与共享网络和卷链接在一起,使得为多容器应用程序定义不同的服务成为可能。您将看到它的实际应用,因为我们将为我们的应用程序定义三个容器:Web 服务器、WordPress 安装和数据库。我们将添加第四个容器来运行用于证书续订的 Certbot 客户端。
输入以下命令以创建 docker-compose.yml 文件:
|
1 |
nano docker-compose.yml |
在 docker-compose.yml 文件中,第一行是 版本定义 行。我们已经为我们的设置了 3。然后,您可以开始定义您的服务。在文件中添加以下代码片段以定义 db 服务:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
version: '3' services: #MySQL 服务 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 |
让我们讨论一下下面 db 服务定义中的内容:
image: 决定了容器将基于的镜像。指定一个特定版本(mysql:8.0) 比使用 latest 标签(mysql:latest) 更好,因为未来版本的 MySQL 镜像 在我们重新构建此镜像时,可能会与我们的应用程序发生冲突。您可以在以下位置找到有关 官方 Dockerfile 文档中的 Dockerfile 最佳实践.container_name: 我们在此处指定容器名称。restart: 此指令决定了容器的重启行为。默认值为no但我们已将其设置为始终重启,除非手动停止。env_file: 此指令用于指定包含环境变量的文件(.env)的位置,这些变量由我们的应用程序使用。environment: 用于指定额外的环境变量。在本教程中,我们指定了MYSQL_DATABASE变量来保存我们应用程序的数据库名称。数据库名称可以包含在docker-compose.yml.volumes: 用于指定挂载位置。在我们的示例中,我们挂载了一个名为 数据卷(名为 dbdata)到容器的/var/lib/mysql目录,这通常是 MySQL 的标准数据目录。command: 此指令指定了一个将覆盖默认 CMD 指令 的命令。我们已在 Docker 镜像的标准mysqld命令中添加了一个选项,该命令用于在容器内启动 MySQL 服务器。我们添加的选项是--default-authentication-plugin=mysql_native_password,它将 MySQL 的默认身份验证插件更新为使用密码身份验证(mysql_native_password)。这对于您的 PHP(WordPress 应用程序正常工作)是必需的,因为它们使用用户名和密码来访问数据库。在较新的 MySQL 版本中,默认身份验证插件已更改。然而,大多数应用程序使用密码身份验证。因此,您必须更改此设置以使应用程序正常工作。networks: 此指令用于指定db服务应该加入app-network,我们将在接下来的教程中定义它。
接下来,让我们为 WordPress 应用程序定义服务配置。我们将服务和 container_name 命名为 app。在 db 服务定义下方添加以下代码片段,注意保持正确的缩进:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#WordPress 应用程序代码服务 app: depends_on: - db image: wordpress:5.1.1-fpm-alpine container_name: app 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: - app:/var/www/html networks: - app-network |
就像我们对 db 服务所做的一样,我们已经为容器命名并定义了重启策略。我们添加的其他一些选项定义如下:
depends_on: 该指令确保容器按依赖顺序启动。在我们的例子中,app容器依赖于db容器。因此,它将在db容器已启动。这需要按此顺序发生,因为 WordPress 应用程序依赖于 MySQL 数据库的可用性才能运行。镜像:如代码片段所示,我们将使用 WordPress 版本 5.1.1 fpm alpine 镜像。我们之前已经解释过php-fpm处理器,这是 Nginx 进行 PHP 处理所必需的。该镜像负责处理这一点。基于 Alpine Linux 项目 的 alpine 镜像有助于减小镜像大小。如果您需要有关镜像变体的更多信息,可以访问此链接以获取 Docker Hub Wordpress 镜像.env_file:指定.env包含数据库凭据的文件。environment: 此指令定义了额外的环境变量。在我们的案例中,我们定义了 WordPress 所期望的变量,并为其分配来自我们的.env文件的变量值。它们是WORDPRESS_DB_USER,WORDPRESS_DB_PASSWORD、以及WORDPRESS_DB_HOST,它指向运行在db容器上的 MySQL 服务器,可通过 MySQL 的默认端口3306进行访问。最后,您会看到WORDPRESS_DB_NAME,我们已将其设置为 WordPress。在 db 容器的 MySQL 服务定义中也指定了相同的值:MYSQL_DATABASE=wordpress.volumes: 此指令将名为 app 的数据卷挂载到/var/www/html挂载点,该挂载点由 WordPress 镜像 创建。数据卷的命名允许与其他容器共享应用程序代码。networks: 最后,我们将 app 容器添加到app-network,以确保它与网络上的其他容器进行通信。
以上就是关于 app 服务容器的全部内容。现在让我们为 Nginx 镜像定义 webserver 服务。首先,在您的 docker-compose.yml 文件中 app 服务定义下方添加以下代码片段:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#Webserver Nginx 服务 webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network |
我们已经解释了 depends_on 选项。对于此 webserver 服务,容器将在 app 容器启动后启动。Web 服务器容器基于 alpine Nginx 镜像。它具有与先前服务定义类似的重启策略。webserver 服务定义中的其他选项包括:
ports:绑定宿主机与容器之间的端口。在 步骤 1 中,我们定义了端口80,位于nginx.conf文件中。该端口被映射到容器的端口80。volumes:在此选项下,我们结合使用了 绑定挂载 和命名卷:app:/var/www/html: 此数据卷定义将 WordPress 应用程序挂载到/var/www/html目录,此前我们已在 Nginx 服务器块中将其设置为根目录。./nginx-conf:/etc/nginx/conf.d: 此定义将宿主机上的 Nginx 配置目录绑定挂载到我们为容器定义的 Nginx 配置目录。因此,宿主机上的任何更改都会自动反映到容器中。certbot-etc:/etc/letsencrypt: 此定义将该域名的 Let’s Encrypt 证书和密钥挂载到容器中的相应目录。
网络: 就像在之前的服务定义中一样,networks指令将 webserver 服务添加到app-networks.
既然我们已经完成了 webserver 的定义,让我们为 Certbot 服务添加指令。这将负责从 Let’s Encrypt 获取您的 TLS/SSL 证书。如果您想了解更多关于保护 Nginx 服务器的安全信息,这篇关于如何使用 Let’s Encrypt 保护 Nginx 的教程是一个很好的资源。
接下来,在 webserver 服务下方添加以下代码片段。请记住设置正确的域名和电子邮件地址:
|
1 2 3 4 5 6 7 8 9 10 |
#certbot 服务 certbot: depends_on: - webserver 镜像: certbot/certbot 容器名称: certbot 卷: - certbot-etc:/etc/letsencrypt - app:/var/www/html 命令: certonly --webroot --webroot-路径=/var/www/html --电子邮件 hackins@cloudsigma.com --同意-服务条款 --否-eff-电子邮件 --暂存 -d 示例.com -d www.example.com |
该 certbot 镜像只有在 webserver 启动后才会启动,因为有 depends_on 指令。Docker Compose 将拉取 Docker Hub 中的 Certbot 镜像,如定义所示。
在 volumes 定义下,Certbot 容器将共享 certbot-etc 中的域名证书和密钥,与 Nginx webserver 容器共享,并将应用程序代码与 app 容器共享。
在 command 定义下,我们指定了一个子命令来运行容器默认的 Certbot certonly 命令,并带有如下所示的附加选项:
-
--webroot: 指定使用 webroot 插件,该插件将文件放置在 webroot 文件夹中进行身份验证。--webroot-path: 指定 webroot 目录的路径。--agree-tos: 表示您同意 ACME 的服务条款.--no-eff-email: 指定您不想将电子邮件分享给 EFF。如果您想分享,可以省略此参数。--staging: 告诉 Certbot 您希望在获取实际证书之前,先从 Let’s Encrypt 的 staging 环境获取测试证书以测试您的配置。Let’s Encrypt 设有 域名请求速率限制。因此,先测试您的配置将有助于避免您的域名受到限制。-d:此选项用于接收证书请求的域名。在本教程中,我们已包含example.com和www.example.com。请指定您实际注册的域名。
我们的 docker-compose.yml 文件已基本完成。但是,您还必须在 Certbot 服务下方添加网络和数据卷定义:
|
1 2 3 4 5 6 7 8 9 10 |
#数据卷 volumes: certbot-etc: app: dbdata: #网络 networks: app-network: driver: bridge |
该 volumes 键定义了要与此 compose 文件中定义的所有服务(容器)共享的数据卷:certbot-etc, app, 以及 dbdata。Docker 创建的数据卷的内容存储在宿主机文件系统上由 Docker 管理的目录中:/var/lib/docker/volumes/。然后,每个数据卷的内容会被挂载到任何使用该数据卷的容器中。这使得在容器之间共享数据和代码成为可能。
The networks 键定义了允许容器之间进行通信的桥接网络。在同一个桥接网络上的容器,例如 webserver 和 db 可以通过端口进行安全通信,而无需将流量暴露给外部网络。我们只暴露端口 80 以允许访问前端网站页面。
完整的 docker-compose.yml 文件将如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
version: '3' services: #MySQL 服务 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 应用程序代码服务 app: depends_on: - db image: wordpress:5.1.1-fpm-alpine container_name: app 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: - app:/var/www/html networks: - app-network #Webserver Nginx 服务 webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network #certbot 服务 certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --staging -d example.com -d www.example.com #数据卷 volumes: certbot-etc: app: dbdata: #网络 networks: app-network: driver: bridge |
您可以保存并关闭该文件。在下一步中,我们将启动并测试容器和证书请求。
步骤 4:运行容器并获取 SSL 证书
Docker Compose 的最大优势在于,一旦您在 docker-compose.yml 文件中定义了所有服务,您只需运行一个命令即可启动所有容器:docker-compose up。该命令会运行指定的每条指令。如果域名请求成功,您应该能在终端中看到正确的退出状态。输入以下命令以创建容器。其中 -d 参数用于在后台运行容器:
|
1 |
docker-compose up -d |
如果您看到类似下方截图中的输出,则说明服务已成功创建:
要确认服务状态,请运行 docker-compose ps 命令:
|
1 |
docker-compose ps |
如果一切成功,该命令的输出如下所示。app, db,以及 webserver 容器的状态应该为 up,并且 certbot 容器应该具有 Exit0 状态:
如果您看到除 Up 以外的状态,在状态列中,对于 app、 db 或 webserver, 或者 Exit 状态不是 0,对于 certbot 容器,那么就出了一些问题。您可以使用以下命令检查每个容器的日志 docker-compose logs,并指定 service_name:
|
1 |
docker-compose logs service_name |
例如,您可以检查 certbot 容器的日志,方法是输入以下命令:
|
1 |
docker-compose logs certbot |
要检查证书是否已挂载到 webserver 容器,请使用 docker-compose exec 命令:
|
1 |
docker-compose exec webserver ls -la /etc/letsencrypt/live |
如果您使用了除 example.com 之外的实际注册域名,且证书请求成功,您应该会看到类似于以下的输出:
确认证书请求成功后,您可以编辑 docker-compose.yml 文件并移除 --staging 标志。使用 nano:
|
1 |
nano docker-compose.yml |
向下滚动到 Certbot 服务定义部分,在 command 选项中,将 --staging 标志替换为 --force-renewal 标志。这告诉 Certbot 您正在请求为相同域名的证书进行续期。您的 Certbot 服务定义现在应该如下所示:
|
1 2 3 4 5 6 7 8 9 10 |
#certbot 服务 certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com |
编辑完成后保存文件。
输入以下命令以重新创建 certbot 容器。其中包含的 --no-deps 标志会指示 Compose 跳过重启 Web 服务器服务,因为它已经在运行:
|
1 |
docker-compose up --force-recreate --no-deps Certbot |
该命令输出以下屏幕截图,显示证书请求已成功:
本步骤到此结束。在下一步中,您将修改 Nginx 配置文件以包含 SSL 证书。
第 5 步:在 Nginx 配置和服务定义中启用 SSL
为了让 Nginx 通过安全的 SSL 提供流量服务,您首先需要修改 Nginx 配置文件以添加 HTTP 重定向到 HTTPS。然后,您需要指定证书和密钥的位置,最后添加安全参数和标头。
在修改配置文件之前,您应该获取 推荐的 Nginx 安全参数,从 Certbot 的 GitHub 仓库,使用 curl,通过以下命令:
|
1 |
curl -sSLo nginx-conf/options-ssl-nginx.conf |
该命令运行并将拉取的参数保存到名为 options-ssl-nginx.conf 的文件中,位于 nginx-conf 目录下。删除 Nginx 配置文件,以便我们可以使用以下命令创建一个新文件:
|
1 2 |
rm nginx-conf/nginx.conf nano nginx-conf/nginx.conf |
在当前为空的 nginx.conf 文件中,添加以下代码,其中包括从 HTTP 到 HTTPS, SSL 凭据协议以及安全标头。正如您之前所做的那样,将 example.com 域名替换为您自己注册的域名:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
服务器 { 监听 80; 监听 [::]:80; 服务器名称 示例.com www.示例.com; 位置 ~ /.良好-已知/acme-挑战 { 允许 所有; 根 /var/www/html; } 位置 / { 重写 ^ https://$host$request_uri? permanent; } } 服务器 { 监听 443 ssl http2; 监听 [::]:443 ssl http2; server_name example.com www.example.com; index index.php index.html index.htm; root /var/www/html; server_tokens off; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.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-安全-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; # 仅在您了解其影响时启用严格传输安全 location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app: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 关闭; } } |
在第一个处理使用端口 80 的非安全请求的 server 块中,我们指定了用于 Certbot 续期请求的 webroot。我们还包含了一个 重定向指令,用于将 HTTP 请求重定向至 HTTPS.
第二个 server 块处理安全的 HTTPS 流量,该流量来自端口 443。如您所见,我们还启用了 SSL 和 HTTP2。HTTP/2 提高了服务器的性能。您可以从 官方的 Nginx HTTP/2 文档中了解更多信息.
在此块中,我们还指定了 Nginx 包含 SSL 证书和密钥位置,以及推荐的 Certbot 安全参数,这些参数由 curl 保存到 nginx-conf/options-ssl-nginx.conf 目录中。
这些额外的安全标头有助于提高您的网站在安全测试网站上的评分,例如 Security Headers 和 SSL Labs。您可以点击这些标头上的链接以了解更多信息:X-Frame-Options, Referrer Policy, X-Content-Type-Options, X-XSS-Protection, Content-Security-Policy。我们已经注释掉了 HTTP Strict Transport Security (HSTS) 响应头。您可以自由阅读关于其 预加载功能 并决定是否要启用它。
其余的指令,例如 root, index, WordPress 特定的 location 块仍如中所述 步骤 1。编辑完成后,您现在可以保存并关闭该文件。
现在我们已经启用了 HTTPS 使用端口的流量,443, 我们还必须在 Web 服务器的服务定义中启用该端口。输入以下命令以打开 docker-compose.yml 文件,使用 nano:
|
1 |
nano docker-compose.yml |
在 web 服务器部分的 ports 选项下,为端口 443 添加映射,如下面高亮显示所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" - "443:443" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt 网络: - 应用-网络 |
完整的 docker-compose.yml 文件现在应该像这样:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
版本: '3' 服务: #MySQL 服务 db: 镜像: mysql:8.0 容器名称: db 重启: 除非-已停止 环境文件: .env 环境: - MYSQL_DATABASE=wordpress 数据卷: - dbdata:/var/lib/mysql 命令: '--default-authentication-plugin=mysql_native_password' 网络: - app-网络 #WordPress 应用程序代码服务 app: 依赖于: - db 镜像: wordpress:5.1.1-fpm-alpine 容器名称: app 重启: 除非-已停止 环境文件: .env 环境: - WORDPRESS_DB_HOST=db:3306 - WORDPRESS_DB_USER=$MYSQL_USER - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD - WORDPRESS_DB_NAME=wordpress volumes: - app:/var/www/html networks: - app-network #Webserver Nginx 服务 webserver: depends_on: - app image: nginx:1.15.12-alpine container_name: webserver restart: unless-stopped ports: - "80:80" - "443:443" volumes: - app:/var/www/html - ./nginx-conf:/etc/nginx/conf.d - certbot-etc:/etc/letsencrypt networks: - app-network #certbot 服务 certbot: depends_on: - webserver image: certbot/certbot container_name: certbot volumes: - certbot-etc:/etc/letsencrypt - app:/var/www/html command: certonly --webroot --webroot-path=/var/www/html --email hackins@cloudsigma.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com #数据卷 volumes: certbot-etc: app: dbdata: #网络 networks: app-network: driver: bridge |
确认一切无误后,保存并关闭文件。之后,运行以下命令重新创建 webserver 服务:
|
1 |
docker-compose up -d --force-recreate --no-deps webserver |
|
1 |
docker-compose ps |
现在所有容器都在运行,可以从 Web 界面继续进行 WordPress 配置了。
步骤 6:通过 Web 界面完成您的 WordPress 配置
导航到您服务器的域名以继续安装。您应该会看到 WordPress 设置主页。它会欢迎您在继续之前选择语言:
选择您的语言并点击 继续 以进入下一页:
在此页面上,填写您的网站标题,选择一个好记的用户名和强密码。出于安全原因,建议不要使用 Admin 作为您的用户名。输入您的电子邮件,然后点击 安装 WordPress 按钮开始安装 WordPress。
安装完成后,您将被带到登录屏幕,在此您将提供您设置的用户名和密码。当您输入有效的凭据时,您应该能够看到您的 WordPress 仪表盘:
您现在已成功安装 WordPress!接下来,您需要采取步骤以确保 SSL 证书将自动续期。
步骤 7:配置自动 SSL 证书续期
Let’s Encrypt TLS/SSL 证书的有效期仅为 90 天。您需要自行创建自动续期配置以确保它们不会过期。您可以通过创建一个脚本并使用 cron 任务 工具来定时运行它。在这一步中,我们将向您展示如何创建一个用于续期证书的脚本。然后,我们将使用 cron 任务工具来定时运行它,并在证书临近过期时进行续期。
在 wordpress_docker 项目目录中,打开一个名为 ssl_renewer.sh 的脚本,使用 nano:
|
1 |
nano ssl_renewer.sh |
将以下代码添加到脚本中,以处理自动续订和 Nginx 配置重新加载。请记住将突出显示的用户名替换为您的非 root 用户名:
|
1 2 3 4 5 6 7 8 |
#!/bin/bash COMPOSE="/usr/local/bin/docker-compose –ansi never" DOCKER="/usr/bin/docker" cd /home/hackins/wordpress_docker/ $COMPOSE run certbot renew --dry-run && $COMPOSE kill -s SIGHUP webserver $DOCKER system prune -af |
在此脚本中,我们将 docker-compose 二进制文件分配给名为 COMPOSE 的变量。我们还包含了 –ansi never 选项,该选项指示脚本运行 docker-compose 命令,而不带 ANSI 控制 字符。我们还将 Docker 二进制文件分配给名为 DOCKER.
。然后,脚本进入我们的项目目录 wordpress_docker 并执行以下命令:
docker-compose run: 它启动 certbot 容器并覆盖我们在 certbot 服务定义中提供的命令。它不运行 certonly 子命令,而是运行 renew 子命令,如果 Let’s Encrypt 的 SSL/TLS 证书即将过期,该子命令将更新这些证书。docker-compose kill: 发送一个 SIGHUP 信号给webserver容器以重新加载 Nginx 配置。您可能想查看 Docker 的这篇关于 如何 使用官方 Nginx Docker 镜像.docker system prune: 此命令将删除所有未使用的容器和镜像。
编辑完成后保存并关闭文件。然后,运行以下命令使其可执行:
|
1 |
chmod +x ssl_renewer.sh |
将其设置为可执行文件后,打开您的 root crontab 文件,以便按照我们将指定的间隔定期运行该脚本:
|
1 |
sudo crontab -e |
该 crontab 在您第一次使用时会要求您选择首选的编辑器:
选择您首选的编辑器并按 Enter 键以打开文件。在文件底部,添加以下行:
|
1 |
*/5 * * * * /home/hackins/wordpress_docker/ssl_renewer.sh >> /var/log/cron_docker.log 2>&1 |
这将时间间隔设置为五分钟,以便我们测试续期脚本是否能正常工作。我们还指定了一个日志文件来保存该任务的输出:cron_docker.log.
等待五分钟并检查 cron.log,以查看脚本的续期请求是否成功:
|
1 |
tail -f /var/log/cron_docker.log |
如果请求成功,您应该会看到类似于以下屏幕截图的内容:
现在我们已经测试并确认其正常工作,您可以修改 crontab 文件来指定每日更新。例如,您可能希望指定脚本在每天下午 6 点运行。为此,请修改 crontab 的最后一行,使其看起来像这样:
|
1 |
0 18 * * * /home/hackins/wordpress_docker/ssl_renewer.sh >> /var/log/cron_docker.log 2>&1 |
此外,您需要移除 –dry-run 标志,从 ssl_renewer.sh 脚本,用于确保在运行时实际执行续期。它应该像这样:
|
1 2 3 4 5 6 7 8 |
#!/bin/bash COMPOSE="/usr/local/bin/docker-compose --ansi never" DOCKER="/usr/bin/docker" cd /home/hackins/wordpress_docker/ $COMPOSE run certbot renew && $COMPOSE kill -s SIGHUP webserver $DOCKER system prune -af |
接下来,保存并关闭文件。完成此操作后,cron 任务将通过在 90 天结束前更新它们来保持您的脚本有效。
结论
如果您已经阅读到本教程的这一步,您可以认为自己距离成为一名 DevOps 工程师又近了一步。您成功创建了一个 Nginx 配置脚本,并创建了一个 docker-compose.yml 文件,并定义了使用 Docker 和 Docker Compose 运行 WordPress 应用程序所需的几个服务。您从 Let’s Encrypt 获取了 SSL/TLS 证书,以确保您的 Web 服务器安全。最后,您创建了一个 cron 任务以确保证书不会过期。做得好!
如果您想深入了解 DevOps,请查看更多关于容器的资源,来自 我们的博客:
- 了解 Kubernetes
- 如何在 Ubuntu 20.04 上使用 Docker 部署 Node.js (Express.js) 应用
- 在带有 Ubuntu 18.04 的 Kubernetes 集群上部署 PHP 应用程序。
- 使用 Docker Compose 部署 Laravel、Nginx 和 MySQL
祝计算愉快!










评论
暂无评论。发表第一条评论吧。