作为Write for DOnations计划的一部分,作者选择了免费和开源基金来接受捐赠。
介绍
GitLab是一个开源协作平台,除了托管代码存储库之外,还提供强大的功能。您可以跟踪问题、托管包和注册表、维护 Wiki、设置持续集成 (CI) 和持续部署 (CD) 管道等。
在本教程中,您将使用 GitLab 构建持续部署管道。您将配置管道以构建 Docker 映像,将其推送到 GitLab 容器注册表,并使用 SSH 将其部署到您的服务器。管道将为推送到存储库的每个提交运行。
您将部署一个小的静态网页,但本教程的重点是配置 CD 管道。静态网页仅用于演示目的;您也可以使用其他 Docker 映像为部署应用相同的管道配置。
完成本教程后,您可以在浏览器中访问自动部署的结果。http://your_server_IP
先决条件
要完成本教程,您需要:
- 按照Ubuntu 18.04 初始服务器设置指南设置一台 Ubuntu 18.04 服务器,包括一个 sudo 非 root 用户和一个防火墙。您至少需要 1 GB RAM 和 1 个 CPU。
- 按照如何在 Ubuntu 18.04 上安装和使用 Docker 指南在服务器上安装 Docker。
- GitLab 实例上具有启用容器注册表的用户帐户。GitLab 官方实例的免费计划满足要求。您还可以按照如何在 Ubuntu 18.04 上安装和配置 GitLab 指南来托管您自己的 GitLab 实例。
第 1 步 – 创建 GitLab 存储库
让我们首先创建一个 GitLab 项目并向其中添加一个 HTML 文件。您稍后会将 HTML 文件复制到 Nginx Docker 映像中,然后您将部署到服务器。
登录到您的 GitLab 实例并单击New project。
- 给它一个正确的Project name。
- (可选)添加项目描述。
- 确保根据您的要求将可见性级别设置为私人或公共。
- 最后点击创建项目
您将被重定向到项目的概览页面。
让我们创建 HTML 文件。在您的项目的概览页面上,单击New file。
设置文件名来index.html
和下面的HTML添加到文件正文:
<html>
<body>
<h1>My Personal Website</h1>
</body>
</html>
单击页面底部的提交更改以创建文件。
在浏览器中打开时,此 HTML 将生成一个空白页面,其中一个标题显示我的个人网站。
Dockerfiles 是 Docker 用来构建 Docker 镜像的配方。让我们创建一个Dockerfile
将 HTML 文件复制到 Nginx 图像中的文件。
返回项目的概览页面,单击+按钮并选择新建文件选项。
设置文件名来Dockerfile
添加这些说明文件主体:
FROM nginx:1.18
COPY index.html /usr/share/nginx/html
该FROM
指令指定要继承的图像——在本例中为nginx:1.18
图像。1.18
是代表 Nginx 版本的图像标签。该nginx:latest
标签引用了最新的 Nginx 版本,但这可能会在将来破坏您的应用程序,这就是建议使用固定版本的原因。
该COPY
指令将index.html
文件复制到/usr/share/nginx/html
Docker 映像中。这是 Nginx 存储静态 HTML 内容的目录。
单击页面底部的提交更改以创建文件。
在下一步中,您将配置 GitLab 运行程序以控制谁可以执行部署作业。
第 2 步 – 注册 GitLab Runner
为了跟踪将与 SSH 私钥联系的环境,您需要将您的服务器注册为 GitLab 运行程序。
在您的部署管道中,您希望使用 SSH 登录到您的服务器。为此,您需要将 SSH 私钥存储在 GitLab CI/CD 变量中(步骤 5)。SSH 私钥是一个非常敏感的数据,因为它是您服务器的入场券。通常,私钥永远不会离开生成它的系统。通常情况下,您会在主机上生成一个 SSH 密钥,然后在服务器上对其进行授权(即,将公钥复制到服务器)以便手动登录并执行部署例程。
这里的情况略有变化:您想要授予对服务器的自治权限 (GitLab CI/CD) 访问权限以自动化部署例程。因此,私钥需要离开生成它的系统,并委托给 GitLab 和其他相关方。您永远不希望您的私钥进入不受您控制或信任的环境。
除了 GitLab,GitLab runner 是另一个您的私钥将进入的系统。对于每个管道,GitLab 使用运行器来执行繁重的工作,即执行您在 CI/CD 配置中指定的作业。这意味着部署作业最终将在 GitLab 运行器上执行,因此私钥将被复制到运行器,以便它可以使用 SSH 登录到服务器。
如果您使用未知的 GitLab Runners(例如,shared runners)来执行部署作业,那么您将不会意识到系统与私钥取得联系。即使 GitLab 运行程序在作业执行后清理所有数据,您也可以通过将自己的服务器注册为 GitLab 运行程序来避免将私钥发送到未知系统。然后私钥将被复制到由您控制的服务器。
首先登录到您的服务器:
- ssh sammy@your_server_IP
为了安装该gitlab-runner
服务,您将添加官方 GitLab 存储库。下载并检查安装脚本:
- curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh > script.deb.sh
- less script.deb.sh
一旦您对脚本的安全性感到满意,请运行安装程序:
- sudo bash script.deb.sh
这可能并不明显,但您必须输入非 root用户的密码才能继续。执行上一条命令时,输出将类似于:
Output[sudo] password for sammy: % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 5945 100 5945 0 0 8742 0 --:--:-- --:--:-- --:--:-- 8729
当curl
命令完成后,您会收到以下消息:
OutputThe repository is setup! You can now install packages.
接下来安装gitlab-runner
服务:
- sudo apt install gitlab-runner
通过检查服务状态来验证安装:
- systemctl status gitlab-runner
您将active (running)
在输出中得到:
Output● gitlab-runner.service - GitLab Runner
Loaded: loaded (/etc/systemd/system/gitlab-runner.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2020-06-01 09:01:49 UTC; 4s ago
Main PID: 16653 (gitlab-runner)
Tasks: 6 (limit: 1152)
CGroup: /system.slice/gitlab-runner.service
└─16653 /usr/lib/gitlab-runner/gitlab-runner run --working-directory /home/gitlab-runner --config /etc/gitla
要注册跑步者,您需要获取项目令牌和 GitLab URL:
- 在您的 GitLab 项目中,导航到Settings > CI/CD > Runners。
- 在手动设置特定的 Runner部分,您将找到注册令牌和 GitLab URL。将两者复制到文本编辑器;您将需要它们来执行下一个命令。它们将被称为和。
https://your_gitlab.com
project_token
回到你的终端,为你的项目注册运行器:
- sudo gitlab-runner register -n --url https://your_gitlab.com --registration-token project_token --executor docker --description "Deployment Runner" --docker-image "docker:stable" --tag-list deployment --docker-privileged
命令选项可以解释如下:
-n
以register
非交互方式执行命令(我们将所有参数指定为命令选项)。--url
是您从 GitLab 中的跑步者页面复制的 GitLab URL。--registration-token
是您从 GitLab 中的跑步者页面复制的令牌。--executor
是执行器类型。docker
在 Docker 容器中执行每个 CI/CD 作业(请参阅GitLab 关于 executors 的文档)。--description
是跑步者的描述,它将显示在 GitLab 中。--docker-image
如果未明确指定,则是在 CI/CD 作业中使用的默认 Docker 映像。--tag-list
是分配给跑步者的标签列表。可以在管道配置中使用标签来为 CI/CD 作业选择特定的运行器。该deployment
标签将允许您引用此特定运行程序来执行部署作业。--docker-privileged
以特权模式执行为每个 CI/CD 作业创建的 Docker 容器。特权容器可以访问主机上的所有设备,并且对主机的访问权限与在容器外运行的进程几乎相同(请参阅 Docker 关于运行时权限和 Linux 功能的文档)。在特权模式下运行的原因是,您可以使用 Docker-in-Docker ( dind ) 在 CI/CD 管道中构建 Docker 映像。为容器提供所需的最低要求是一种很好的做法。对您来说,需要在特权模式下运行才能使用 Docker-in-Docker。请注意,您仅为此特定项目注册了运行程序,您可以控制在特权容器中执行的命令。
执行gitlab-runner register
命令后,您将收到以下输出:
OutputRunner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
通过转到GitLab 中的Settings > CI/CD > Runners来验证注册过程,注册的 runner 将在其中显示。
在下一步中,您将创建一个部署用户。
第 3 步 – 创建部署用户
您将创建一个专用于部署任务的用户。您稍后将配置 CI/CD 管道以使用该用户登录到服务器。
在您的服务器上,创建一个新用户:
- sudo adduser deployer
您将被引导完成用户创建过程。输入一个强密码以及您想要指定的任何其他用户信息(可选)。最后用 确认用户创建Y
。
将用户添加到 Docker 组:
- sudo usermod -aG docker deployer
这允许部署者执行docker
执行部署所需的命令。
警告:将用户添加到 Docker 组,授予与 root 用户等效的权限。有关这如何影响系统安全性的更多详细信息,请参阅Docker 守护程序攻击面。
在下一步中,您将创建一个 SSH 密钥,以便能够以deployer身份登录到服务器。
第 4 步 – 设置 SSH 密钥
您将为部署用户创建一个 SSH 密钥。GitLab CI/CD 稍后将使用密钥登录服务器并执行部署例程。
让我们首先切换到新创建的部署者用户,您将为其生成 SSH 密钥:
- su deployer
系统将提示您输入部署者密码以完成用户切换。
接下来,生成 4096 位 SSH 密钥。ssh-keygen
正确回答命令的问题很重要:
- 第一个问题:用 回答
ENTER
,它将密钥存储在默认位置(本教程的其余部分假设密钥存储在默认位置)。 - 第二个问题:配置密码保护SSH私钥(用于认证的密钥)。如果您指定密码,则每次使用私钥时都必须输入密码。通常,密码短语为 SSH 密钥添加了另一个安全层,这是一种很好的做法。拥有私钥的人也需要密码短语才能使用密钥。就本教程而言,拥有一个空密码很重要,因为 CI/CD 管道将以非交互方式执行,因此不允许输入密码。
总而言之,运行以下命令并确认两个问题ENTER
以创建 4096 位 SSH 密钥并将其存储在默认位置,密码为空:
- ssh-keygen -b 4096
要为部署者用户授权 SSH 密钥,您需要将公钥附加到authorized_keys
文件中:
- cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
~
是 Linux 中用户 home 的缩写。该cat
程序将打印文件的内容;在这里,您使用>>
运算符重定向输出cat
并将其附加到authorized_keys
文件中。
在此步骤中,您已为 CI/CD 管道创建了一个 SSH 密钥对以登录和部署应用程序。接下来,您将私钥存储在 GitLab 中,以使其在管道过程中可访问。
步骤 5 — 将私钥存储在 GitLab CI/CD 变量中
您将 SSH 私钥存储在 GitLab CI/CD 文件变量中,以便管道可以使用该密钥登录到服务器。
当 GitLab 创建 CI/CD 管道时,它会将所有变量发送到相应的运行器,并且这些变量将被设置为作业持续时间的环境变量。特别是,文件变量的值存储在文件中,环境变量将包含该文件的路径。
当您在变量部分时,您还将为服务器 IP 和服务器用户添加一个变量,这将通知管道有关目标服务器和登录用户的信息。
首先显示 SSH 私钥:
- cat ~/.ssh/id_rsa
将输出复制到剪贴板。确保在之后添加换行符-----END RSA PRIVATE KEY-----
:
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
现在导航到GitLab 项目中的Settings > CI / CD > Variables并单击Add Variable。填写表格如下:
- 钥匙:
ID_RSA
- 值:从剪贴板粘贴您的 SSH 私钥(包括末尾的换行符)。
- 类型:文件
- 环境范围:全部(默认)
- 保护变量:选中
- 掩码变量:未选中
注意:该变量不能被屏蔽,因为它不符合正则表达式要求(参见GitLab 的关于屏蔽变量的文档)。但是,私钥永远不会出现在控制台日志中,这使得屏蔽它过时了。
将在运行器上为每个 CI/CD 作业创建一个包含私钥的文件,其路径将存储在$ID_RSA
环境变量中。
使用您的服务器 IP 创建另一个变量。单击添加变量并按如下方式填写表单:
- 钥匙:
SERVER_IP
- 价值:
your_server_IP
- 类型:变量
- 环境范围:全部(默认)
- 保护变量:选中
- 掩码变量:选中
最后,用登录用户创建一个变量。单击添加变量并按如下方式填写表单:
- 钥匙:
SERVER_USER
- 价值:
deployer
- 类型:变量
- 环境范围:全部(默认)
- 保护变量:选中
- 掩码变量:选中
您现在已将私钥存储在 GitLab CI/CD 变量中,这使得该密钥在管道执行期间可用。在下一步中,您将继续配置 CI/CD 管道。
第 6 步 – 配置.gitlab-ci.yml
文件
您将配置 GitLab CI/CD 管道。管道将构建一个 Docker 镜像并将其推送到容器注册表。GitLab 为每个项目提供了一个容器注册表。您可以通过转到GitLab 项目中的Packages & Registries > Container Registry来探索容器注册表(在GitLab 的容器注册表文档中阅读更多内容。)管道的最后一步是登录到您的服务器,拉取最新的 Docker 镜像,删除旧容器,然后启动一个新容器。
现在您将创建.gitlab-ci.yml
包含管道配置的文件。在 GitLab 中,转到项目概述页面,单击+按钮并选择New file。然后将文件名设置为.gitlab-ci.yml
.
(或者,您可以克隆存储库并.gitlab-ci.yml
在本地计算机上进行所有以下更改,然后提交并推送到远程存储库。)
开始添加以下内容:
stages:
- publish
- deploy
每个作业都分配到一个阶段。分配到同一阶段的作业并行运行(如果有足够的运行程序可用)。阶段将按照指定的顺序执行。在这里,publish
舞台先走,deploy
舞台第二。后续阶段仅在前一阶段成功完成(即所有作业都已通过)时开始。舞台名称可以任意选择。
当您想要将此 CD 配置与现有的 CI 管道结合起来以测试和构建应用程序时,您可能希望在现有阶段之后添加publish
和deploy
阶段,以便仅在测试通过时才进行部署。
在此之后,将其添加到您的.gitlab-ci.yml
文件中:
. . .
variables:
TAG_LATEST: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:latest
TAG_COMMIT: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:$CI_COMMIT_SHORT_SHA
variables 部分定义了在作业script
部分的上下文中可用的环境变量。这些变量将作为通常的 Linux 环境变量可用;也就是说,您可以在脚本中通过添加美元符号作为前缀来引用它们,例如$TAG_LATEST
. GitLab 为每个提供上下文特定信息的作业创建了一些预定义变量,例如作业正在处理的分支名称或提交哈希(阅读有关预定义变量的更多信息)。在这里,您从预定义的变量中组合了两个环境变量。他们代表:
CI_REGISTRY_IMAGE
:表示绑定到特定项目的容器注册表的 URL。此 URL 取决于 GitLab 实例。例如,gitlab.com项目的注册表 URL遵循以下模式:. 但由于 GitLab 将提供此变量,因此您无需知道确切的 URL。registry.gitlab.com/your_user/your_project
CI_COMMIT_REF_NAME
:为其构建项目的分支或标记名称。CI_COMMIT_SHORT_SHA
:为其构建项目的提交修订的前八个字符。
这两个变量都由预定义的变量组成,将用于标记 Docker 镜像。
TAG_LATEST
将latest
标签添加到图像。这是提供始终代表最新版本的标记的常用策略。对于每个部署,latest
镜像将在容器注册表中被新构建的 Docker 镜像覆盖。
TAG_COMMIT
,另一方面,使用被部署的提交 SHA 的前八个字符作为镜像标签,从而为每个提交创建一个唯一的 Docker 镜像。您将能够跟踪 Docker 镜像的历史记录到 Git 提交的粒度。这是进行持续部署时的常用技术,因为它允许您在部署有缺陷的情况下快速部署旧版本的代码。
正如您将在接下来的步骤中探索的那样,将部署回滚到较旧的 Git 修订版的过程可以直接在 GitLab 中完成。
$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME
指定 Docker 映像基本名称。根据GitLab 的文档,Docker 镜像名称必须遵循以下方案:
image name scheme<registry URL>/<namespace>/<project>/<image>
$CI_REGISTRY_IMAGE
代表<registry URL>/<namespace>/<project>
部分并且是强制性的,因为它是项目的注册表根。$CI_COMMIT_REF_NAME
是可选的,但对于为不同的分支托管 Docker 镜像很有用。在本教程中,您将只使用一个分支,但最好构建一个可扩展的结构。一般来说,GitLab 支持的镜像仓库名称分为三个级别:
repository name levelsregistry.example.com/group/project:some-tag
registry.example.com/group/project/image:latest
registry.example.com/group/project/my/image:rc1
对于您的TAG_COMMIT
变量,您使用了第二个选项, whereimage
将替换为分支名称。
接下来,将以下内容添加到您的.gitlab-ci.yml
文件中:
. . .
publish:
image: docker:latest
stage: publish
services:
- docker:dind
script:
- docker build -t $TAG_COMMIT -t $TAG_LATEST .
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
- docker push $TAG_COMMIT
- docker push $TAG_LATEST
该publish
部分是CI/CD 配置中的第一个作业。让我们分解一下:
image
是用于此作业的 Docker 映像。GitLab 运行程序将为每个作业创建一个 Docker 容器并在该容器中执行脚本。docker:latest
image 确保docker
命令可用。stage
将作业分配给publish
舞台。services
指定 Docker-in-Docker——dind
服务。这就是您在特权模式下注册 GitLab 运行程序的原因。
该script
部分的的publish
工作指定执行该任务的shell命令。执行这些命令时,工作目录将设置为存储库根目录。
docker build ...
:基于 构建 Docker 映像,Dockerfile
并使用变量部分中定义的最新提交标记对其进行标记。docker login ...
:将 Docker 登录到项目的容器注册表。您使用预定义的变量$CI_BUILD_TOKEN
作为身份验证令牌。GitLab 将生成令牌并在作业的生命周期内保持有效。docker push ...
:将两个镜像标签推送到容器注册表。
在此之后,将deploy
作业添加到您的.gitlab-ci.yml
:
. . .
deploy:
image: alpine:latest
stage: deploy
tags:
- deployment
script:
- chmod og= $ID_RSA
- apk update && apk add openssh-client
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker pull $TAG_COMMIT"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker container rm -f my-app || true"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker run -d -p 80:80 --name my-app $TAG_COMMIT"
Alpine 是一个轻量级的 Linux 发行版,在这里作为 Docker 镜像就足够了。您将作业分配给deploy
舞台。部署标记确保作业将在标记deployment
为 的运行器上执行,例如您在步骤 2 中配置的运行器。
在script
一节的deploy
工作有两个配置性的命令开始:
chmod og= $ID_RSA
:从私钥中撤销组和其他人的所有权限,以便只有所有者可以使用它。这是一个要求,否则 SSH 拒绝使用私钥。apk update && apk add openssh-client
:更新 Alpine 的包管理器 (apk) 并安装openssh-client
提供ssh
命令的 。
接下来是四个连续的ssh
命令。每个的模式是:
ssh connect pattern for all deployment commandsssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "command"
在ssh
您command
在远程服务器上执行的每个语句中。为此,您需要使用您的私钥进行身份验证。
选项如下:
-i
代表身份文件,$ID_RSA
是包含私钥文件路径的 GitLab 变量。-o StrictHostKeyChecking=no
确保绕过这个问题,无论您是否信任远程主机。这个问题在管道等非交互式上下文中无法回答。$SERVER_USER
和$SERVER_IP
是您在第 5 步中创建的 GitLab 变量。它们为 SSH 连接指定远程主机和登录用户。command
将在远程主机上执行。
部署最终是通过在您的服务器上执行以下四个命令来进行的:
docker login ...
:将 Docker 登录到容器注册表。docker pull ...
:从容器注册表中拉取最新的镜像。docker container rm ...
: 删除现有容器(如果存在)。|| true
确保退出代码始终成功,即使没有以 name 运行的容器my-app
。这保证了当容器不存在时(例如,对于第一次部署),如果存在则删除例程而不会破坏管道。docker run ...
:使用注册表中的最新映像启动一个新容器。容器将被命名为my-app
。80
主机上的端口将绑定到80
容器的端口(顺序为-p host:container
)。-d
以分离模式启动容器,否则管道将卡住等待命令终止。
注意:考虑到执行命令的 GitLab 运行程序是完全相同的服务器,使用 SSH 在您的服务器上运行这些命令似乎很奇怪。然而它是必需的,因为运行程序在 Docker 容器中执行命令,因此如果您不使用 SSH 执行命令,您将部署在容器内而不是服务器内。有人可能会争辩说,您可以使用shell 执行程序,而不是使用Docker 作为运行程序执行程序。在主机上运行命令。但是,这会对您的管道产生约束,即运行器必须与您要部署到的服务器是同一台服务器。这不是一种可持续且可扩展的解决方案,因为有一天您可能希望将应用程序迁移到不同的服务器或使用不同的运行器服务器。在任何情况下,使用 SSH 执行部署命令都是有意义的,可能是出于技术或迁移相关的原因。
让我们继续将其添加到您的部署作业中.gitlab-ci.yml
:
. . .
deploy:
. . .
environment:
name: production
url: http://your_server_IP
only:
- master
GitLab 环境允许您控制 GitLab 内的部署。您可以通过转到Operations > Environments检查 GitLab 项目中的环境。如果管道尚未完成,则将没有可用的环境,因为到目前为止还没有进行部署。
当管道作业定义一个environment
部分时,production
每次作业成功完成时,GitLab 都会为给定的环境(此处)创建部署。这允许您跟踪 GitLab CI/CD 创建的所有部署。对于每个部署,您都可以看到相关的提交以及为其创建的分支。
还有一个可用于重新部署的按钮,允许您回滚到软件的旧版本。environment
单击“查看部署”按钮时,将打开该部分中指定的 URL 。
该only
部分定义了作业将运行的分支和标签的名称。默认情况下,GitLab 将为每次推送到存储库启动一个管道并运行所有作业(前提是该.gitlab-ci.yml
文件存在)。该only
部分是将作业执行限制到某些分支/标签的一种选择。在这里,您只想为master
分支执行部署作业。要定义关于作业是否应该运行的更复杂的规则,请查看规则语法。
注:在2020年10月,GitHub上已经改变了它的命名约定的默认分支从master
到main
。其他提供商,例如 GitLab 和开发人员社区,一般都开始遵循这种方法。master
本教程中使用术语分支来表示您可能具有不同名称的默认分支。
您的完整.gitlab-ci.yml
文件将如下所示:
stages:
- publish
- deploy
variables:
TAG_LATEST: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:latest
TAG_COMMIT: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:$CI_COMMIT_SHORT_SHA
publish:
image: docker:latest
stage: publish
services:
- docker:dind
script:
- docker build -t $TAG_COMMIT -t $TAG_LATEST .
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
- docker push $TAG_COMMIT
- docker push $TAG_LATEST
deploy:
image: alpine:latest
stage: deploy
tags:
- deployment
script:
- chmod og= $ID_RSA
- apk update && apk add openssh-client
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker pull $TAG_COMMIT"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker container rm -f my-app || true"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker run -d -p 80:80 --name my-app $TAG_COMMIT"
environment:
name: production
url: http://your_server_IP
only:
- master
最后单击GitLab 页面底部的Commit changes以创建.gitlab-ci.yml
文件。或者,在本地克隆 Git 存储库后,提交文件并将其推送到远程。
您已经创建了一个 GitLab CI/CD 配置,用于构建 Docker 映像并将其部署到您的服务器。在下一步中,您将验证部署。
第 7 步 – 验证部署
现在,您将在 GitLab 的各个位置以及您的服务器和浏览器中验证部署。
当.gitlab-ci.yml
文件被推送到存储库时,GitLab 将自动检测它并启动 CI/CD 管道。在您创建.gitlab-ci.yml
文件时,GitLab 启动了第一个管道。
转到GitLab 项目中的CI/CD > Pipelines以查看管道的状态。如果作业仍在运行/挂起,请等待它们完成。您将看到带有两个绿色复选标记的Passed管道,表示发布和部署作业已成功运行。
让我们检查一下管道。单击“状态”列中的“已通过”按钮以打开管道的概览页面。您将获得一般信息的概述,例如:
- 整个管道的执行时长。
- 执行管道的提交和分支。
- 相关合并请求。如果负责的分支有一个开放的合并请求,它会显示在这里。
- 在此管道中执行的所有作业及其状态。
接下来单击部署按钮以打开部署作业的结果页面。
在作业结果页面上,您可以看到作业脚本的 shell 输出。这是调试失败管道时要寻找的地方。在右侧边栏中,您将找到添加到此作业的部署标记,并且它是在您的Deployment Runner上执行的。
如果滚动到页面顶部,您会发现此作业已部署到生产消息。GitLab 认识到部署是由于作业的环境部分而发生的。单击生产链接以移至生产环境。
您将了解所有生产部署。到目前为止只有一个部署。对于每次部署,最右侧都有一个重新部署按钮。重新部署将重复该特定管道的部署作业。
重新部署是否按预期工作取决于管道配置,因为它只会在相同情况下重复部署作业。由于您已配置为使用提交 SHA 作为标记部署 Docker 映像,因此重新部署将适用于您的管道。
注意:您的 GitLab 容器注册表可能有过期策略。过期策略会定期从容器注册表中删除旧的镜像和标签。因此,早于到期策略的部署将无法重新部署,因为此提交的 Docker 映像已从注册表中删除。您可以在设置 > CI/CD > Container Registry 标签过期策略中管理过期策略。到期时间间隔通常设置得很高,比如 90 天。但是当你遇到试图部署一个已经因为过期策略从注册表中删除的镜像的情况时,你可以通过重新运行发布来解决问题 该特定管道的作业也是如此,它将为给定的提交重新创建映像并将其推送到注册表。
接下来单击“查看部署”按钮,该按钮将在浏览器中打开,您应该会看到“我的个人网站”标题。http://your_server_IP
最后,我们要检查您服务器上已部署的容器。如果您已经断开连接,请转到您的终端并确保再次登录(它适用于sammy和deployer两个用户):
- ssh sammy@your_server_IP
现在列出正在运行的容器:
- docker container ls
这将列出my-app
容器:
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b64df4b37f8 registry.your_gitlab.com/your_gitlab_user/your_project/master:your_commit_sha "nginx -g 'daemon of…" 4 hours ago Up 4 hours 0.0.0.0:80->80/tcp my-app
阅读如何在 Ubuntu 18.04 上安装和使用 Docker 指南以了解有关管理 Docker 容器的更多信息。
您现在已经验证了部署。在下一步中,您将完成回滚部署的过程。
第 8 步 – 回滚部署
接下来,您将更新网页,这将创建一个新部署,然后使用 GitLab 环境重新部署之前的部署。这涵盖了部署有缺陷时部署回滚的用例。
首先对index.html
文件进行一些更改:
- 在 GitLab 中,转到项目概述并打开
index.html
文件。 - 单击编辑按钮打开在线编辑器。
- 将文件内容更改为以下内容:
<html>
<body>
<h1>My Enhanced Personal Website</h1>
</body>
</html>
通过单击页面底部的提交更改来保存更改。
将创建一个新管道来部署更改。在 GitLab 中,转到CI/CD > Pipelines。管道完成后,您可以在浏览器中打开更新后的网页,现在显示的是My Enhanced Personal Website而不是My Personal Website。http://your_server_IP
当您转到操作 > 环境 > 生产时,您将看到新创建的部署。现在单击初始旧部署的重新部署按钮:
单击“回滚”按钮确认弹出窗口。
该旧管道的部署作业将重新启动,您将被重定向到作业的概览页面。等待工作完成,然后在浏览器中打开,您将看到最初的标题我的个人网站再次出现。http://your_server_IP
让我们总结一下您在本教程中取得的成就。
结论
在本教程中,您已使用 GitLab CI/CD 配置了持续部署管道。您创建了一个由 HTML 文件和 Dockerfile 组成的小型 Web 项目。然后您将.gitlab-ci.yml
管道配置配置为:
- 构建 Docker 镜像。
- 将 Docker 映像推送到容器注册表。
- 登录服务器,拉取最新镜像,停止当前容器,启动一个新容器。
GitLab 现在会将网页部署到您的服务器,以便每次推送到存储库。
此外,您已经在 GitLab 和您的服务器上验证了部署。您还创建了第二个部署并使用 GitLab 环境回滚到第一个部署,这演示了您如何处理有缺陷的部署。
此时,您已经自动化了整个部署链。您现在可以更频繁地与全世界和/或客户共享代码更改。因此,开发周期可能会变短,因为收集反馈和发布代码更改所需的时间更少。
作为下一步,您可以使您的服务可通过域名访问并保护与 HTTPS 的通信,如何使用 Traefik 作为 Docker 容器的反向代理是一个很好的后续行动。