Docker 컨테이너에서 CI/CD 작업 실행하기

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated

CI/CD 작업을 전용 CI/CD 빌드 서버나 로컬 머신에서 호스팅되는 Docker 컨테이너에서 실행할 수 있습니다.

Docker 컨테이너에서 CI/CD 작업을 실행하려면 다음을 수행해야 합니다:

  1. 러너를 등록하고 도커 실행자를 사용하도록 구성합니다.
  2. .gitlab-ci.yml 파일에서 CI/CD 작업을 실행할 컨테이너 이미지를 지정합니다.
  3. 선택 사항. MySQL과 같은 다른 서비스도 컨테이너에서 실행할 수 있습니다. .gitlab-ci.yml 파일에 services를 지정하여 수행합니다.

도커 실행자를 사용하는 러너 등록

Docker를 사용하는 GitLab 러너를 사용하려면 러너를 등록해야 합니다.

다음 예제는 서비스를 제공하기 위해 임시 템플릿을 설정하는 방법을 보여줍니다.

cat > /tmp/test-config.template.toml << EOF
[[runners]]
[runners.docker]
[[runners.docker.services]]
name = "postgres:latest"
[[runners.docker.services]]
name = "mysql:latest"
EOF

그런 다음 이 템플릿을 사용하여 러너를 등록합니다.

sudo gitlab-runner register \
  --url "https://gitlab.example.com/" \
  --token "$RUNNER_TOKEN" \
  --description "docker-ruby:2.6" \
  --executor "docker" \
  --template-config /tmp/test-config.template.toml \
  --docker-image ruby:3.3

등록된 러너는 ruby:2.6 Docker 이미지를 사용하고, postgres:latestmysql:latest 두 개의 서비스를 실행하여 빌드 프로세스 중에 접근할 수 있습니다.

이미지란 무엇인가요

image 키워드는 Docker 실행자가 CI/CD 작업을 실행하는 데 사용하는 Docker 이미지의 이름입니다.

기본적으로 실행자는 이미지를 Docker Hub에서 가져옵니다. 그러나 gitlab-runner/config.toml 파일에서 레지스트리 위치를 구성할 수 있습니다. 예를 들어 Docker pull 정책을 사용하여 로컬 이미지를 설정할 수 있습니다.

이미지 및 Docker Hub에 대한 자세한 정보는 Docker 개요를 참조하세요.

이미지 요구 사항

CI/CD 작업을 실행하는 데 사용되는 모든 이미지는 다음 어플리케이션이 설치되어 있어야 합니다:

  • sh 또는 bash
  • grep

.gitlab-ci.yml 파일에서 image 정의

모든 작업에 사용되는 이미지와 런타임 중에 사용하려는 서비스 목록을 정의할 수 있습니다:

default:
  image: ruby:2.6
  services:
    - postgres:11.7
  before_script:
    - bundle install

test:
  script:
    - bundle exec rake spec

이미지 이름은 다음 형식 중 하나여야 합니다:

  • image: <image-name> (latest 태그 사용과 동일)
  • image: <image-name>:<tag>
  • image: <image-name>@<digest>

확장된 Docker 구성 옵션

  • GitLab 및 GitLab Runner 9.4에서 도입되었습니다.

image 또는 services 항목에 대해 문자열이나 맵을 사용할 수 있습니다:

  • 문자열은 레지스트리를 포함하여 전체 이미지 이름을 사용해야 합니다 (Docker Hub 이외의 레지스트리에서 이미지를 다운로드하는 경우).
  • 맵은 적어도 name 옵션을 포함해야 합니다. 이는 문자열 설정에 사용된 것과 동일한 이미지 이름입니다.

예를 들어 다음 두 정의는 동일합니다:

  • imageservices를 위한 문자열:

    image: "registry.example.com/my/image:latest"
    
    services:
      - postgresql:14.3
      - redis:latest
    
  • imageservices를 위한 맵. image:name은 필수입니다:

    image:
      name: "registry.example.com/my/image:latest"
    
    services:
      - name: postgresql:14.3
      - name: redis:latest
    

스크립트가 실행되는 위치

CI 작업이 Docker 컨테이너에서 실행될 때 before_script, script, after_script 명령이 /builds/<project-path>/ 디렉토리에서 실행됩니다. 이미지에는 다른 기본 WORKDIR가 정의되어 있을 수 있습니다. WORKDIR를 저장하여 작업 실행 중에 컨테이너에서 참조할 수 있도록 환경 변수로 설정하세요.

이미지의 엔트리포인트 재정의

  • GitLab 및 GitLab Runner 9.4에서 도입되었습니다. 확장된 구성 옵션에 대한 자세한 내용은 여기를 참조하세요.

이용 가능한 엔트리포인트 재정의 방법을 설명하기 전에, 러너가 어떻게 시작되는지 설명하겠습니다. CI/CD 작업에서 사용되는 컨테이너에 Docker 이미지를 사용합니다.

  1. 러너는 정의된 엔트리포인트를 사용하여 Docker 컨테이너를 시작합니다. .gitlab-ci.yml 파일에서 기본 Dockerfile의 값을 재정의할 수 있습니다.
  2. 러너는 실행 중인 컨테이너에 연결합니다.
  3. 러너는 스크립트 (‘before_script’, ‘script’, ‘after_script’의 조합)를 준비합니다.
  4. 러너는 스크립트를 컨테이너의 쉘 ‘stdin’에 보내고 출력을 받습니다.

Docker 이미지의 entrypoint를 재정의하려면, .gitlab-ci.yml 파일에서 다음을 수행하세요:

  • Docker 17.06 이상의 경우 entrypoint를 빈 값으로 설정합니다.
  • Docker 17.03 이전의 경우 entrypoint/bin/sh -c, /bin/bash -c 또는 이미지에서 사용 가능한 동등한 쉘로 설정합니다.

image:entrypoint의 시쿽스는 Dockerfile ENTRYPOINT와 유사합니다.

예를 들어 super/sql:experimental 이미지에 SQL 데이터베이스가 있는 경우 이를 기반 이미지로 사용하여 테스트를 실행하려고 합니다. 또한 이 이미지가 /usr/bin/super-sql run을 엔트리포인트로 구성하고 있을 것으로 가정합니다. 추가 옵션 없이 컨테이너를 시작하면 데이터베이스 프로세스가 실행됩니다. 러너는 이미지에 엔트리포인트가 없거나 엔트리포인트가 쉘 명령을 시작할 수 있도록 예상합니다.

확장된 Docker 구성 옵션으로 다음과 같이 .gitlab-ci.yml 파일에 entrypoint를 정의할 수 있습니다.

Docker 17.06 이상의 경우:

image:
  name: super/sql:experimental
  entrypoint: [""]

Docker 17.03 이전의 경우:

image:
  name: super/sql:experimental
  entrypoint: ["/bin/sh", "-c"]

config.toml에서 이미지 및 서비스 정의

config.toml 파일에서 다음을 정의할 수 있습니다.

[runners.docker]
  image = "ruby:latest"
  services = ["mysql:latest", "postgres:latest"]

이러한 방식으로 정의된 이미지 및 서비스는 해당 러너에서 실행되는 모든 작업에 추가됩니다.

개인 컨테이너 레지스트리에서 이미지 액세스

개인 컨테이너 레지스트리에 액세스하려면 GitLab 러너 프로세스가 다음을 사용할 수 있습니다:

어떤 옵션을 사용해야 하는지 정의하려면 러너 프로세스가 다음과 같이 구성을 읽습니다:

  • DOCKER_AUTH_CONFIG CI/CD 변수.
  • 러너의 config.toml 파일에 설정된 DOCKER_AUTH_CONFIG 환경 변수.
  • 사용자가 프로세스를 실행하는 홈 디렉터리인 $HOME/.docker 디렉터리의 config.json 파일. 자식 프로세스를 비특권 사용자로 실행하도록 --user 플래그가 제공된 경우에는, 런너 프로세스 사용자의 홈 디렉터리가 사용됩니다.

요구 사항 및 제한사항

  • GitLab 러너 13.1 이상의 Kubernetes executor에서 사용 가능합니다.
  • 자격 증명 저장소 사용자격 증명 도우미 사용는 바이너리가 GitLab 러너의 $PATH에 추가되고 이를 수행할 수 있는 액세스가 필요합니다. 따라서 이러한 기능은 인스턴스 러너나 러너가 설치된 환경에 액세스할 수 없는 다른 러너에서 사용할 수 없습니다.

정적으로 정의된 자격 증명 사용

개인 레지스트리에 액세스하는 두 가지 접근 방식이 있습니다. 모두 적절한 인증 정보로 DOCKER_AUTH_CONFIG CI/CD 변수를 설정해야 합니다.

  1. 작업별: 개인 레지스트리에 액세스하도록 하려면, DOCKER_AUTH_CONFIGCI/CD 변수로 추가하십시오.
  2. 러너별: 모든 작업이 개인 레지스트리에 액세스하도록 러너를 구성하려면, DOCKER_AUTH_CONFIG를 러너 구성의 환경 변수로 추가하십시오.

각각에 대한 예시는 아래에 제공되어 있습니다.

DOCKER_AUTH_CONFIG 데이터 결정

예를 들어, registry.example.com:5000/private/image:latest 이미지를 사용하려고 합니다. 이 이미지는 비공개이며 개인 컨테이너 레지스트리에 로그인해야 합니다.

다음과 같은 로그인 자격 증명이 있다고 가정해 봅시다:

레지스트리 registry.example.com:5000
사용자 이름 my_username
암호 my_password

DOCKER_AUTH_CONFIG 값을 결정하려면 다음 방법 중 하나를 사용할 수 있습니다:

  • 로컬 머신에서 docker login을 실행하십시오:

    docker login registry.example.com:5000 --username my_username --password my_password
    

    그런 다음 ~/.docker/config.json의 내용을 복사하십시오.

    컴퓨터에서 레지스트리에 액세스할 필요가 없다면, docker logout을 실행하십시오:

    docker logout registry.example.com:5000
    
  • 일부 설정에서는 Docker 클라이언트가 docker login 결과를 저장하기 위해 사용 가능한 시스템 키 저장소를 사용할 수 있습니다. 이 경우 ~/.docker/config.json을 읽을 수 없으므로, ${username}:${password}의 base64로 인코딩된 버전을 준비하고 Docker 구성 JSON을 수동으로 만들어야 합니다. 터미널을 열고 다음 명령을 실행하십시오:

    # echo 대신 printf를 사용하는 것이 좋습니다(새 줄을 인코딩하지 않도록).
    printf "my_username:my_password" | openssl base64 -A
    
    # 복사할 예시 출력
    bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=
    

특별 문자를 포함하는 사용자 이름을 가지고 있다면(@과 같은), 인증 문제를 방지하기 위해 백 슬래시(\)로 이스케이프 처리해야 합니다.

다음과 같이 Docker JSON 구성 내용을 생성하십시오:

  {
      "auths": {
          "registry.example.com:5000": {
              "auth": "(위의 base64 내용)"
          }
      }
  }

작업 구성

registry.example.com:5000에 액세스할 수 있도록 하려면, 다음 단계를 따르십시오:

  1. Docker 구성 파일 내용을 값으로 하는 CI/CD 변수 DOCKER_AUTH_CONFIG를 생성하십시오:

    {
        "auths": {
            "registry.example.com:5000": {
                "auth": "bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ="
            }
        }
    }
    
  2. 이제 .gitlab-ci.yml 파일에서 image 또는 services로 정의된 registry.example.com:5000에서 개인 이미지를 사용할 수 있습니다:

    image: registry.example.com:5000/namespace/image:tag
    

    위 예시에서 GitLab 러너는 registry.example.com:5000에서 namespace/image:tag 이미지를 찾습니다.

필요한 만큼 많은 레지스트리에 대한 구성을 추가할 수 있으며, 앞에서 설명한대로 "auths" 해시에 더 많은 레지스트리를 추가하십시오.

러너가 DOCKER_AUTH_CONFIG를 일치시키기 위해 모든 곳에 전체 hostname:port 조합이 필요합니다. 예를 들어, .gitlab-ci.yml 파일에서 registry.example.com:5000/namespace/image:tag가 지정된 경우, DOCKER_AUTH_CONFIG에서도 registry.example.com:5000을 지정해야 합니다. 오직 registry.example.com만 지정하는 것은 작동하지 않습니다.

Runner 구성

여러 파이프라인이 동일한 레지스트리에 액세스하는 경우, runner 레벨에서 레지스트리 액세스를 설정해야 합니다. 이렇게 하면 파이프라인 작성자가 적절한 runner에서 작업을 실행함으로써 개인 레지스트리에 액세스할 수 있습니다. 또한 레지스트리 변경 및 자격 증명 로테이션을 간단하게할 수 있습니다.

이것은 그 runner에서 어떤 작업이든 모든 프로젝트를 통해 동일한 권한으로 레지스트리에 액세스할 수 있음을 의미합니다. 레지스트리 액세스를 제어해야 하는 경우, runner 액세스를 제어해야 합니다.

DOCKER_AUTH_CONFIG를 runner에 추가하려면:

  1. config.toml 파일을 다음과 같이 수정합니다.

    [[runners]]
      environment = ["DOCKER_AUTH_CONFIG={\"auths\":{\"registry.example.com:5000\":{\"auth\":\"bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=\"}}}"]
    
    • DOCKER_AUTH_CONFIG에 포함된 이중 인용부호는 백슬래시로 이스케이프해야 합니다. 이렇게 함으로써 TOML에서 해석되는 것을 방지합니다.
    • environment 옵션은 목록입니다. 이미 존재하는 항목이 있는 경우 이를 대체하지 않고 목록에 추가해야 합니다.
  2. runner 서비스를 다시 시작합니다.

자격 증명 저장소 사용

자격 증명 저장소를 구성하려면:

  1. 자격 증명 저장소를 사용하려면, 지정된 키체인이나 외부 저장소와 상호작용하는 외부 도우미 프로그램이 필요합니다. GitLab Runner의 $PATH에서 도우미 프로그램을 사용할 수 있도록 해야 합니다.

  2. GitLab Runner가 그것을 사용하도록 해야 합니다. 이를 위해 두 가지 방법이 있습니다.:

    • CI/CD 변수를 생성하여 DOCKER_AUTH_CONFIG를 Docker 구성 파일의 내용으로 설정합니다:

        {
          "credsStore": "osxkeychain"
        }
      
    • 또는 self-managed runner를 실행 중이라면, 이전 JSON을 ${GITLAB_RUNNER_HOME}/.docker/config.json에 추가합니다. GitLab Runner는 이 구성 파일을 읽고 해당 저장소에 필요한 도우미를 사용합니다.

credsStore모든 레지스트리에 액세스하기 위해 사용됩니다. 개인 레지스트리 및 Docker Hub에서의 공용 이미지를 모두 사용하는 경우, Docker Hub에서 이미지를 끌어올리는 데 실패합니다. Docker 데몬은 모든 레지스트리에 동일한 자격 증명을 사용하려고 시도하기 때문입니다.

자격 증명 헬퍼 사용

  • GitLab Runner 12.0에서 도입되었습니다.

예를 들어, <aws_account_id>.dkr.ecr.<region>.amazonaws.com/private/image:latest 이미지에 액세스하려면, 이 이미지는 개인 이미지이며 개인 컨테이너 레지스트리에 로그인해야 합니다.

<aws_account_id>.dkr.ecr.<region>.amazonaws.com에 대한 액세스를 구성하려면 다음 단계를 따르세요:

  1. docker-credential-ecr-login이 GitLab Runner의 $PATH에서 사용 가능한지 확인합니다.
  2. 다음 AWS 자격 증명 설정 중 하나를 가져야 합니다. GitLab Runner가 자격 증명에 액세스할 수 있도록 해야 합니다.
  3. GitLab Runner가 이를 사용하도록 설정해야 합니다. 이를 위해 두 가지 방법이 있습니다.:

    • CI/CD 변수를 만들어 DOCKER_AUTH_CONFIG를 Docker 구성 파일의 내용으로 설정합니다:

      {
        "credHelpers": {
          "<aws_account_id>.dkr.ecr.<region>.amazonaws.com": "ecr-login"
        }
      }
      

      이렇게 하면 Docker가 특정 레지스트리에 대한 자격 증명 헬퍼를 구성합니다.

      대신, Docker를 모든 Amazon Elastic Container Registry (ECR) 레지스트리에 대한 자격 증명 헬퍼를 사용하도록 구성할 수도 있습니다:

      {
        "credsStore": "ecr-login"
      }
      

      참고: {"credsStore": "ecr-login"}를 사용하는 경우, AWS 공유 구성 파일(~/.aws/config)에서 리전을 명시적으로 설정해야 합니다. 왜냐하면 ECR 자격 증명 헬퍼가 권한 부여 토큰을 검색할 때 리전을 명시해야 하기 때문입니다.

    • 또는 self-managed runner를 실행 중이라면, 이전의 JSON을 ${GITLAB_RUNNER_HOME}/.docker/config.json에 추가합니다. GitLab Runner는 이 구성 파일을 읽고 해당 저장소에 필요한 도우미를 사용합니다.

  4. 이제 .gitlab-ci.yml 파일의 image 및/또는 services에 정의된 <aws_account_id>.dkr.ecr.<region>.amazonaws.com에서 개인 이미지를 사용할 수 있습니다:

    image: <aws_account_id>.dkr.ecr.<region>.amazonaws.com/private/image:latest
    

    위의 예시에서, GitLab Runner는 private/image:latest 이미지를 위해 <aws_account_id>.dkr.ecr.<region>.amazonaws.com을 확인합니다.

원하는만큼 많은 레지스트리에 대한 구성을 추가할 수 있으며, "credHelpers" 해시에 더 많은 레지스트리를 추가할 수 있습니다.

이미지의 무결성을 확인하기 위해 체크섬을 사용하세요

이미지의 무결성을 확인하기 위해 .gitlab-ci.yml 파일의 작업 정의에 이미지 체크섬을 사용하는 것을 권장합니다. 실패한 이미지 무결성 검증은 수정된 컨테이너를 사용하지 못하도록 합니다.

이미지 체크섬을 사용하려면 끝에 체크섬을 추가해야 합니다:

image: ruby:2.6.8@sha256:d1dbaf9665fe8b2175198e49438092fdbcf4d8934200942b94425301b17853c7

이미지 체크섬은 이미지 TAG 탭에서 DIGEST 열을 확인해야 합니다. 예를 들어, Ruby 이미지를 확인합니다. 체크섬은 6155f0235e95와 같이 임의의 문자열입니다.

또한 시스템의 모든 이미지의 체크섬을 다음 명령을 사용하여 가져올 수 있습니다: docker images --digests:

❯ docker images --digests
REPOSITORY                                                        TAG       DIGEST                                                                    (...)
gitlab/gitlab-ee                                                  latest    sha256:723aa6edd8f122d50cae490b1743a616d54d4a910db892314d68470cc39dfb24   (...)
gitlab/gitlab-runner                                              latest    sha256:4a18a80f5be5df44cb7575f6b89d1fdda343297c6fd666c015c0e778b276e726   (...)

커스텀 GitLab Runner Docker 이미지 만들기

AWS CLI 및 Amazon ECR 자격 증명 도우미를 패키지화하여 사용자 지정 GitLab Runner Docker 이미지를 만들 수 있습니다. 이 설정은 컨테이너화된 응용 프로그램을 위해 AWS 서비스와 안전하고 원활한 상호 작용을 용이하게 합니다. 예를 들어, AWS에 마이크로서비스를 배포하는 팀들은 이 설정을 사용하여 수동 자격 증명 관리를 사용하지 않고 Amazon ECR에서 Docker 이미지를 관리, 배포 및 업데이트할 수 있습니다.

  1. AWS 및 GitLab 인증.
  2. 다음 내용으로 Dockerfile을 생성하세요:

    # 패키지 버전 관리
    ARG GITLAB_RUNNER_VERSION=v17.3.0
    ARG AWS_CLI_VERSION=2.17.36
    
    # AWS CLI 및 Amazon ECR 자격 증명 도우미
    FROM amazonlinux as aws-tools
    RUN set -e \
        && yum update -y \
        && yum install -y --allowerasing git make gcc curl unzip \
        && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" --output "awscliv2.zip" \
        && unzip awscliv2.zip && ./aws/install -i /usr/local/bin \
        && yum clean all
    
    # ECR 자격 증명 도우미 다운로드 및 설치
    RUN curl --location --output  /usr/local/bin/docker-credential-ecr-login "https://github.com/awslabs/amazon-ecr-credential-helper/releases/latest/download/docker-credential-ecr-login-linux-amd64"
    RUN chmod +x /usr/local/bin/docker-credential-ecr-login
    
    # ECR 자격 증명 도우미 구성
    RUN mkdir -p /root/.docker
    RUN echo '{ "credsStore": "ecr-login" }' > /root/.docker/config.json
    
    # GitLab Runner를 기반으로한 최종 이미지
    FROM gitlab/gitlab-runner:${GITLAB_RUNNER_VERSION}
    
    # 필요한 패키지 설치
    RUN apt-get update \
        && apt-get install -y --no-install-recommends jq procps curl unzip groff libgcrypt20 tar gzip less openssh-client \
        && apt-get clean && rm -rf /var/lib/apt/lists/*
    
    # AWS CLI 및 Amazon ECR 자격 증명 도우미 이진 파일 복사
    COPY --from=aws-tools /usr/local/bin/ /usr/local/bin/
    
    # ECR 자격 증명 도우미 구성 복사
    COPY --from=aws-tools /root/.docker/config.json /root/.docker/config.json
    
  3. .gitlab-ci.yml 내에서 커스텀 GitLab Runner Docker 이미지를 빌드하려면 다음 예제를 포함하세요:

    variables:
      DOCKER_DRIVER: overlay2
      IMAGE_NAME: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
      GITLAB_RUNNER_VERSION: v17.3.0
      AWS_CLI_VERSION: 2.17.36
    
    stages:
      - build
    
    build-image:
      stage: build
      script:
        - echo "GitLab 컨테이너 레지스트리에 로그인 중..."
        - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
        - echo "Docker 이미지 빌드 중..."
        - docker build --build-arg GITLAB_RUNNER_VERSION=${GITLAB_RUNNER_VERSION} --build-arg AWS_CLI_VERSION=${AWS_CLI_VERSION} -t ${IMAGE_NAME} .
        - echo "Docker 이미지를 GitLab 컨테이너 레지스트리에 푸시하는 중..."
        - docker push ${IMAGE_NAME}
      rules:
        - changes:
            - Dockerfile
    
  4. 러너 등록.