作者选择International Medical Corps接受捐赠,作为Write for DOnations计划的一部分。
介绍
持续集成/持续部署 (CI/CD)是一种开发实践,它允许软件团队在多个平台上更轻松、更快速地构建、测试和部署应用程序。CircleCI是一个流行的自动化平台,允许您为您的项目构建和维护 CI/CD 工作流。
持续部署在很多方面都是有益的。它有助于标准化应用程序的部署步骤并保护它免受未记录的更改的影响。它还有助于避免执行重复步骤,让您更专注于开发。使用 CircleCI,您可以在开发、测试和生产的所有不同部署过程中拥有单一视图。
在本教程中,您将在本地构建一个Node.js应用程序并将其推送到GitHub。之后,您将配置 CircleCI 以连接到运行Ubuntu 18.04的虚拟专用服务器 (VPS),您将完成设置代码以在 VPS 上自动部署的步骤。到本文结束时,您将拥有一个有效的 CI/CD 管道,CircleCI 将在其中挑选您从本地环境推送到 GitHub 存储库的任何代码,并将其部署到您的 VPS 上。
先决条件
在开始之前,您需要具备以下条件:
- 一个 GitHub 帐户,您可以在GitHub 网站上创建。
- 按照 Ubuntu 18.04初始服务器设置教程设置一台 Ubuntu 18.04 服务器,包括 sudo 非 root 用户和防火墙。
- CircleCI 帐户,您可以在CircleCI 网站上创建。
- 了解git 版本控制的基础知识会很有帮助。您可以使用How To Create a Pull Request on GitHub和Introduction to Git: Installation, Usage, and Branches来学习基础知识。
- 在本地环境和远程服务器上,您都需要一个运行Node.js的开发环境;本教程在 Node.js 版本 10.22.0 和 npm 版本 6.14.6 上进行了测试。要在 macOS 或 Ubuntu 18.04 上安装它,请按照如何在 macOS 上安装 Node.js 和创建本地开发环境或如何在 Ubuntu 18.04 上安装 Node.js 的使用 PPA 安装部分中的步骤进行操作。
步骤 1 — 创建本地节点项目
在此步骤中,您将在本地创建一个 Node.js 项目,您将在本教程中将其用作示例应用程序。您稍后会将其推送到 GitHub 上的存储库。
继续在本地终端上运行这些命令,以便您可以设置快速的 Node 开发环境。
首先,为测试项目创建一个目录:
- mkdir circleci-test
切换到新目录:
- cd circleci-test
通过初始化npm环境来执行此操作以拉取依赖项(如果有)。该-y
标志将自动接受抛出的每个提示npm init
:
- npm init -y
有关 的更多信息npm
,请查看我们的如何使用带有 npm 和 package.json 的 Node.js 模块教程。
接下来,创建一个基本服务器,Hello World!
在有人访问任何路由时提供服务。使用文本编辑器,app.js
在项目的根目录中创建一个名为的文件。本教程将使用nano:
- nano app.js
将以下代码添加到app.js
文件中:
const http = require('http');
http.createServer(function (req, res) {
res.write('Hello World!');
res.end();
}).listen(8080, '0.0.0.0');
此示例服务器使用该http
包来侦听端口上的任何传入请求,8080
并触发一个请求侦听器函数,该函数以字符串 进行 回复Hello World
。
保存并关闭文件。
您可以通过在终端的同一目录中运行以下命令在本地计算机上进行测试。这将创建一个运行服务器的 Node 进程 ( app.js
):
- node app.js
现在访问http://localhost:8080
浏览器中的URL。您的浏览器将呈现字符串Hello World!
。测试完应用程序后,通过按下CTRL+C
启动 Node 进程的同一终端来停止服务器。
您现在已经设置了示例应用程序。在下一步中,您将在项目中添加一个配置文件,以便 CircleCI 可以使用它进行部署。
第 2 步 – 将配置文件添加到您的项目
CircleCI 根据项目文件夹中的配置文件执行工作流。在此步骤中,您将创建该文件以定义部署工作流。
.circleci
在项目根目录下创建一个文件夹:
- mkdir .circleci
添加一个config.yml
在其中调用的新文件:
- nano .circleci/config.yml
这将打开一个带有YAML文件扩展名的文件。YAML 是一种经常用于配置管理的语言。
将以下配置添加到新config.yml
文件中:
version: 2.1
# Define the jobs we want to run for this project
jobs:
pull-and-build:
docker:
- image: arvindr226/alpine-ssh
steps:
- checkout
- run: ssh -oStrictHostKeyChecking=no -v $USER@$IP "./deploy.sh"
# Orchestrate our job run sequence
workflows:
version: 2
build-project:
jobs:
- pull-and-build:
filters:
branches:
only:
- main
保存此文件并退出文本编辑器。
该文件告诉 CircleCI 管道以下内容:
- 有一个名为
pull-and-build
的作业,其步骤涉及启动一个Docker 容器,从它通过 SSH 连接到 VPS,然后运行该deploy.sh
文件。 - Docker 容器用于创建临时环境以执行
steps
配置部分中提到的命令。在这种情况下,您需要做的就是 SSH 进入 VPS 并运行sh deploy.sh
命令,因此环境需要轻量级但仍允许 SSH 命令。Docker 镜像arvindr226/alpine-ssh
是一个支持 SSH的Alpine Linux镜像。 deploy.sh
是您将在 VPS 中创建的文件。它将作为部署过程的一部分每次运行,并将包含特定于您的项目的步骤。- 在该
workflows
部分中,您通知 CircleCI 它需要基于某些过滤器来执行此作业,在这种情况下,只有对主分支的更改才会触发此作业。
接下来,您将提交这些文件并将其推送到 GitHub 存储库。您将通过从项目目录运行以下命令来完成此操作。
首先,将 Node.js 项目目录初始化为 git repo:
- git init
继续将新更改添加到 git 存储库:
- git add .
然后提交更改:
- git commit -m "initial commit"
如果这是第一次提交,git 会提示你运行一些git config
命令来识别你。
从您的浏览器导航到GitHub并使用您的 GitHub 帐户登录。创建一个circleci-test
没有自述文件或许可证文件的新存储库。创建存储库后,返回命令行以将本地文件推送到 GitHub。
要遵循 GitHub 协议,请main
使用以下命令重命名您的分支:
- git branch -M main
在首次推送文件之前,您需要将 GitHub 添加为远程存储库。通过运行来做到这一点:
- git remote add origin https://github.com/GitHub_username/circleci-test
使用以下push
命令执行此操作,该命令会将文件传输到 GitHub:
- git push -u origin main
您现在已将代码推送到 GitHub。在下一步中,您将在 VPS 中创建一个将steps
在pull-and-build
部件中执行的新用户。
第 3 步 – 为部署创建一个新用户
现在您已准备好项目,您将在 VPS 中创建一个部署用户。
作为您的sudo
用户连接到您的 VPS
- ssh your_username@your_server_ip
接下来,使用useradd
命令创建一个不使用密码登录的新用户。
- sudo useradd -m -d /home/circleci -s /bin/bash circleci
此命令在系统上创建一个新用户。该-m
标志指示命令创建由该-d
标志指定的主目录。
circleci
在这种情况下将是新的部署用户。出于安全考虑,您不会将此用户添加到sudo
组中,因为此用户的唯一工作是创建从 VPS 到 CircleCI 网络的 SSH 连接并运行deploy.sh
脚本。
确保您的 VPS 上的防火墙对端口开放8080
:
- sudo ufw allow 8080
您现在需要创建一个 SSH 密钥,新用户可以使用该密钥登录。您将创建一个没有密码的 SSH 密钥,否则 CircleCI 将无法解密它。您可以在官方 CircleCI 文档中找到更多信息。此外,CircleCI 期望 SSH 密钥的格式为 PEM 格式,因此您将在创建密钥对时强制执行该格式。
回到您的本地系统,移动到您的主文件夹:
- cd
然后运行以下命令:
- ssh-keygen -m PEM -t rsa -f .ssh/circleci
此命令使用-m
标志指定的 PEM 格式和标志指定的密钥类型创建 RSA 密钥-t
。您还指定-f
来创建一个名为circleci
and的新密钥对circleci.pub
。指定名称将避免覆盖现有id_rsa
文件。
打印出新的公钥:
- cat ~/.ssh/circleci.pub
这将输出您生成的公钥。您需要在您的 VPS 中注册此公钥。将此复制到剪贴板。
回到 VPS,.ssh
为circleci
用户创建一个目录:
- sudo mkdir /home/circleci/.ssh
在这里,您将从本地计算机复制的公钥添加到名为的文件中authorized_keys
:
- sudo nano /home/circleci/.ssh/authorized_keys
在此处添加复制的公钥,保存文件,然后退出文本编辑器。
为circleci
用户授予其目录权限,以便在部署期间不会遇到权限问题。
- sudo chown -R circleci:circleci /home/circleci
验证您是否可以使用私钥以新用户身份登录。在本地系统上打开一个新终端并运行:
- ssh circleci@your_server_ip -i ~/.ssh/circleci
您现在将以circleci
用户身份登录到您的 VPS。这说明SSH连接成功。接下来,您将您的 GitHub 存储库连接到 CircleCI。
第 4 步 – 将您的 GitHub 项目添加到 CircleCI
在这一步中,您将把您的 GitHub 帐户连接到您的 CircleCI 帐户,并circleci-test
为 CI/CD添加项目。如果您使用 GitHub 帐户注册,那么您的 GitHub 将自动与您的 CircleCI 帐户相关联。如果没有,请转到https://circleci.com/account
并连接它。
要添加您的circleci-test
项目,请导航到您的 CircleCI 项目仪表板:https://app.circleci.com/projects/project-dashboard/github/your_username
在这里,您将找到列出的 GitHub 中的所有项目。单击项目circleci-test 的设置项目。这将带您进入项目设置页面:
您现在可以选择为项目设置配置,您已经在 repo 中设置了该配置。由于这已经设置,选择使用现有配置选项。这将弹出一个弹出框,确认您要构建管道:
从这里开始,点击Start Building。这将带您进入circleci-test
管道页面。目前,这条管道将失败。这是因为您必须首先更新项目的 SSH 密钥。
导航到项目设置并选择左侧的SSH 密钥部分。https://app.circleci.com/settings/project/github/your_username/circleci-test
circleci
通过运行以下命令从本地计算机检索您之前创建的私钥:
- cat ~/.ssh/circleci
复制此命令的输出。
在“附加 SSH 密钥”部分下,单击“添加 SSH 密钥”按钮。
这将打开一个窗口,要求您输入主机名和 SSH 密钥。输入您选择的主机名,并添加您从本地环境复制的私有 SSH 密钥。
CircleCI 现在将能够circleci
使用此密钥以新用户身份登录VPS。
最后一步是将 VPS 的用户名和 IP 提供给 CircleCI。在同一个Project Settings页面中,转到左侧的Environment Variables选项卡:
添加一个名为的环境变量USER用的价值circleci
和IP与您的VPS的IP地址的值(或域名的VPS的,如果你有一个DNS记录)。
创建这些变量后,您就完成了 CircleCI 所需的设置。接下来,您将授予circleci
用户通过 SSH 访问 GitHub 的权限。
第 5 步 – 将 SSH 密钥添加到 GitHub
您现在需要提供一种circleci
用户可以通过 GitHub 进行身份验证的方式,以便它可以执行git
诸如git pull
.
为此,您将为该用户创建一个 SSH 密钥以对 GitHub 进行身份验证。
以circleci
用户身份连接到 VPS :
- ssh circleci@your_server_ip -i ~/.ssh/circleci
创建一个没有密码的新 SSH 密钥对:
- ssh-keygen -t rsa
然后输出公钥:
- cat ~/.ssh/id_rsa.pub
复制输出,然后转到circleci-test
GitHub 存储库的部署密钥设置。https://github.com/your_username/circleci-test/settings/keys
单击添加部署密钥以添加复制的公钥。使用您想要的密钥名称填充Title字段,然后在Key字段中添加复制的公钥。最后,单击添加密钥按钮将密钥添加到您的帐户。
现在circleci
用户可以访问您的 GitHub 帐户,您将使用此 SSH 身份验证来设置您的项目。
步骤 6 — 在 VPS 上设置项目
现在要设置项目,您将克隆存储库并以circleci
用户身份在 VPS 上进行项目的初始设置。
在您的 VPS 上,运行以下命令:
- git clone [email protected]:your_username/circleci-test.git
导航到它:
- cd circleci-test
首先,安装依赖项:
- npm install
现在通过运行您构建的服务器来测试应用程序:
- node app.js
转到您的浏览器并尝试该地址。您将收到输出。http://your_vps_ip:8080
Hello World!
停止此进程CTRL+C
并用于pm2
将此应用程序作为后台进程运行。
安装pm2
以便您可以将 Node 应用程序作为独立进程运行。pm2
是一个用 Node.js 编写的多功能进程管理器。即使在您注销服务器后,它也会帮助您保持示例 Node.js 项目作为活动进程运行。您可以在如何在 Ubuntu 18.04 上设置用于生产的 Node.js 应用程序教程中阅读更多相关内容。
- npm install -g pm2
注意: 在Ubuntu 18.04等一些系统上,全局安装npm包会导致权限错误,会导致安装中断。由于避免使用sudo
with是一种安全最佳实践npm install
,因此您可以通过更改 npm 的默认目录来解决此问题。如果遇到EACCES
错误,请按照官方 npm 文档中的说明进行操作。
您可以使用该pm2 start
命令将app.js
文件作为 Node 进程运行。您可以app
使用--name
标志命名它以便稍后识别它:
- pm2 start app.js --name "app"
您还需要提供部署说明。这些命令将在circleci
用户每次部署代码时运行。
返回主目录,因为这将是circleci
用户在成功登录尝试期间登陆的路径:
- cd ~
继续创建deploy.sh
文件,其中将包含部署说明:
- nano deploy.sh
您现在将使用Bash 脚本来自动化部署:
#!/bin/bash
#replace this with the path of your project on the VPS
cd ~/circleci-test
#pull from the branch
git pull origin main
# followed by instructions specific to your project that you used to do manually
npm install
export PATH=~/.npm-global/bin:$PATH
source ~/.profile
pm2 restart app
这将自动将工作目录更改为项目根目录,从 GitHub 中提取代码,安装依赖项,然后重新启动应用程序。保存并退出文件。
通过运行使这个文件成为可执行文件:
- chmod u+x deploy.sh
现在返回到您的本地机器并进行快速更改以对其进行测试。切换到您的项目目录:
- cd circleci-test
打开你的app.js
文件:
- nano circleci-test/app.js
现在添加以下突出显示的行:
const http = require('http');
http.createServer(function (req, res) {
res.write('Foo Bar!');
res.end();
}).listen(8080, '0.0.0.0');
保存文件并退出文本编辑器。
添加此更改并提交:
- git add .
- git commit -m "modify app.js"
现在将其推送到您的主分支:
- git push origin main
这将触发一个新的部署管道。导航到查看正在运行的管道。https://app.circleci.com/pipelines/github/your_username
成功后,在 刷新浏览器。现在将在您的浏览器中呈现。http://your_vps_ip:8080
Foo Bar!
结论
这些是将 CircleCI 与您的 GitHub 存储库和基于 Linux 的 VPS 集成的步骤。您可以修改 以deploy.sh
获取与您的项目相关的更具体的说明。
如果您想了解有关 CI/CD 的更多信息,请查看我们的CI/CD 主题页面。有关使用 CircleCI 设置工作流的更多信息,请转到CircleCI 文档。