GitLab Runner配置在作业中有三种方法可以使用 docker build 和 docker run ,每个都有自己的考虑。
一、使用 Shell 执行器
最简单的方法是在 shell 执行模式下安装 GitLab Runner。然后 GitLab Runner 作为 gitlab -runner 用户执行作业脚本。
安装 GitLab Runner 。
在 GitLab Runner 安装期间,选择 shell 作为执行作业脚本或使用命令的方法:
sudo gitlab-ci-multi-runner register -n \
--url https://gitlab.com/ \
--registration-token REGISTRATION_TOKEN \
--executor shell \
--description "My Runner"
有关如何在不同系统上安装 Docker Engine 的更多信息,请参阅 Supported installations 。
sudo usermod -aG docker gitlab-runner
gitlab - runner 是否可以访问Docker:
sudo -u gitlab-runner -H docker info
现在你可以通过将 docker info 添加到 . gitlab - ci . yml 中来验证一切是否正常:
before_script:
- docker info
build_image:
script:
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests
注:通过在 docker 组中添加 gitlab - runner ,你可以有效地授予 gitlab - runner 的完整的 root 权限。有关更多信息,请阅读 On Docker security: docker group considered harmful 。
二、使用 docker-in-docker 执行器
第二种方法是使用专门的 Docker 镜像 docker-in-docker(dind),它安装了所有工具( docker和 docker - compose ),并以特权模式在该镜像的上下文中运行作业脚本。为了做到这一点,请按以下步骤操作:
sudo gitlab-ci-multi-runner register -n \--url https://gitlab.com/ \
--registration-token REGISTRATION_TOKEN \
--executor docker \
--description "My Docker Runner" \
--docker-image "docker:latest" \
--docker-privileged
上面的命令将注册一个新的 Runner 来使用 Docker 所提供的特殊 docker : latest 镜像。 请注意,它使用 privileged 模式启动构建和服务容器。 如果要使用 docker-in-docker 模式,您始终必须在 Docker 容器中使用 privileged = true 。
上面的命令将创建一个类似于这个的 config . toml 条目:
[[runners]]
url = "https://gitlab.com/"
token = TOKEN
executor = "docker"
[runners.docker]
tls_verify = false
image = "docker:latest"
privileged = true
disable_cache = false
volumes = ["/cache"]
[runners.cache]
Insecure = false
(请注意包含docker : dind服务)
image: docker:latest
# When using dind, it's wise to use the overlayfs driver for
# improved performance.
variables:
DOCKER_DRIVER: overlay
services:
- docker:dind
before_script:
- docker info
build:
stage: build
script:
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests
Docker-in-Docker 运行良好,是推荐的配置,但并不是没有挑战:
使用这种方法的示例项目可以在这里找到: https://gitlab.com/gitlab-examples/docker .
三、Use Docker socket binding
第三种方法是将 / var / run / docker . sock 绑定装载到容器中,以便 docker 在该镜像的上下文中可用。为了做到这点,遵循以下步骤:
sudo gitlab-ci-multi-runner register -n \
--url https://gitlab.com/ \
--registration-token REGISTRATION_TOKEN \
--executor docker \
--description "My Docker Runner" \
--docker-image "docker:latest" \
--docker-volumes /var/run/docker.sock:/var/run/docker.sock
上面的命令将注册一个新的 Runner 来使用 Docker 提供的特殊 docker : latest 镜像。 请注意,它正在使用 Runner 本身的 Docker 守护进程,docker 命令产生的任何容器都将是 Runner 的兄弟,而不是所运行程序的子进程。 这可能会有不适合您的工作流程的复杂性和局限性。
上面的命令将创建一个类似于这个的 config . toml 条目:
[[runners]]
url = "https://gitlab.com/"
token = REGISTRATION_TOKEN
executor = "docker"
[runners.docker]
tls_verify = false
image = "docker:latest"
privileged = false
disable_cache = false
volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
[runners.cache]
Insecure = false
(请注意,在 Docker 执行器中使用 Docker 时,不需要包含docker : dind服务):
image: docker:latest
before_script:
- docker info
build:
stage: build
script:
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests
虽然上述方法避免在特权模式下使用 Docker,但您应该了解以下影响:
docker run --rm -t -i -v $(pwd)/src:/home/app/src test-image:latest run_app_tests
四、使用 OverlayFS 驱动程序
默认情况下,使用 docker : dind 时,Docker 使用 vfs 存储驱动程序,每次运行时都会拷贝文件系统。磁盘操作非常密集,如果使用不同的驱动程序(例如 overlay ),则可以避免这种情况。
sudo lsmod | grep overlay
如果没有结果,那就没有加载。加载之:
sudo modprobe overlay
如果一切顺利,您需要确保在系统重启时也加载该模块。Ubuntu 系统上是通过编辑 / etc /modules 完成的。
variables:
DOCKER_DRIVER: overlay
五、使用 GitLab 容器 Registry
一旦构建了 Docker 镜像,就可以将其推送到内置的GitLab 容器 Registry 中。例如,如果你在 runner 上使用 docker-in-docker,那 . gitlab - ci . yml 可能如下:
build:
image: docker:latest
services:
- docker:dind
stage: build
script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.example.com
- docker build -t registry.example.com/group/project/image:latest .
- docker push registry.example.com/group/project/image:latest
必须使用为你创建的特殊 gitlab - ci - token 用户,才能推送到连接到项目的 Registry。它的密码由 $ CI_JOB_TOKEN 变量提供。这允许您自动构建和部署 Docker 镜像。您也可以利用其他变量来避免硬编码:
services:
- docker:dind
variables:
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
before_script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
build:
stage: build
script:
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
在这里, $ CI_REGISTRY_IMAGE 将解析为与该项目相关联的 Registry 地址, $CI_COMMIT_REF_NAME 将解析为该作业所在分支或标签的名称。还声明了我们自己的变量 $IMAGE_TAG ,将两者结合起来,以节省我们在 script 部分中的输入。
这是一个更详细的例子,将任务分解为 4 个流水线(pipeline)阶段,包括并行运行的两个测试。build 存储在容器 Registry 中,并在后续阶段使用,需要时则下载该镜像。对 master 的更改也被标记为 latest ,并使用特定于应用程序的部署脚本进行部署:
image: docker:latest
services:
- docker:dind
stages:
- build
- test
- release
- deploy
variables:
CONTAINER_TEST_IMAGE: registry.example.com/my-group/my-project/my-
image:$CI_COMMIT_REF_NAME
CONTAINER_RELEASE_IMAGE: registry.example.com/my-group/my-project/my-image:latest
before_script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.example.com
build:
stage: build
script:
- docker build --pull -t $CONTAINER_TEST_IMAGE .
- docker push $CONTAINER_TEST_IMAGE
test1:
stage: test
script:
- docker pull $CONTAINER_TEST_IMAGE
- docker run $CONTAINER_TEST_IMAGE /script/to/run/tests
test2:
stage: test
script:
- docker pull $CONTAINER_TEST_IMAGE
- docker run $CONTAINER_TEST_IMAGE /script/to/run/another/test
release-image:
stage: release
script:
- docker pull $CONTAINER_TEST_IMAGE
- docker tag $CONTAINER_TEST_IMAGE $CONTAINER_RELEASE_IMAGE
- docker push $CONTAINER_RELEASE_IMAGE
only:
- master
deploy:
stage: deploy
script:
- ./deploy.sh
only:
- master
使用容器 Registry 的注意事项: