使用GitLab构建Docker镜像并托管

介绍

容器化正迅速成为在云环境中打包和部署应用程序的最常用方法。它提供的标准化,以及其资源效率和灵活性,使其成为现代DevOps思维模式的重要推动者。当您的应用程序和微服务完全集装箱化时,许多有趣的云本机部署,编排和监控策略都成为可能。

Docker容器是目前最常见的容器类型。虽然有像Docker Hub这样的公共Docker镜像存储库,但对于私有代码,您需要支付服务来构建和存储您的映像,或者运行您自己的软件来执行此操作。

GitLab Community Edition是一个自托管软件套件,提供Git存储库托管,项目跟踪,CI/CD服务和Docker镜像注册表等功能。在本教程中,我们将使用GitLab的持续集成服务从示例Node.js应用程序构建Docker镜像。然后将测试这些镜像并将其上传到我们自己的私有Docker注册表。

准备

在开始之前,我们需要一台已经设置好可以使用sudo命令的非root账号的Ubuntu服务器,并且已开启防火墙。没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后在购买服务器。。要存储我们的源代码,运行CI / CD任务以及托管Docker注册表,我们需要在Ubuntu服务器上安装GitLab实例。GitLab目前推荐一款至少具有2个CPU内核和4GB内存的服务器。此外,我们将使用腾讯云的SSL证书来保护服务器。如何设置此SSL证书取决于你是否拥有可解析该服务器的域名。

并且,您需要学会在如何在Ubuntu 16.04上安装和配置GitLab

第一步 - 设置特权GitLab运行器

在准备介绍的如何在Ubuntu 16.04上安装和配置GitLab教程中,我们使用sudo gitlab-runner register设置了一个GitLab运行器。该运行器能够在隔离的Docker容器内运行软件的构建和测试。

但是,为了构建Docker镜像,我们的需要完全访问Docker服务本身。建议的配置方法是使用Docker的官方docker-in-docker映像来运行作业。这需要授予特殊的privileged执行模式,因此我们将在启用此模式的情况下创建第二个runner

因为使用特权runner会对安全性产生影响,所以我们将创建一个特定于项目的运行器,它只接受我们hello_hapi项目中的Docker作业。在hello_hapi项目页面中,单击左侧菜单底部的“设置”,然后单击子菜单中的“CI / CD ”:

现在单击Runners settings部分旁边的Expand按钮:

将提供有关设置特定运行器的一些信息,包括注册令牌。请记住这些内容。当我们使用它来注册新runner时,runner将仅被锁定到此项目。

当我们在此页面上时,单击“Disable shared Runners”按钮。我们希望确保我们的Docker作业始终在我们的特权runner上运行。如果有一个非特权共享runner可用,GitLab可能会选择使用那个,这会导致构建错误。

登录到当前CI运行器的服务器。

现在,运行以下命令来设置特权项目特定的运行程序:

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
Registering 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模式。

您的runner现在已经设置,注册并正在运行。要验证,请切换回浏览器。单击GitLab主菜单栏中的扳手图标,然后单击左侧菜单中的Runners。您的runner将被列出:

现在我们有一个能够构建Docker镜像的runner,让我们为它设置一个私有的Docker注册表来推送镜像。

第二步 - 设置GitLab的Docker Registry

通过设置自己的Docker注册表,您可以从自己的私有服务器推送和提取镜像,从而提高安全性并减少工作流对外部服务的依赖性。

只需几个配置更新,GitLab就会设置一个私有的Docker注册表。首先,我们将设置注册表所在的URL。然后,我们将(可选)配置注册表以使用与S3兼容的对象存储服务来存储其数据。

SSH到您的GitLab服务器,然后打开GitLab配置文件:

sudo nano /etc/gitlab/gitlab.rb

向下滚动到Container Registry设置部分。我们将取消注释registry_external_url行并将其设置为我们的GitLab主机名,其端口号为5555

registry_external_url 'https://gitlab.example.com:5555'

接下来,添加以下两行以告知注册表在哪里可以找到我们的腾讯云证书:

registry_nginx['ssl_certificate'] = "/etc/Tencent_cloud_SSL/live/gitlab.example.com/fullchain.pem"
registry_nginx['ssl_certificate_key'] = "/etc/Tencent_cloud_SSL/live/gitlab.example.com/privkey.pem"

保存并关闭该文件,然后重新配置GitLab:

sudo gitlab-ctl reconfigure
. . .
gitlab Reconfigured!

更新防火墙以允许流量到注册表端口:

sudo ufw allow 5555

现在切换到安装了Docker的另一台机器,并登录到私有Docker注册表。如果您的本地开发计算机上没有Docker,则可以使用设置的任何服务器来运行GitLab CI作业,因为它已经安装了Docker:

docker login gitlab.example.com:5555

系统将提示您输入用户名和密码。使用您的GitLab凭据登录。

Login Succeeded

成功!注册表已设置并正常工作。目前,它将文件存储在GitLab服务器的本地文件系统上。

第三步 - 更新gitlab-ci.yaml和构建Docker镜像

要在Docker中构建我们的应用程序,我们需要更新.gitlab-ci.yml文件。您可以直接在GitLab中编辑此文件,方法是从主项目页面单击它,然后单击编辑按钮。或者,您可以将repo克隆到本地计算机,编辑文件,然后再将gitpush复制回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(image:docker:latest)并将其链接到docker-in-docker服务(docker:dind)。然后定义buildtestreleasebuild使用repo中提供的Dockerfile构建Docker镜像,然后将其上传到我们的Docker镜像注册表。如果成功,test阶段将下载我们刚刚构建的镜像并在其中运行npm test命令。如果测试阶段成功,则阶段将下载release镜像,将其标记为hello_hapi:latest并将其推回到注册表。

根据您的工作流程,您还可以添加其他test阶段,甚至是将应用程序推送到临时或生产环境的deploy阶段。

更新配置文件应该已触发新构建。返回hello_hapiGitLab中的项目,然后单击提交的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
> 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
Hello, test!

成功!你可以用CTRL-C来停止容器。从现在开始,每次我们将新代码推送到我们的存储库的master分支时,我们都会自动构建并测试新的hello_hapi:latest镜像。

结论

在本教程中,我们设置了一个新的GitLab运行器来构建Docker镜像,创建了一个私有Docker注册表来存储它们,并更新了一个Node.js应用程序,用于在Docker容器内构建和测试。更多Linux教程请前往腾讯云+社区学习更多知识。


参考文献:《How To Build Docker Images and Host a Docker Image Repository with GitLab》

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏田飞雨的专栏

Docker 使用指南 (三)—— 网络配置

本文详细介绍了Docker网络配置的四个模式,以及模式下的具体配置操作。希望对入门,Docker的童鞋有所帮助。

4.5K00
来自专栏木制robot技术杂谈

使用 docker-compose 在 Docker 中启动带密码的 Redis

在服务器上使用 docker-compose 启动一个 Docker 中的 Redis 时,配置文件没有生效,Redis 没有加密码,导致 redis 中被写入...

3.1K20
来自专栏编程坑太多

跟我一起学docker(二)--核心概念和安装

19740
来自专栏魏艾斯博客www.vpsss.net

windows 下如何生成 tar 或 gz 压缩包

32240
来自专栏漫漫全栈路

Docker渐入佳境

以网站服务为例,一般需要80端口,那么如何使容器的端口能被外界访问得到呢?这就要用到容器的端口映射。

25670
来自专栏IT笔记

内网文库搭建备忘录

13330
来自专栏Janti

每天学一点Docker(3)(制作你的第一个容器)

今天开始制作第一个容器,其实很简单 首先你要准备这些条件: 1.一个Ubuntu系统 2.这个系统能够联网,最起码ping www.baidu.com是可以的 ...

40170
来自专栏糊一笑

centos中docker的安装

21030
来自专栏刘君君

Docker在Ubuntu下私服搭建

50040
来自专栏A周立SpringCloud

用户定义网络中的内嵌DNS服务器

本节中的信息涵盖用户自定义网络中的容器的内嵌DNS服务器操作。连接到用户自定义网络的容器的DNS lookup与连接到默认 bridge 网络的容器的工作机制不...

32150

扫码关注云+社区

领取腾讯云代金券