如何使用GitLab构建Docker映像并托管Docker映像存储库
介绍
容器化正在迅速成为在云环境中打包和部署应用程序最被接受的方法。 它提供的标准化,连同其资源效率(与完整的虚拟机相比)和灵活性,使其成为现代 DevOps 思维方式的重要推动者。 当您的应用程序和微服务完全容器化时,许多有趣的 云原生 部署、编排和监控策略成为可能。
Docker 容器是迄今为止最常见的容器类型。 尽管像 Docker Hub 这样的公共 Docker 镜像存储库充满了容器化的开源软件镜像,您现在可以 docker pull
使用这些镜像,但对于私有代码,您需要支付服务来构建和存储您的图像,或运行您自己的软件来执行此操作。
GitLab 社区版是一个自托管软件套件,提供 Git 存储库托管、项目跟踪、CI/CD 服务和 Docker 映像注册表等功能。 在本教程中,我们将使用 GitLab 的持续集成服务从示例 Node.js 应用程序构建 Docker 映像。 然后将测试这些图像并将其上传到我们自己的私有 Docker 注册表。
先决条件
在开始之前,我们需要设置 一个安全的 GitLab 服务器 和 一个 GitLab CI 运行器 来执行持续集成任务。 以下部分将提供链接和更多详细信息。
使用 SSL 保护的 GitLab 服务器
要存储我们的源代码、运行 CI/CD 任务并托管 Docker 注册表,我们需要在 Ubuntu 16.04 服务器上安装一个 GitLab 实例。 GitLab 目前推荐 具有至少 2 个 CPU 内核和 4GB RAM 的服务器。 此外,我们将使用 Let's Encrypt 的 SSL 证书保护服务器。 为此,您需要一个指向服务器的域名。
您可以通过以下教程完成这些先决条件要求:
- 如何使用 DigitalOcean 设置主机名 将向您展示如何使用 DigitalOcean 控制面板管理域
- 使用 Ubuntu 16.04 的初始服务器设置将获得非 root、启用 sudo 的用户设置,并启用 Ubuntu 的
ufw
防火墙 - 如何在 Ubuntu 16.04 上安装和配置 GitLab 将向您展示如何安装 GitLab 并使用 Let's Encrypt 提供的免费 TLS/SSL 证书对其进行配置
GitLab CI 运行者
How To Set Up Continuous Integration Pipelines with GitLab CI on Ubuntu 16.04 将为您概述 GitLab 的 CI 服务,并向您展示如何设置 CI 运行器来处理作业。 我们将在本教程中创建的演示应用程序和运行器基础架构之上进行构建。
第 1 步 — 设置特权 GitLab CI Runner
在先决条件 GitLab 持续集成教程中,我们使用 sudo gitlab-runner register
设置了一个 GitLab 运行器及其交互式配置过程。 该运行程序能够在隔离的 Docker 容器内运行软件的构建和测试。
然而,为了构建 Docker 镜像,我们的运行器需要完全访问 Docker 服务本身。 推荐的配置方法是使用 Docker 的官方 docker-in-docker
映像来运行作业。 这需要授予运行器一个特殊的 privileged
执行模式,因此我们将创建一个启用此模式的第二个运行器。
注意:授予运行器特权模式基本上禁用了使用容器的所有安全优势。 不幸的是,启用支持 Docker 的运行器的其他方法也带有类似的安全隐患。 请查看 Docker Build 上的官方 GitLab 文档,以了解有关不同运行器选项以及最适合您的情况的更多信息。
因为使用特权运行器存在安全隐患,我们将创建一个特定于项目的运行器,它只接受我们 hello_hapi
项目上的 Docker 作业(GitLab 管理员总是可以手动将此运行器添加到其他项目中)晚点)。 在您的 hello_hapi
项目页面中,单击左侧菜单底部的 Settings,然后在子菜单中单击 CI/CD:
现在单击 Runners settings 部分旁边的 Expand 按钮:
会有一些关于设置 Specific Runner 的信息,包括注册令牌。 记下这个令牌。 当我们使用它注册一个新的跑者时,跑者将只锁定到这个项目。
当我们在这个页面上时,点击 Disable shared Runners 按钮。 我们希望确保我们的 Docker 作业始终在我们的特权运行器上运行。 如果非特权共享运行器可用,GitLab 可能会选择使用该运行器,这会导致构建错误。
登录到具有当前 CI 运行器的服务器。 如果您还没有设置运行器的机器,请返回并完成先决条件教程的 安装 GitLab CI Runner 服务 部分,然后再继续。
现在,运行以下命令来设置特权项目特定的运行器:
sudo gitlab-runner register -n \ --url https://gitlab.example.com/ \ --registration-token your-token \ --executor docker \ --description "docker-builder" \ --docker-image "docker:latest" \ --docker-privileged
OutputRegistering runner... succeeded runner=61SR6BwV Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
请务必替换您自己的信息。 我们在命令行上设置所有运行器选项,而不是使用交互式提示,因为提示不允许我们指定 --docker-privileged
模式。
您的跑步者现在已设置、注册并运行。 要验证,请切换回您的浏览器。 单击 GitLab 主菜单栏中的扳手图标,然后单击左侧菜单中的 Runners。 您的跑步者将被列出:
现在我们有了一个能够构建 Docker 镜像的运行器,让我们为它设置一个私有 Docker 注册表以将图像推送到。
第 2 步 — 设置 GitLab 的 Docker 注册表
设置您自己的 Docker 注册表可以让您从自己的私有服务器推送和拉取镜像,从而提高安全性并减少您的工作流程对外部服务的依赖。
GitLab 将建立一个私有 Docker 注册表,只需进行一些配置更新。 首先,我们将设置注册表所在的 URL。 然后我们将(可选)配置注册表以使用与 S3 兼容的对象存储服务来存储其数据。
SSH 到您的 GitLab 服务器,然后打开 GitLab 配置文件:
sudo nano /etc/gitlab/gitlab.rb
向下滚动到 Container Registry 设置 部分。 我们将取消注释 registry_external_url
行并将其设置为我们的 GitLab 主机名,端口号为 5555
:
/etc/gitlab/gitlab.rb
registry_external_url 'https://gitlab.example.com:5555'
接下来,添加以下两行来告诉注册表在哪里可以找到我们的 Let's Encrypt 证书:
/etc/gitlab/gitlab.rb
registry_nginx['ssl_certificate'] = "/etc/letsencrypt/live/gitlab.example.com/fullchain.pem" registry_nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/gitlab.example.com/privkey.pem"
保存并关闭文件,然后重新配置 GitLab:
sudo gitlab-ctl reconfigure
Output. . . gitlab Reconfigured!
更新防火墙以允许到注册表端口的流量:
sudo ufw allow 5555
现在切换到另一台安装了 Docker 的机器,并登录到私有 Docker 注册表。 如果您的本地开发计算机上没有 Docker,您可以使用设置的任何服务器来运行 GitLab CI 作业,因为它已经安装了 Docker:
docker login gitlab.example.com:5555
系统将提示您输入用户名和密码。 使用您的 GitLab 凭据登录。
OutputLogin Succeeded
成功! 注册表已设置并正在运行。 目前它将文件存储在 GitLab 服务器的本地文件系统上。 如果您想改用对象存储服务,请继续阅读本节。 如果没有,请跳至第 3 步。
要为注册表设置对象存储后端,我们需要了解有关我们的对象存储服务的以下信息:
- 访问密钥
- 密钥
- Region (
us-east-1
) 例如,如果使用 Amazon S3,或 Region Endpoint 如果使用 S3 兼容服务 (https://nyc.digitaloceanspaces.com
) - 存储桶名称
如果您正在使用 DigitalOcean Spaces,您可以通过阅读如何创建 DigitalOcean Space 和 API Key了解如何设置新空间并获取以上信息。
获得对象存储信息后,打开 GitLab 配置文件:
sudo nano /etc/gitlab/gitlab.rb
再次向下滚动到容器注册表部分。 查找 registry['storage']
块,取消注释,并将其更新为以下内容,再次确保在适当的地方替换您自己的信息:
/etc/gitlab/gitlab.rb
registry['storage'] = { 's3' => { 'accesskey' => 'your-key', 'secretkey' => 'your-secret', 'bucket' => 'your-bucket-name', 'region' => 'nyc3', 'regionendpoint' => 'https://nyc3.digitaloceanspaces.com' } }
如果您使用的是 Amazon S3,则只需要 region
而不需要 regionendpoint
。 如果您使用 Spaces 等 S3 兼容服务,则需要 regionendpoint
。 在这种情况下, region
实际上并没有配置任何内容,您输入的值也无关紧要,但它仍然需要存在且不能为空。
保存并关闭文件。
注意:目前存在一个BUG,如果您的对象存储桶为空,注册表将在三十秒后关闭。 为避免这种情况,请在运行下一步之前将文件放入存储桶中。 在注册表添加自己的对象后,您可以稍后将其删除。
如果您使用的是 DigitalOcean Spaces,您可以使用控制面板界面拖放来上传文件。
再次重新配置 GitLab:
sudo gitlab-ctl reconfigure
在您的另一台 Docker 机器上,再次登录注册表以确保一切正常:
docker login gitlab.example.com:5555
您应该会收到 Login Succeeded
消息。
现在我们已经设置了 Docker 注册表,让我们更新应用程序的 CI 配置以构建和测试我们的应用程序,并将 Docker 映像推送到我们的私有注册表。
第 3 步 — 更新 gitlab-ci.yaml
并构建 Docker 映像
要在 Docker 中构建我们的应用程序,我们需要更新 .gitlab-ci.yml
文件。 您可以直接在 GitLab 中编辑此文件,方法是从项目主页面单击它,然后单击 Edit 按钮。 或者,您可以将 repo 克隆到本地计算机,编辑文件,然后 git push
将其返回到 GitLab。 看起来像这样:
git clone git@gitlab.example.com:sammy/hello_hapi.git cd hello_hapi # edit the file w/ your favorite editor git commit -am "updating ci configuration" git push
首先,删除文件中的所有内容,然后粘贴以下配置:
.gitlab-ci.yml
image: docker:latest services: - docker:dind stages: - build - test - release variables: TEST_IMAGE: gitlab.example.com:5555/sammy/hello_hapi:$CI_COMMIT_REF_NAME RELEASE_IMAGE: gitlab.example.com:5555/sammy/hello_hapi:latest before_script: - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN gitlab.example.com:5555 build: stage: build script: - docker build --pull -t $TEST_IMAGE . - docker push $TEST_IMAGE test: stage: test script: - docker pull $TEST_IMAGE - docker run $TEST_IMAGE npm test release: stage: release script: - docker pull $TEST_IMAGE - docker tag $TEST_IMAGE $RELEASE_IMAGE - docker push $RELEASE_IMAGE only: - master
请务必使用您自己的信息更新突出显示的 URL 和用户名,然后使用 GitLab 中的 提交更改 按钮进行保存。 如果您在 GitLab 之外更新文件,请将更改和 git push
提交回 GitLab。
这个新的配置文件告诉 GitLab 使用最新的 docker 镜像(image: docker:latest
)并将其链接到 docker-in-docker 服务(docker:dind)。 然后定义 build
、test
和 release
阶段。 build
阶段使用 repo 中提供的 Dockerfile
构建 Docker 镜像,然后将其上传到我们的 Docker 镜像注册表。 如果成功,test
阶段将下载我们刚刚构建的图像并在其中运行 npm test
命令。 如果测试阶段成功,release
阶段将拉取镜像,将其标记为 hello_hapi:latest
并将其推送回注册表。
根据您的工作流程,您还可以添加额外的 test
阶段,甚至是 deploy
阶段,将应用程序推送到暂存或生产环境。
更新配置文件应该触发了新的构建。 返回 GitLab 中的 hello_hapi
项目并单击提交的 CI 状态指示器:
然后,在结果页面上,您可以单击任何阶段以查看其进度:
最终,所有阶段都应通过显示绿色复选标记图标来表明它们已成功。 我们可以通过点击左侧菜单中的Registry项找到刚刚构建的Docker镜像:
如果您单击图像名称旁边的小“文档”图标,它会将相应的 docker pull ...
命令复制到剪贴板。 然后,您可以拉取并运行您的图像:
docker pull gitlab.example.com:5555/sammy/hello_hapi:latest docker run -it --rm -p 3000:3000 gitlab.example.com:5555/sammy/hello_hapi:latest
Output> hello@1.0.0 start /usr/src/app > node app.js Server running at: http://56fd5df5ddd3:3000
映像已从注册表中拉下并在容器中启动。 切换到浏览器并连接到端口 3000 上的应用程序进行测试。 在这种情况下,我们在本地机器上运行容器,因此我们可以通过以下 URL 的 localhost 访问它:
http://localhost:3000/hello/test
OutputHello, test!
成功! 您可以使用 CTRL-C
停止容器。 从现在开始,每次我们将新代码推送到存储库的 master
分支时,我们都会自动构建和测试一个新的 hello_hapi:latest
映像。
结论
在本教程中,我们设置了一个新的 GitLab 运行程序来构建 Docker 映像,创建了一个私有 Docker 注册表来存储它们,并更新了一个 Node.js 应用程序,以便在 Docker 容器内构建和测试。
要了解有关此设置中使用的各种组件的更多信息,您可以阅读 GitLab CE、GitLab Container Registry 和 Docker 的官方文档。