介绍
容器化正在迅速成为在云环境中打包和部署应用程序的最被接受的方法。 它提供的标准化以及其资源效率(与完整虚拟机相比)和灵活性使其成为现代DevOps思维模式的强大推动力。 当您的应用程序和微服务完全容器化时,许多有趣的云本地部署,编排和监控策略成为可能。
Docker容器是目前最常用的容器类型。 尽管像Docker Hub这样的公共Docker镜像仓库充满了您可以在今天使用Docker并使用的容器式开源软件镜像,但您需要私有代码来支付服务来构建和存储图像,或者运行自己的软件以这样做。
GitLab Community Edition是一个自托管软件套件,提供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内存的服务器 。
您可以通过以下教程完成这些先决条件要求:
- 使用Ubuntu 16.04的初始服务器安装程序将获得一个非超级用户,启用sudo的用户,并启用Ubuntu的
ufw
防火墙 - 如何在Ubuntu 16.04上安装和配置GitLab将向您展示如何安装和配置GitLab
另外,我们将使用来自Let's Encrypt的SSL证书来保护服务器。 为此,您需要一个指向服务器的域名:
- 如何使用DigitalOcean设置主机名将告诉您如何使用DigitalOcean控制面板管理域
- 如何保护GitLab让我们在Ubuntu 16.04上加密包括安装Certbot Let's Encrypt客户端,下载SSL证书以及更新GitLab的配置以使用这些证书
一个GitLab CI Runner
如何在Ubuntu 16.04上使用GitLab CI设置持续集成管道将为您提供GitLab CI服务的概述,并向您展示如何设置CI runner来处理作业。 我们将在本教程中创建的演示应用程序和运行器基础结构之上进行构建。
第1步 - 设置特权GitLab CI亚军
在必备的GitLab持续集成教程中,我们使用sudo gitlab-runner register
及其交互式配置过程设置了一个GitLab运行器。 该跑步者能够在隔离的Docker容器内运行软件的构建和测试。
但是,为了构建Docker镜像,我们的运行者需要完全访问Docker服务本身。 推荐的配置方式是使用Docker官方的docker-in-docker
镜像来运行作业。 这要求授予跑步者一个特殊的privileged
执行模式,所以我们将创建一个启用此模式的第二跑步者。
注意:授予runner 特权模式基本上禁用了使用容器的所有安全优势。 不幸的是,支持Docker的跑步者的其他方法也带有类似的安全隐患。 请查看Docker Build官方GitLab文档 ,了解更多关于不同跑步选项的信息,以及哪种最适合您的情况。
因为使用特权跑步者有安全隐患,所以我们将创建一个项目特定的跑步者,它只接受我们的hello_hapi
项目中的Docker作业(GitLab管理员可以随时手动将此跑步者添加到其他项目中)。 在您的hello_hapi
项目页面中,单击左侧菜单底部的设置 ,然后在子菜单中单击CI / CD :
现在点击跑步者设置部分旁边的展开按钮:
会有一些关于设置特定跑步者的信息 ,包括注册令牌。 记下这个令牌。 当我们使用它来注册一个新的跑步者时,跑步者只会被锁定到这个项目。
当我们在这个页面上时,点击禁用共享运行程序按钮。 我们希望确保我们的Docker作业始终运行在我们的特权运行器上。 如果一个非特权的共享运行器可用,GitLab可能会选择使用该运行器,这会导致构建错误。
登录到具有您当前的CI运行器的服务器。 如果您尚未安装机器,请返回并完成安装GitLab CI Runner服务
在继续之前,先决条件教程的一部分。
现在,运行以下命令来设置特权项目特定的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!
一定要替换你自己的信息。 我们在命令行中设置了所有的runner选项,而不是使用交互式提示,因为提示不允许我们指定--docker-privileged
模式。
你的跑步者现在已经建立,注册并且正在运行。 要验证,请切换回您的浏览器。 点击主GitLab菜单栏中的扳手图标,然后点击左侧菜单中的Runners 。 你的选手将被列出:
现在我们有了一个能够构建Docker镜像的跑步者,让我们设置一个私人Docker注册表来将它推送到。
第2步 - 设置GitLab的Docker注册表
通过设置自己的Docker注册表,您可以从自己的专用服务器上推送和提取图像,从而提高安全性并减少工作流对外部服务的依赖性。
GitLab将设置一个私人Docker注册表,只需进行一些配置更新。 首先,我们将设置注册管理机构所在的URL。 然后,我们将(可选)配置注册表以使用S3兼容对象存储服务来存储其数据。
SSH到你的GitLab服务器,然后打开GitLab配置文件:
sudo nano /etc/gitlab/gitlab.rb
向下滚动到容器注册表设置部分。 我们将取消registry_external_url
行并将其设置为端口号为5555
我们的GitLab主机名:
registry_external_url 'https://gitlab.example.com:5555'
接下来,添加以下两行来告诉注册表在哪里可以找到我们的加密证书:
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步。
要为注册表设置对象存储后端,我们需要知道关于对象存储服务的以下信息:
- 访问密钥
- 密钥
- 例如,如果使用Amazon S3,则使用Region (
us-east-1
);如果使用S3兼容服务,则使用Region Endpoint (https://nyc.digitaloceanspaces.com
) - 存储桶名称
如果您使用DigitalOcean Spaces,您可以通过阅读如何创建DigitalOcean空间和API密钥来了解如何设置新空间并获取上述信息。
当你有你的对象存储信息时,打开GitLab配置文件:
sudo nano /etc/gitlab/gitlab.rb
再次向下滚动到容器注册表部分。 查找registry['storage']
块,取消注释,并将其更新为以下内容,并再次确保在适当的情况下替换自己的信息:
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
并不实际配置任何内容,并且您输入的值不重要,但它仍然需要存在而不是空白。
保存并关闭文件。
注意:目前存在一个错误,如果您的对象存储桶为空,注册表将在三十秒后关闭。 为避免这种情况,请在运行下一步之前在文件夹中放入一个文件。 您可以稍后在注册表添加自己的对象后将其删除。
如果您正在使用DigitalOcean Spaces,则可以使用控制面板界面进行拖放以上载文件。
重新配置GitLab一次:
sudo gitlab-ctl reconfigure
在您的其他Docker机器上,再次登录到注册表以确保一切正常:
docker login gitlab.example.com:5555
你应该得到一个Login Succeeded
消息。
现在我们已经设置了Docker注册表,让我们更新应用程序的CI配置,以构建和测试我们的应用程序,并将Docker映像推送到我们的私有注册表。
第3步 - 更新gitlab-ci.yaml
并构建Docker镜像
注意:如果您没有完成关于GitLab CI的先决条件文章,您需要将示例存储库复制到您的GitLab服务器。 遵循从GitHub部分复制示例存储库部分来执行此操作。
为了在Docker中构建我们的应用程序,我们需要更新.gitlab-ci.yml
文件。 您可以在GitLab中通过在主项目页面中单击该文件,然后单击编辑按钮来编辑该文件。 或者,您可以将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
首先,删除文件中的所有内容,然后粘贴以下配置:
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
阶段使用Dockerfile
提供的Dockerfile
构建Docker镜像,然后将其上传到Docker镜像注册表。 如果成功, test
阶段将下载我们刚刚构建的镜像,并在其中npm test
命令。 如果测试阶段成功,则release
阶段将拉取图像,将其标记为hello_hapi:latest
并将其推回注册表。
根据您的工作流程,您还可以添加额外的test
阶段,甚至可以deploy
将应用程序推送到分段或生产环境的阶段。
更新配置文件应该触发了一个新的版本。 返回到GitLab中的hello_hapi
项目,然后单击CI状态指示器进行提交:
在结果页面上,您可以点击任何阶段查看进度:
最终,所有阶段都应通过显示绿色复选标记图标表明他们已成功。 我们可以通过单击左侧菜单中的注册表项来找到刚构建的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访问它:
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的官方文档。