[分享] 极狐GitLab使用Docker构建docker镜像

参考:

说明


您可以将 GitLab CI/CD 与 Docker 一起使用来创建 Docker 映像。例如,您可以创建应用程序的 Docker 映像,对其进行测试,然后将其发布到容器注册表。

要在 CI/CD 作业中运行 Docker 命令,您必须配置 GitLab Runner 以支持docker命令。

启用docker-in-docker有三种方式:

  • The shell executor

    此种方式就是使用shell 执行器,要求您的gitlab-runner机器已经安装了 docker 并且 docker 命令已经配置了环境变量,shell 执行器就像我们使用命令行的 shell 命令一样去使用 docker。

  • Docker-in-Docker(推荐)

    此种方式需要使用 docker 或 k8s 执行器,dind 相当于运行流水线的时候同时开启了两个容器或者 pod,一个容器(A容器)用来提供 docker 服务,另一个容器(B容器)用来执行流水线实际的任务。B 容器通过连接 A 容器获取 docker 服务,前提是 B 容器需要有 docker 客户端可以连接到远程的 docker 服务。

  • Docker socket binding

    此种方式就是使用 socket 映射的方式以发到容器内部可以访问控制外部容器的方式,同样也是需要使用 docker 执行器。

Docker-in-docker


本次主要介绍使用 Docker-in-docker 的方式构建 docker 镜像。

为了保存构建的镜像,您需要为您的 GitLab 实例开启镜像仓库的功能。

Enable the Container Registry

在使用 HTTPS 时或者使用了Let’s Encrypt integration,镜像仓库的功能默认开启,如果没有开启,使用如下方式开启:

Configure Container Registry under an existing GitLab domain

# /etc/gitlab/gitlab.rb
registry_external_url 'https://registry-gitlab.example.com'
registry_nginx['redirect_http_to_https'] = true # 可省略
registry_nginx['listen_port'] = 5678 # 可省略

注册 Runner

sudo gitlab-runner register -n \
  --url https://<your domain name>/ \
  --registration-token REGISTRATION_TOKEN \
  --executor docker \
  --description "My Docker Runner" \
  --docker-image "docker:19.03.12" \
  --docker-privileged \
  --docker-volumes "/certs/client"

在/etc/gitlab-runner/config.toml中,你可以看到类似如下配置:

[[runners]]
  url = "https://gitlab.com/"
  token = TOKEN
  executor = "docker"
  [runners.docker]
    tls_verify = false
    image = "docker:19.03.12"
    privileged = true
    disable_cache = false
    volumes = ["/certs/client", "/cache"]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]

运行流水线

示例 Dockerfile

FROM centos:7.9.2009

ENV WKPATH /var/lib/pgsql/11/data
RUN mkdir -p /var/lib/pgsql/11/data
WORKDIR $WKPATH 

RUN yum install -y vim telnet net-tools tree postgresql

EXPOSE 5432

CMD echo $WKPATH
CMD echo '-----END-----'
CMD /bin/bash

创建流水线规则文件

default:
  image: docker:19.03.12
  services: 
  # 启动一个 docker server,用来提供 docker 服务
    - name: docker:19.03.12-dind
      # alias 可以了解为主机名
      alias: docker

stages:
  - build
  - run

variables:
  DOCKER_HOST: "tcp://docker:2375" 
  # 如果 runner 是 tls disabled, 这里留空 ""
  DOCKER_TLS_CERTDIR: "/certs"
  # CI_REGISTRY_IMAGE = CI_REGISTRY/CI_PROJECT_NAMESPACE/CI_PROJECT_NAME/<IMAGE_NAME>:<IMAGE_TAG> 此处要注意 CI_REGISTRY/CI_PROJECT_NAMESPACE/CI_PROJECT_NAME 为本仓库的镜像仓库地址
  DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  CONTAINER_RELEASE_IMAGE: $CI_REGISTRY_IMAGE:latest

before_script:
  - docker info
  - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    
build:
  stage: build
  script:
    - docker build --pull -t $DOCKER_IMAGE .
    - docker push $DOCKER_IMAGE

run:
  stage: run
  script:
    - docker pull $DOCKER_IMAGE
    - docker run -it -d --privileged --name postgres --hostname postgres $DOCKER_IMAGE /usr/sbin/init
    - docker ps