使用 Docker 构建

栏目: 服务器 · 发布时间: 6年前

内容简介:使用 Docker 构建

使用 Docker 构建

GitLab CI 允许你使用 Docker Engine 构建和测试基于 Docker 的项目。

这也允许您使用 docker - compose 和其他 docker-enabled 的工具。

持续集成/持续部署的新趋势之一是:

  1. 创建应用程序镜像,
  2. 针对创建的镜像运行测试,
  3. 将镜像推送到远程 Registry,并
  4. 从推送的镜像部署到服务器。

当您的应用程序已经具有可用于创建和测试镜像的 Dockerfile 时,它也很有用:

[crayon-592837dc16763251780303 inline="true"  class="bash"]$ docker build -t my-image dockerfiles/
$ docker run my-docker-image /script/to/run/tests
$ docker tag my-image my-registry:5000/my-image
$ docker push my-registry:5000/my-image

[/crayon]

这需要 GitLab Runner 的特殊配置,以在作业期间启用 docker 支持。

Runner 配置

在作业中有三种方法可以使用 docker build docker run ,每个都有自己的考虑。

使用 Shell 执行器

最简单的方法是在 shell 执行模式下安装 GitLab Runner。然后 GitLab Runner 作为 gitlab - runner 用户执行作业脚本。

  1. 安装 GitLab Runner
  2. 在 GitLab Runner 安装期间,选择 shell 作为执行作业脚本或使用命令的方法:

    [crayon-592837dc1677f360374054 inline="true"  class="bash"]sudo gitlab-ci-multi-runner register -n \
      --url https://gitlab.com/ \
      --registration-token REGISTRATION_TOKEN \
      --executor shell \
      --description "My Runner"
    

    [/crayon]

  3. 在服务器上安装 Docker Engine。

    有关如何在不同系统上安装 Docker Engine 的更多信息,请参阅 Supported installations

  4. 新增 gitlab - runner 用户到 docker 组:

    [crayon-592837dc1678d581765961 inline="true"  class="bash"]sudo usermod -aG docker gitlab-runner
    

    [/crayon]

  5. 验证

    gitlab - runner

    是否可以访问Docker:
    [crayon-592837dc16797404884169 inline="true"  class="bash"]sudo -u gitlab-runner -H docker info
    

    [/crayon]

    现在你可以通过将 docker info 添加到 . gitlab - ci . yml 中来验证一切是否正常:

    [crayon-592837dc167a4437031041 inline="true"  class="yaml"]before_script:
      - docker info
     
    build_image:
      script:
        - docker build -t my-docker-image .
        - docker run my-docker-image /script/to/run/tests
    

    [/crayon]

  6. 现在可以使用 docker 命令,如果需要可以安装 docker - compose

注:

* 通过在 docker 组中添加 gitlab - runner ,你可以有效地授予 gitlab - runner 的完整的 root 权限。有关更多信息,请阅读 On Docker security: docker group considered harmful

使用 docker-in-docker 执行器

第二种方法是使用专门的 Docker 镜像 docker-in-docker(dind),它安装了所有工具( docker docker - compose ),并以特权模式在该镜像的上下文中运行作业脚本。

为了做到这一点,请按以下步骤操作:

  1. 安装 GitLab Runner
  2. 从命令行注册 GitLab Runner 以使用 docker privileged 模式:

    [crayon-592837dc167cd441193319 inline="true"  class="bash"]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
    

    [/crayon]

    上面的命令将注册一个新的 Runner 来使用 Docker 所提供的特殊 docker : latest 镜像。 请注意,它使用 privileged 模式启动构建和服务容器。 如果要使用 docker-in-docker 模式,您始终必须在 Docker 容器中使用 privileged = true

    上面的命令将创建一个类似于这个的 config . toml 条目:

    [crayon-592837dc167e2985324318 inline="true" ][[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
    

    [/crayon]

  3. 您现在可以在构建脚本中使用 docker

    (请注意包含

    docker : dind

    服务)
    [crayon-592837dc167ef144978683 inline="true"  class="yaml"]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
    

    [/crayon]

Docker-in-Docker 运行良好,是推荐的配置,但并不是没有挑战:

  • 启用 -- docker - privileged 禁用了容器的所有安全机制,并使你的主机由于特权升级而暴露,从而导致容器突破(主机-容器屏障)。有关更多信息,请查看官方 Docker 文档 Runtime privilege and Linux capabilities
  • 当使用 docker-in-docker 时,每个作业都处于一个干净的环境中,没有过去的历史。并发作业工作正常,因为每个构建都获得自己的 Docker Engine 实例,因此不会相互冲突。但这也意味着作业可能会更慢,因为没有缓存层。
  • 默认情况下, docker : dind 使用 -- storage - driver vfs ,这是最慢的形式。要使用其他驱动程序,请参阅使用 overlayfs 驱动程序。

使用这种方法的示例项目可以在这里找到: https://gitlab.com/gitlab-examples/docker .

Use Docker socket binding

第三种方法是将 / var / run / docker . sock 绑定装载到容器中,以便 docker 在该镜像的上下文中可用。

为了做到这点,遵循以下步骤:

  1. 安装 GitLab Runner .
  2. 从命令行注册 GitLab Runner 以使用 docker 并共享 / var / run / docker . sock

    [crayon-592837dc1680c834533733 inline="true"  class="bash"]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
    

    [/crayon]

    上面的命令将注册一个新的 Runner 来使用 Docker 提供的特殊 docker : latest 镜像。 请注意,它正在使用 Runner 本身的 Docker 守护进程,docker 命令产生的任何容器都将是 Runner 的兄弟,而不是所运行程序的子进程。 这可能会有不适合您的工作流程的复杂性和局限性。

    上面的命令将创建一个类似于这个的 config . toml 条目:

    [crayon-592837dc1681a405766012 inline="true" ][[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
    

    [/crayon]

  3. 您现在可以在构建脚本中使用 docker

    (请注意,在 Docker 执行器中使用 Docker 时,不需要包含

    docker : dind

    服务):
    [crayon-592837dc16829831249836 inline="true"  class="yaml"]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
    

    [/crayon]

虽然上述方法避免在特权模式下使用 Docker,但您应该了解以下影响:

  • 共享 docker 守护进程,禁用了容器的所有安全机制,并将主机暴露给特权提升,从而导致容器突破屏障。例如,如果一个项目运行 docker rm - f $ ( docker ps - a - q ) ,它将删除 GitLab Runner 容器。
  • 并发作业可能无效;如果你的测试创建了具有特定名称的容器,它们可能会相互冲突。
  • 将文件和目录从源代码库共享到容器中可能无法正常工作,因为卷装载是在主机上下文中完成的,而不是在构建容器中,例如:
    [crayon-592837dc1683d116571021 inline="true" ]docker run --rm -t -i -v $(pwd)/src:/home/app/src test-image:latest run_app_tests
    

    [/crayon]

使用 OverlayFS 驱动程序

默认情况下,使用 docker : dind 时,Docker 使用 vfs 存储驱动程序,每次运行时都会拷贝文件系统。磁盘操作非常密集,如果使用不同的驱动程序(例如 overlay ),则可以避免这种情况。

  1. 确保使用最近的内核,最好是 & gt ; = 4.2
  2. 检查

    overlay

    模块是否加载:
    [crayon-592837dc16861671092748 inline="true" ]sudo lsmod | grep overlay
    

    [/crayon]

    如果没有结果,那就没有加载。加载之:

    [crayon-592837dc1686d334243037 inline="true" ]sudo modprobe overlay
    

    [/crayon]

    如果一切顺利,您需要确保在系统重启时也加载该模块。Ubuntu 系统上是通过编辑 / etc / modules 完成的。添加以下行:

    [crayon-592837dc16880144867623 inline="true" ]overlay
    

    [/crayon]

  3. . gitlab - ci . yml

    顶部定义一个变量以使用该驱动:
    [crayon-592837dc16892252317096 inline="true" ]variables:
      DOCKER_DRIVER: overlay
    

    [/crayon]

使用 GitLab 容器 Registry

注:

– 此功能需要 GitLab 8.8 和 GitLab Runner 1.2。

– 从 GitLab 8.12 开始,如果你的帐户启用了两步认证,则需要传递个人访问令牌而不是密码,才能登录到 GitLab 的 Container Registry。

一旦构建了 Docker 镜像,就可以将其推送到内置的GitLab 容器 Registry 中。例如,如果你在 runner 上使用 docker-in-docker,那 . gitlab - ci . yml 可能如下:

[crayon-592837dc1689f983583603 inline="true"  class="yaml"] 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

[/crayon]

必须使用为你创建的特殊 gitlab - ci - token 用户,才能推送到连接到项目的 Registry。它的密码由 $ CI_JOB_TOKEN 变量提供。这允许您自动构建和部署 Docker 镜像。

您也可以利用其他变量来避免硬编码:

[crayon-592837dc168b8321264291 inline="true"  class="yaml"]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

[/crayon]

在这里, $ CI_REGISTRY_IMAGE 将解析为与该项目相关联的 Registry 地址, $ CI_COMMIT_REF_NAME 将解析为该作业所在分支或标签的名称。还声明了我们自己的变量 $ IMAGE_TAG ,将两者结合起来,以节省我们在 script 部分中的输入。

这是一个更详细的例子,将任务分解为 4 个流水线(pipeline)阶段,包括并行运行的两个测试。 build 存储在容器 Registry 中,并在后续阶段使用,需要时则下载该镜像。对 master 的更改也被标记为 latest ,并使用特定于应用程序的部署脚本进行部署:

[crayon-592837dc168ee226130640 inline="true"  class="yaml"]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

[/crayon]

使用容器 Registry 的注意事项:

  • 在运行命令之前必须先登录到容器 Registry。把它放在 before_script 里,会在每个作业之前运行它。
  • 使用 docker build -- pull 可以确保 Docker 在构建前获取 base 镜像的任何更改,以防您的缓存失效。这需要运行更长时间,但意味着不会遇到未打安全补丁的 base 镜像。
  • 在每个 docker run 之前做一个明确的 docker pull ,确保获取刚构建的最新镜像。如果您正在使用多个会在本地缓存镜像的 Runner,这一点尤为重要。在镜像标签中使用 git SHA 又使得这不太必要,因为每个作业都将是唯一的,并且您不应该有一个过时的镜像,但是如在依赖更改后,重新构建给定的 Commit,这仍然可能(有过时的镜像)。
  • 同时发生多个作业的情况下,你不会想直接构建为 latest

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Two Scoops of Django

Two Scoops of Django

Daniel Greenfeld、Audrey M. Roy / CreateSpace Independent Publishing Platform / 2013-4-16 / USD 29.95

Two Scoops of Django: Best Practices For Django 1.5 is chock-full of material that will help you with your Django projects. We'll introduce you to various tips, tricks, patterns, code snippets, and......一起来看看 《Two Scoops of Django》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换