域名注册与云服务器项目部署
Auth: LIU Yilin
概述
本篇文档旨在指导读者如何构建一个完整的后端网络架构,实现至少 2 个NestJS服务在同一个云服务器实例中运行,并能通过域名实现 HTTPS 访问。涉及的技术和服务包括域名注册、CDN、云服务器、Docker、反向代理等。具体内容如下:
- 域名注册:使用 Namecheap 注册域名
- CDN 和 SSL/TLS 证书:使用 Cloudflare 提供的 CDN 服务和免费 SSL/TLS 证书
- 云服务器:使用 Amazon Lightsail 作为云服务器提供商
- Docker:使用 Docker 容器化应用并将镜像存储在 Docker Hub
- 反向代理:使用 Nginx 作为反向代理服务器以实现负载均衡和 SSL/TLS 证书配置
为顺利完成本篇文档,读者需要掌握以下背景知识:
- 基本的网络概念,如 DNS、HTTP/HTTPS、域名和 IP 地址等
- 基本的 Linux 命令行操作
- 了解 Docker 及其基本操作
- 了解 Nginx 及其配置方法
- 了解 NestJS 框架的基本知识
1. 域名注册
在本段中,我们使用 Namecheap 作为域名注册提供商。要注册一个域名,请按照以下步骤操作:
访问 Namecheap 官网:https://www.namecheap.com/
在首页的搜索框中输入您想要注册的域名,然后点击搜索图标或按 Enter 键。
如果您选择的域名可用,将看到“添加到购物车”的按钮。点击此按钮将域名添加到购物车。
之后点击购物车图标,然后点击“Checkout”按钮进入结算页面。
在结算页面,输入您的支付信息,确认订单详情,并同意相关条款。特别注意的是,可以不选择自动续约,同时也不需要勾选相应的 SSL/TLS,CDN 等增值服务,这些我们在后面会采用其他的方案。完成支付后,您将拥有所选域名的使用权。
在完成购买后,登录 Namecheap 帐户。在“域名列表”或“域名管理”页面中,您将看到您刚注册的域名。后续,我们将需要在这里对域名进行配置。
2. 将域名绑定至 Cloudflare
在本段中,我们将通过以下步骤将已注册的域名绑定到 Cloudflare,从而利用 Cloudflare 提供的 CDN 和免费 SSL/TLS 证书服务。
访问 Cloudflare 官网并注册一个帐户(如果尚未注册):https://www.cloudflare.com/
登录 Cloudflare 帐户后,点击右上角的“+ 添加站点”按钮。
输入您在 Namecheap 注册的域名,然后点击“添加站点”按钮。
大部分情况下选择免费套餐即可满足需求,然后点击“确认计划”按钮。
Cloudflare 将扫描您的域名 DNS 记录。扫描完成后,点击“继续”按钮。
将 Cloudflare 提供的两个 DNS 名称服务器记录复制下来。稍后,我们需要将这些记录添加到 Namecheap 的域名配置中。
回到 Namecheap 帐户,进入之前注册的域名的管理页面。找到“域名服务器”或“Name Servers”部分,选择“自定义”或“Custom”。将刚刚从 Cloudflare 复制的两个 DNS 名称服务器记录分别填入,然后点击“保存”或“Save”。
返回 Cloudflare,点击“完成”按钮。此时,Cloudflare 可能需要几分钟到几小时来检测 DNS 更改。当检测到更改并成功激活后,您将看到 Cloudflare 上的域名状态显示为“活动”。记得关掉这些 AUTO-RENEW,避免多年后忽然信用卡被扣费。
现在,您已成功将域名绑定至 Cloudflare,并可以使用其 CDN 和 SSL/TLS 证书服务。
3. 创建并配置 Lightsail 实例环境
在本段中,我们将创建 Amazon Lightsail 实例并配置环境,安装 Docker 并准备部署我们的应用。以下是详细步骤:
3.1 创建 Lightsail 实例
访问 Amazon Lightsail 官网并登录(如果您还没有 AWS 帐户,请先注册一个):https://aws.amazon.com/lightsail/
在 AWS Management Console 中,找到“Lightsail”服务,进入 Lightsail 主页面。
点击“创建实例”按钮。
选择实例位置。建议选择离目标用户最近的区域以获得较低的延迟。
选择实例平台。在本文中,我们选择“Linux/Unix”。
选择实例镜像。我们推荐使用“Amazon Linux 2”,因为它是一个经过优化且易于管理的 Linux 发行版。使用 Ubuntu 也是一个不错的选择。
选择实例计划。根据您的需求和预算选择合适的计划。对于个人应用或者测试少部分项目,例如测试 API,使用 5 美元的套餐即可。
为实例命名。输入一个便于识别的实例名称,以便后续管理。
点击“创建实例”按钮。创建过程可能需要几分钟。完成后,您将在 Lightsail 主页面看到新创建的实例。
3.2 配置 Lightsail 实例环境
在本段中,我们将配置 Amazon Lightsail 实例环境,安装 Docker 并准备部署我们的应用。以下是详细步骤:
在 Lightsail 主页面上,点击刚刚创建的实例。
点击“连接”按钮,以通过网页终端连接到实例。您也可以使用 SSH 客户端连接到实例,但需要先下载实例的私钥并进行适当的配置。
点击 connect 栏,下拉,点击 Download default key,这时你会得到连接服务器的秘钥
在终端中进入当前文件夹下,我们通过以下命令通过 SSH 连接服务器
ssh -i LightsailDefaultKey-ap-northeast-2.pem ec2-user@3.39.224.60
过程中输入 yes,连接成功
首次登录时,您的用户名为
ec2-user
。Amazon Linux 2 与传统的 Ubuntu 发行版不同,Amazon Linux 2 使用ec2-user
作为默认用户名,而 Ubuntu 通常使用ubuntu
作为默认用户名。更新实例的软件包。在Amazon Linux 2上,可以使用以下命令:
sudo yum update -y
在传统的Ubuntu发行版上,相应的命令是:
sudo apt-get update && sudo apt-get upgrade -y
安装 Docker。在Amazon Linux 2上,运行以下命令:
sudo amazon-linux-extras install docker -y
在传统的Ubuntu发行版上,安装 Docker 的命令可能会有所不同:
sudo apt-get install -y docker.io
启动 Docker 服务并设置为开机自启动。在Amazon Linux 2上,使用以下命令:
sudo systemctl enable docker
sudo systemctl start docker在传统的Ubuntu发行版上,相应的命令是:
sudo systemctl enable docker
sudo systemctl start docker将当前用户添加到 Docker 组,以允许在未提供
sudo
前缀的情况下运行 Docker 命令。在Amazon Linux 2上,使用以下命令:sudo usermod -aG docker ec2-user
在传统的Ubuntu发行版上,相应的命令是:
sudo usermod -aG docker ubuntu
完成此操作后,您需要断开并重新连接到实例,以便用户组更改生效。
现在,您已成功配置了 Amazon Lightsail 实例环境,并安装了 Docker。在接下来的部分,我们将使用 Docker 部署应用程序到这个实例。
Nginx 暂时先不需要安装
3.4 将 Cloudflare 域名绑定到 Lightsail IP
登录到 Cloudflare 帐户,并选择您刚刚添加的域名。
点击页面顶部的 "DNS" 标签。
确保您已删除所有现有的 A 记录(如果有的话)。然后,点击 "Add Record"(添加记录)按钮创建一个新的 A 记录。
选择记录类型为 "A",在 "Name" 字段中输入
@
,以表示这是针对主域名的记录(例如:example.com
)。在 "IPv4 address" 字段中输入您的 Amazon Lightsail 实例的公共 IP 地址。配置其他选项,然后点击 "Save"(保存)。同样,您可以为其他子域(如
www
)创建一个新的 A 记录,将其指向相同的 IP 地址。DNS 更改可能需要一些时间生效,通常在几分钟到几小时之间。在此期间,您可以继续配置 Lightsail 实例和应用程序。
完成这些步骤后,您的 Cloudflare 域名将成功绑定到 Amazon Lightsail 实例的 IP 地址,显示如下:
4. 镜像打包、上传和部署并简单测试
在本段中,我们将演示如何在本地打包 Docker 镜像,将其上传到 Docker Hub,并在 Lightsail 实例上部署并进行简单测试。以下是详细步骤:
4.1 本地打包 Docker 镜像
确保您已安装了 Docker。
下载地址:https://docs.docker.com/desktop/install/windows-install/
对于 Apple Silicon Mac 用户,您需要安装适用于 Apple Silicon 的 Docker Desktop:https://docs.docker.com/docker-for-mac/apple-silicon/
创建一个名为
Dockerfile
的文件(无文件扩展名)并将其放置在项目根目录中。在这个文件中,您将定义构建镜像所需的所有指令。以下是一个简单的示例,这是第一个 NestJS 容器的镜像,先采用 3000 端口,第二个需要用 3001 端口,避免冲突。值得注意的是,如果包管理器是 npm,需要将 pnpm 改成 npmFROM node:18
RUN npm install -g pnpm
RUN mkdir -p /app
WORKDIR /app
COPY package.json .
RUN pnpm install
COPY . .
RUN pnpm build
EXPOSE 3000
CMD [ "pnpm", "start" ]由于您使用的是 Apple Silicon Mac,您需要为目标平台指定 x86 架构。在终端中,导航到项目根目录,然后运行以下命令:
docker buildx build --platform linux/amd64 -t your_dockerhub_username/your_image_name:tag_name .
对于传统的 x86 架构计算机,您只需运行:
docker build -t your_dockerhub_username/your_image_name:tag_name .
注意:请替换
your_dockerhub_username
、your_image_name
和tag_name
为您实际的 Docker Hub 用户名、镜像名称和标签。一定要严格按照该命名规范来命名镜像,不然接下来无法上传镜像到 Docker Hub。注意:请替换
your_dockerhub_username
、your_image_name
和tag_name
为您实际的 Docker Hub 用户名、镜像名称和标签。
4.2 上传镜像到 Docker Hub
在 4.2 开始之前,让我们简要了解一下 Docker Hub 及其特性。Docker Hub 是一个用于分享和管理 Docker 镜像的公共仓库。它允许开发者创建和存储自己的镜像,并可以将这些镜像与他人共享。Docker Hub 提供了一个中心化的资源库,使开发者能够轻松地发布和部署容器化的应用程序。Docker Hub 提供免费的公共仓库,以及付费的私有仓库,以满足不同用户的需求。通过将镜像托管在 Docker Hub 上,您可以简化应用程序的部署过程,无论是在本地还是在云服务器上。如果您还没有 Docker Hub 帐户,请注册一个:https://hub.docker.com/
在终端中,登录到 Docker Hub:
docker login
输入您的 Docker Hub 用户名和密码。
将本地镜像推送到 Docker Hub:
docker push your_dockerhub_username/your_image_name:tag_name
如图所示,镜像为 dianapgrande/server-management-system:
4.3 在 Lightsail 实例上部署并简单测试
连接到 Lightsail 实例。您可以使用之前的网页终端连接,或使用 SSH 客户端连接到实例。
拉取 Docker 镜像:
docker pull your_dockerhub_username/your_image_name:tag_name
注意:请替换
your_dockerhub_username
、your_image_name
和tag_name
为您实际的 Docker Hub 用户名、镜像名称和标签。运行容器:
docker run -d --name your_container_name -p 3000:3000 your_dockerhub_username/your_image_name:tag_name
注意:请替换
your_container_name
。在这行代码中,-d
表示容器运行后在后台运行,其运行的日志,不会在现有的实例的界面打印出来。-p
表示端口映射,左侧是宿主机端口,右侧是容器端口。3000 端口用于访问容器内 NestJS 的服务。因为目前没有配置 SSL/TLS 证书,我们是直接通过 IP 地址访问实例中的服务。通过 Postman 进行测试。
注意:URL 中要加上 3000 端口才能正常访问 NestJS 服务的 API。
5. SSL/TLS 证书创建并配置 Nginx 等
在本段中,我们将使用 Cloudflare 创建 SSL/TLS 证书,并配置 Nginx 以将请求代理到适当的 NestJS 项目。同时,我们将部署第二个 NestJS 项目并确保它在正确的路径下可用。
5.1 创建 SSL/TLS 证书
登录到 Cloudflare 帐户,选择您的域名。
点击"SSL/TLS"选项卡。
在"Overview"下,将 SSL/TLS 加密模式设置为"Full (strict)"。
转到"Origin Server"部分,点击"Create Certificate"按钮。
在"Certificate"对话框中,使用默认设置(RSA 私钥类型,有效期为 15 年),然后点击"Next"。
将显示生成的证书及私钥。复制到文件并保存在 Lightsail 实例中(例如,
cert.pem
和key.pem
)。在本文档,具体放置位置如下:/etc/ssl/certs/dianapgrande.com.pem;
和/etc/ssl/private/dianapgrande.com.key;
5.2 更新 NestJS 项目路由前缀
为了使两个 NestJS 项目能够正确地通过预定的 URL 访问,需要在每个项目中更新路由前缀。对于每个项目,请按照以下步骤操作:
在
src/main.ts
文件中,在app.listen()
之前,添加以下代码,用适当的路径替换your_route_prefix
:app.setGlobalPrefix("your_route_prefix");
例如对于第一个项目,
your_route_prefix
应为server-management-system
,对于第二个项目,your_route_prefix
应为new-york-city-taxi-trip
。确保在每个项目中保存更改并重新构建 Docker 镜像,然后按照第 4 部分的步骤将新的镜像上传到 Docker Hub。
在 Lightsail 实例上,停止并删除现有的容器,然后使用更新后的镜像重新运行它们。
docker stop your_container_name
docker rm your_container_name
docker run -d --name your_container_name -p 3000:3000 your_dockerhub_username/your_image_name:updated_tag_name对于第二个项目,将端口映射和容器名称更改为适当的值,即 3001。
(OPTIONAL)上文中提到了更新 NestJS 项目路由前缀的方法。这是为了确保项目可以通过指定的子路径访问。在大多数情况下,这应该足够使项目正确运行。但是,还有一些可能需要考虑的额外修改:
- 静态资源访问:如果您的项目包含静态资源(如图像、CSS 或 JavaScript 文件),请确保它们的路径正确。通常,您需要在静态资源的路径前添加相应的子路径。您可以在 NestJS 的
StaticModule
中配置这些路径。 - 跨域资源共享(CORS):如果您的项目涉及跨域请求,例如从不同的域访问 API,您可能需要更新 CORS 设置。确保您允许的域名和路径与新的子路径相匹配。在 NestJS 中,您可以在创建
AppModule
时使用enableCors
方法配置 CORS 设置。 - API 客户端:如果您的项目有前端应用程序或其他客户端使用 API,确保这些客户端也更新为使用新的子路径。这可能包括更新 API 请求的 URL 和处理跨域请求(如上所述)。
- 第三方服务和库:如果您使用了第三方服务或库(如身份验证、日志或分析服务),请确保这些服务的配置已更新,以反映新的子路径。
这些额外修改可能因项目而异,具体取决于项目使用的功能和技术。请仔细审查项目以确保所有相关路径和设置已正确更新。
- 静态资源访问:如果您的项目包含静态资源(如图像、CSS 或 JavaScript 文件),请确保它们的路径正确。通常,您需要在静态资源的路径前添加相应的子路径。您可以在 NestJS 的
5.3 部署第二个 NestJS 项目
按照第 4 部分的步骤将第二个 NestJS 项目的 Docker 镜像打包并上传到 Docker Hub。
在 Lightsail 实例上,拉取第二个项目的镜像并运行容器,将端口映射到 3001:
docker run -d --name your_second_container_name -p 3001:3001 your_dockerhub_username/your_second_image_name:tag_name
5.2 配置 Nginx
将
cert.pem
和key.pem
文件上传到 Lightsail 实例的/etc/nginx/ssl/
目录(如果不存在,请创建此目录)。您可以使用 SCP 或 SFTP 将文件上传到实例。在
/etc/nginx/conf.d
目录下创建一个新的配置文件,例如your_domain.conf
。将以下内容添加到此文件:server {
listen 80;
server_name dianapgrande.com www.dianapgrande.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name dianapgrande.com www.dianapgrande.com;
# SSL 证书和密钥文件的路径
ssl_certificate /etc/ssl/certs/dianapgrande.com.pem;
ssl_certificate_key /etc/ssl/private/dianapgrande.com.key;
# 推荐的 SSL 设置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
location /new-york-city-taxi-trip {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
location /server-management-system {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}注意:
这个文件将配置 Nginx 以侦听 HTTP 和 HTTPS 请求。HTTP 请求将被重定向到 HTTPS。同时,基于请求路径,Nginx 将请求代理到不同的 NestJS 项目。
将该配置文件放在
/etc/nginx/conf.d
目录下是一种更好的设计模式,因为它可以更轻松地扩展以添加更多的项目。每个项目可以有其自己的配置文件,这使得管理和更新配置变得更加简单。对于未来的项目,只需在/etc/nginx/conf.d
目录下创建新的配置文件,或者在同一个文件中location
块添加内容即可。
特别补充:
在Ubuntu系统上,
/etc/nginx/conf.d
目录的使用方式与Amazon Linux 2略有不同。在 Ubuntu 上,主要的差别可能在于 Nginx 的安装和启动方式。在 Ubuntu 中,您可以使用apt
软件包管理器安装 Nginx,而在Amazon Linux 2中,您需要使用yum
或dnf
。- 在Ubuntu上启动 Nginx,您需要使用
systemctl
命令:sudo systemctl restart nginx
, - 在Amazon Linux 2上启动 Nginx,您需要使用
service
命令:sudo service nginx restart
。
在Amazon Linux 2中,默认情况下,Nginx 已经包含了一个指向
/etc/nginx/conf.d
目录的链接,所以无需手动创建链接。在其他系统(如Ubuntu)中,如果需要链接
conf.d
目录到 Nginx 的主配置文件,可以在/etc/nginx/nginx.conf
文件的http
块中添加以下内容:include /etc/nginx/conf.d/*.conf;
- 在Ubuntu上启动 Nginx,您需要使用
在完成配置文件的编辑后,请检查 Nginx 配置文件的语法正确性。在命令行中执行以下命令:
sudo nginx -t
如果配置文件语法正确,您将看到类似以下的输出:
nginx: configuration file /etc/nginx/nginx.conf test is successful
如果发现任何语法错误,请根据提示进行修正。
最后,有两种方法以应用新的配置。
重新启动 Nginx 服务。这将导致 Nginx 进程完全停止并重新启动。这种方法在应用配置更改时非常有效,但可能会导致在重启过程中短暂的服务中断。
在 Amazon Linux 2 上,执行以下命令:
sudo service nginx restart
在 Ubuntu 上,执行以下命令:
sudo systemctl restart nginx
重新加载 Nginx 配置而不中断正在运行的进程。在重新加载配置时,Nginx 服务不会停止,客户端不会遇到连接中断。这是一种平滑更新配置的方法,适用于在生产环境中避免服务中断的情况。是一个更优雅的方法来应用 Nginx 配置更改,因为它在重新加载配置时不会导致服务中断。在 Amazon Linux 2 和 Ubuntu 系统中,可以直接使用此命令。
在 Amazon Linux 2 和 Ubuntu 上,命令完全相同:
sudo nginx -s reload
现在,您应该能够通过该 URL 访问第一个 NestJS 项目:
https://dianapgrande.com/server-management-system/
通过该 URL 访问第二个 NestJS 项目:
6. 最终测试
成功访问: