DinD 与 Gitlab CI
像大多数开发人员一样,我们希望能够自动化尽可能多的流程。将 Docker 映像推送到注册表是一项可以轻松自动化的任务。在本文中,我们将介绍如何使用 Gitlab CI 构建 Docker 映像并将其发布到 Gitlab 注册表。但是,您也可以非常轻松地编辑它以将您的图像也推送到 DockerHub。 关于 Docker 相关术语的简要说明: 容器:图像的一个实例称为容器(docker run) 图
像大多数开发人员一样,我们希望能够自动化尽可能多的流程。将 Docker 映像推送到注册表是一项可以轻松自动化的任务。在本文中,我们将介绍如何使用 Gitlab CI 构建 Docker 映像并将其发布到 Gitlab 注册表。但是,您也可以非常轻松地编辑它以将您的图像也推送到 DockerHub。
关于 Docker 相关术语的简要说明:
-
容器:图像的一个实例称为容器(
docker run
) -
图像:一组不可变层 (
docker build
) -
hub:官方注册中心,您可以从 (
docker pull
) 获取更多 Docker 镜像
示例
这是一个示例.gitlab-ci.yml
文件,可用于构建 Docker 映像并将其推送到 Gitlab 注册表。
variables:
DOCKER_DRIVER: overlay2
services:
- docker:dind
stages:
- publish
publish-docker:
stage: publish
image: docker
script:
- export VERSION_TAG=v1.2.3
- docker login ${CI_REGISTRY} -u gitlab-ci-token -p ${CI_BUILD_TOKEN}
- docker build -t ${CI_REGISTRY_IMAGE}:latest -t ${CI_REGISTRY_IMAGE}:${VERSION_TAG} .
- docker push ${CI_REGISTRY_IMAGE}:latest
- docker push ${CI_REGISTRY_IMAGE}:${VERSION_TAG}
进入全屏模式 退出全屏模式
解释
上面的代码可能有点混乱,可能需要学习很多。所以现在我们将逐行分解。
variables:
DOCKER_DRIVER: overlay2
进入全屏模式 退出全屏模式
在我们的前几行中,我们定义了一些将被所有工作使用的变量(这些变量是全局的)。我们定义了一个变量DOCKER_DRIVER: overlay2
,这有助于加快我们的 Docker 容器的速度,因为默认情况下它使用vfs
,它更慢在此处了解更多信息。
random-job:
stage: publish
variables:
DOCKER_DRIVER: overlay2
script:
- echo "HELLO"
进入全屏模式 退出全屏模式
请注意,我们可以在我们的工作中轻松定义
variables
,就像您在上面的示例中看到的一样。
services:
- docker:dind
进入全屏模式 退出全屏模式
接下来的几行定义了一个服务。服务是在我们的工作期间链接的 Docker 映像。同样在此示例中,它是全局定义的,并将链接到我们所有的工作。我们可以很容易地在我们的工作中定义它,就像在variables
示例中一样。docker:dind
映像自动使用其entrypoint
启动 docker 守护进程。我们需要使用这个守护进程在 CI 中构建/推送我们的 Docker 镜像。
docker:dind
(dind u003d Docker in Docker)镜像与docker
镜像几乎相同。不同之处在于 dind 映像启动了一个 Docker 守护进程。在此示例中,作业将使用docker
映像作为客户端并连接到在此容器中运行的守护程序。
我们也可以只在工作中使用dind
图像,并在第一行简单地启动dockerd
(& u003d 在后台)。dockerd
命令将 Docker 守护进程作为客户端启动,因此我们可以与其他 Docker 守护进程通信。它会达到同样的结果。我认为服务方法更干净一些,但正如已经说过的那样,任何一种方法都行得通。
publish-docker:
stage: publish
image: docker:dind
script:
- dockerd &
...
- docker push ${CI_REGISTRY_IMAGE}:${VERSION_TAG}
进入全屏模式 退出全屏模式
信息:Gitlab CI 服务的一个常见用例是启动 MySQL 等数据库。然后我们可以在我们的工作中连接到它,运行我们的测试。它可以大大简化我们的工作。
注意:我们还可以通过其他几种方式构建/推送我们的图像。这是推荐的方法。
stages:
- publish
进入全屏模式 退出全屏模式
接下来,我们定义我们的阶段并给它们命名。每个作业都必须附加一个有效的阶段。阶段用于确定作业何时在我们的 CI 管道中运行。如果两个作业具有相同的阶段,那么它们将并行运行。前面定义的阶段将首先运行,因此顺序很重要。然而在这个例子中,我们只有一个阶段和一个工作,所以这不是很重要,更多的是要记住的事情。
publish-docker:
stage: publish
...
进入全屏模式 退出全屏模式
现在我们定义我们的工作,其中publish-docker
是我们在Gitlab CI
管道上的工作名称。然后我们定义作业应该在什么stage
中运行,在这种情况下,该作业将在publish
阶段运行。
publish-docker:
...
image: docker
...
进入全屏模式 退出全屏模式
然后我们定义在这个作业中使用什么 Docker 镜像。在这项工作中,我们将使用docker
图像。这个镜像有我们需要的所有命令来build
和push
我们的 Docker 镜像。它将作为客户端向dind
守护进程发出请求。
script:
- export VERSION_TAG=v1.2.3
- docker login ${CI_REGISTRY} -u gitlab-ci-token -p ${CI_BUILD_TOKEN}
- docker build -t ${CI_REGISTRY_IMAGE}:latest -t ${CI_REGISTRY_IMAGE}:${VERSION_TAG} .
- docker push ${CI_REGISTRY_IMAGE}:latest
- docker push ${CI_REGISTRY_IMAGE}:${VERSION_TAG}
进入全屏模式 退出全屏模式
最后,我们得到了 CI 文件的真正内容。构建和推送的代码是 Docker 镜像到注册表:
- export VERSION_TAG=v1.2.3
进入全屏模式 退出全屏模式
标记我们的图像通常是一个好主意,在这种情况下,我使用的是发布名称。你也可以从你的setup.py
或package.json
文件中得到这个。在我的 Python 项目中,我通常使用这个命令export VERSION_TAG=$(cat setup.py | grep version | head -1 | awk -F= '{ print $2 }' | sed 's/[",]//g' | tr -d "'")
来解析我的setup.py
以获得版本号。但这可以是你想要的任何东西。在这里,我们只是将其保持为静态以使事情变得更简单,但实际上,您可能希望以编程方式检索它(版本号)。
- docker login ${CI_REGISTRY} -u gitlab-ci-token -p ${CI_BUILD_TOKEN}
进入全屏模式 退出全屏模式
然后我们登录到我们的 Gitlab 注册表,环境变量$CI_REGISTRY
和CI_BUILD_TOKEN
是预定义的 Gitlab 变量,它们被注入到我们的环境中。你可以在这里阅读更多关于它们的信息。由于我们正在推送到我们的 Gitlab 注册表,因此我们可以只使用在环境中定义的凭据,即username=gitlab-ci-token
并为一次性令牌提供密码。
注意:您只能在受保护的分支/标签上执行此操作。
- docker build -t ${CI_REGISTRY_IMAGE}:latest -t ${CI_REGISTRY_IMAGE}:${VERSION_TAG} .
- docker push ${CI_REGISTRY_IMAGE}:latest
- docker push ${CI_REGISTRY_IMAGE}:${VERSION_TAG}
进入全屏模式 退出全屏模式
最后,我们运行我们的常规命令来构建和推送我们的图像。您可以找到图片的位置取决于项目名称和您的用户名,但应遵循此格式
registry.gitlab.com/<username>/<project_name>/<tag>
进入全屏模式 退出全屏模式
(可选)推送到DockerHub
- docker login -u hmajid2301 -p ${DOCKER_PASSWORD}
- export IMAGE_NAME="hmajid2301/example_project"
- docker build -t ${IMAGE_NAME}:latest -t ${IMAGE_NAME}:${VERSION_TAG} .
- docker push ${IMAGE_NAME}:latest
- docker push ${IMAGE_NAME}:${VERSION_TAG}
进入全屏模式 退出全屏模式
我们还可以使用上面的代码将我们的图像推送到 DockerHub。我们需要先登录到 DockerHub。然后将我们的图像名称更改为<username>/<project_name>
。
附录
-
好 SO 后
-
Gitlab CI 文档
-
Gitlab 示例
更多推荐
所有评论(0)