调试失败的Docker构建在Gitlab CI上并执行中间层

时间:2018-08-19 21:32:54

标签: docker debugging dockerfile gitlab-ci docker-build

我想知道如何通过执行中间构建层并在该层外运行调试容器来监视其中的内容来调试Docker构建。

因为在任何地方都找不到答案,所以我创建了自定义解决方案,效果很好(见下文)。

1 个答案:

答案 0 :(得分:0)

解决方案

我在管道中添加了debug-failed-build作业,该作业将该层作为docker映像上传到Gitlabs Docker注册表:

.gitlab-registry-login: &local-registry-login
  docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"

build:
  stage: build
  script:
    - *local-registry-login
    - docker build --pull -t "${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}" . | tee docker-build-debug.out
    - docker push "${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}"
  artifacts:
    paths:
      - docker-build-debug.out
    when: on_failure
    expire_in: 30 mins

debug-failed-build:
  stage: debug
  script:
    - *local-registry-login
    - DEBUG_LAYER=$(grep '\-\-\-> [0-9a-z]' docker-build-debug.out |tail -1| cut -b 7-)
    - docker tag "$DEBUG_LAYER" "${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}-failed"
    - docker push "${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}-failed"
  when: on_failure
  dependencies:
    - build

工作方式

Docker构建的输出存储在一个文件中,该文件在发生故障的情况下作为工件传递给debug-failed-build作业。这是一个示例,Docker构建的输出看起来像(只是片段):

Step 16/19 : VOLUME ["/sys/fs/cgroup"]
 ---> Using cache
 ---> a63a68682fcb
Step 17/19 : COPY --from=ansibleci-base /ansibleci-base /ansibleci-base
 ---> Using cache
 ---> 98fa646b73fb
Step 18/19 : RUN ln -s /ansibleci-base/scripts/run-tests.sh /usr/local/bin/run-tests &&     ln -s /ansibleci-base/ansible-plugins/human_log.py /usr/local/lib/python3.6/dist-packages/ansible/plugins/callback/human_log.py
 ---> Running in 83116392053c
ln: failed to create symbolic link '/usr/local/lib/python3.6/dist-packages/ansible/plugins/callback/human_log.py': No such file or directory

DEBUG_LAYER=...脚本命令后面的表达式将从Docker构建输出(98fa646b73fb)中提取最后一个层ID。下一条命令将为该层提供一个准备好要上载到注册表的图像名称,最后一条命令将上载该图像。

作为上传图像的替代方法,您还可以将图层另存为文件(使用docker save),并将保存的图像存储为压缩的tar存档。然后,将这个档案定义为Gitlab CI Artifact,您可以将其下载到计算机上并docker load在那里。