Docker executor

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

GitLab Runner은 Docker executor를 사용하여 Docker 이미지에서 작업을 실행합니다.

Docker executor를 사용하여 다음을 수행할 수 있습니다:

  • 각 작업에 대해 동일한 빌드 환경을 유지합니다.
  • CI 서버에서 작업을 실행할 필요 없이 로컬에서 명령을 테스트하는 데 동일한 이미지를 사용합니다.

Docker executor는 Docker Engine를 사용하여 각 작업을 별도 및 격리된 컨테이너에서 실행합니다. Executor는 Docker Engine에 연결하기 위해 다음을 사용합니다:

Docker executor workflow

Docker executor는 준비, 작업 전, 작업, 작업 후 단계로 작업을 나눕니다.

  1. 준비: services를 생성하고 시작합니다.
  2. 작업 전: 이전 단계에서 캐시를 복원하고 아티팩트를 다운로드한 후 특별한 Docker 이미지에서 실행됩니다.
  3. 작업: Runner에 구성한 Docker 이미지에서 빌드를 실행합니다.
  4. 작업 후: 캐시를 생성하고 GitLab에 아티팩트를 업로드합니다. 특별한 Docker 이미지에서 실행됩니다.

지원되는 구성

Docker executor는 다음 구성을 지원합니다.

Windows 구성의 알려진 이슈 및 추가 요구 사항은 Windows 컨테이너 사용를 참조하십시오.

Runner가 설치된 곳: Executor는: 컨테이너가 실행 중:
Windows docker-windows Windows
Windows docker Linux
Linux docker Linux

다음 구성은 지원되지 않습니다:

Runner가 설치된 곳: Executor는: 컨테이너가 실행 중:
Linux docker-windows Linux
Linux docker Windows
Linux docker-windows Windows
Windows docker Windows
Windows docker-windows Linux
note
GitLab Runner는 Docker Engine API v1.25를 사용하여 Docker Engine과 통신합니다. 이는 Linux 서버의 경우 Docker의 최소 지원 버전1.13.0이어야 함을 의미하며, Windows Server의 경우 보다 최신 버전이어야 합니다Windows Server 버전을 식별하기 위해.

Docker executor 사용

Docker executor를 사용하려면 config.toml에서 executor로 Docker를 정의하십시오.

다음 예시는 Docker를 executor로 정의하고 예시 구성을 보여줍니다. 이 값들에 대한 자세한 정보는 고급 구성을 참조하십시오.

concurrent = 4

[[runners]]
name = "myRunner"
url = "https://gitlab.com/ci"
token = "......"
executor = "docker"
[runners.docker]
  tls_verify = true
  image = "my.registry.tld:5000/alpine:latest"
  privileged = false
  disable_entrypoint_overwrite = false
  oom_kill_disable = false
  disable_cache = false
  volumes = [
    "/cache",
  ]
  shm_size = 0
  allowed_pull_policies = ["always", "if-not-present"]
  allowed_images = ["my.registry.tld:5000/*:*"]
  allowed_services = ["my.registry.tld:5000/*:*"]
  [runners.docker.volume_driver_ops]
    "size" = "50G"

이미지 및 서비스 구성

전제 조건:

  • 작업이 실행되는 이미지는 운영 체제 PATH에 있는 작동하는 셸을 가져야 합니다. 지원되는 셸은 다음과 같습니다:

Docker executor를 구성하려면 .gitlab-ci.ymlconfig.toml에서 Docker 이미지 및 서비스를 정의하십시오.

다음 키워드를 사용하십시오:

  • image: Runner가 작업을 실행하는 데 사용하는 Docker 이미지의 이름.
    • 로컬 Docker Engine이나 Docker Hub의 이미지를 입력하십시오. 자세한 정보는 Docker 문서를 참조하십시오.
    • 이미지 버전을 정의하려면 콜론(:)을 사용하여 태그를 추가하십시오. 태그를 지정하지 않으면 Docker는 버전으로 latest를 사용합니다.
  • services: image에 연결되어 다른 컨테이너를 생성하는 추가 이미지. 서비스 유형에 대한 자세한 정보는 Services를 참조하십시오.

.gitlab-ci.yml에서 이미지 및 서비스 정의

모든 작업에 대해 Runner가 사용하는 이미지 및 빌드 시간에 사용할 서비스 디렉터리을 정의하십시오.

예시:

image: ruby:2.7

services:
  - postgres:9.3

before_script:
  - bundle install

test:
  script:
  - bundle exec rake spec

작업별로 다른 이미지 및 서비스를 정의하려면:

before_script:
  - bundle install

test:2.6:
  image: ruby:2.6
  services:
  - postgres:9.3
  script:
  - bundle exec rake spec

test:2.7:
  image: ruby:2.7
  services:
  - postgres:9.4
  script:
  - bundle exec rake spec

.gitlab-ci.yml에서 image를 정의하지 않으면 Runner는 config.toml에 정의된 image를 사용합니다.

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

Runner가 실행하는 모든 작업에 이미지 및 서비스를 추가하려면 config.toml[runners.docker]를 업데이트하십시오. .gitlab-ci.ymlimage를 정의하지 않으면 Runner는 config.toml에 정의된 이미지를 사용합니다.

예시:

[runners.docker]
  image = "ruby:2.7"

[[runners.docker.services]]
  name = "mysql:latest"
  alias = "db"

[[runners.docker.services]]
  name = "redis:latest"
  alias = "cache"

이 예시는 테이블 배열 구문을 사용합니다.

개인 레지스트리의 이미지 정의

전제 조건:

개인 레지스트리에서 이미지를 정의하려면 .gitlab-ci.yml에서 레지스트리 이름과 이미지를 제공하십시오.

예시:

image: my.registry.tld:5000/namespace/image:tag

이 예에서 GitLab Runner는 레지스트리 my.registry.tld:5000에서 이미지 namespace/image:tag를 검색합니다.

네트워크 구성

서비스를 CI/CD 작업에 연결하려면 네트워크를 구성해야 합니다.

네트워크를 구성하는 방법은 다음과 같습니다:

  • 권장 사항. 실행기(runner)를 사용하여 각 작업에 대한 네트워크를 생성합니다.
  • 컨테이너 링크 정의. 컨테이너 링크는 Docker의 레거시 기능입니다.

각 작업을 위한 네트워크 생성

각 작업에 대한 네트워크를 생성할 수 있습니다.

이 네트워킹 모드를 활성화하면 실행기(runner)는 각 작업에 대해 사용자 정의 Docker 브릿지 네트워크를 생성하고 사용합니다. Docker 환경 변수는 컨테이너 간에 공유되지 않습니다. 사용자 정의 브릿지 네트워크에 대한 자세한 내용은 도커 문서를 참조하십시오.

이 네트워킹 모드를 사용하려면 config.toml의 피처 플래그 또는 환경 변수에서 FF_NETWORK_PER_BUILD를 활성화하십시오.

network_mode을 설정하지 마십시오.

예시:

[[runners]]
  (...)
  executor = "docker"
  environment = ["FF_NETWORK_PER_BUILD=1"]

또는:

[[runners]]
  (...)
  executor = "docker"
  [runners.feature_flags]
    FF_NETWORK_PER_BUILD = true

기본 도커 주소 풀을 설정하려면 dockerd에서 default-address-pool을 사용하십시오. 네트워크에서 CIDR 범위가 이미 사용 중이라면, Docker 네트워크가 호스트의 다른 네트워크와(다른 Docker 네트워크를 포함하여) 충돌할 수 있습니다.

이 기능은 Docker 데몬이 IPv6를 활성화하여 구성된 경우에만 작동합니다. IPv6 지원을 활성화하려면 Docker 구성에서 enable_ipv6true로 설정하십시오. 자세한 내용은 도커 문서를 참조하십시오.

실행기(runner)는 작업 컨테이너를 해결하기 위해 build 별칭을 사용합니다.

실행기(runner)가 각 작업을 위한 네트워크 생성하는 방법

작업이 시작되면, 실행기(runner)가 다음을 수행합니다:

  1. docker network create <network> 명령어와 유사한 브릿지 네트워크를 생성합니다.
  2. 서비스와 컨테이너를 브릿지 네트워크에 연결합니다.
  3. 작업이 종료되면 네트워크를 제거합니다.

작업을 실행하는 컨테이너 및 서비스를 실행하는 컨테이너는 서로의 호스트 이름 및 별칭을 해결합니다. 이 기능은 Docker에서 제공됩니다.

컨테이너 링크로 네트워크 구성

Docker 레거시 컨테이너 링크(legacy container links)와 기본 Docker bridge를 사용하여 작업 컨테이너를 서비스에 연결하는 네트워크 모드를 구성할 수 있습니다. 이 네트워킹 모드는 FF_NETWORK_PER_BUILD가 활성화되지 않은 경우의 기본값입니다.

네트워크를 구성하려면, config.toml 파일에서 네트워킹 모드를 지정하십시오:

  • bridge: 브릿지 네트워크 사용. 기본값.
  • host: 컨테이너 내에서 호스트의 네트워크 스택 사용.
  • none: 네트워킹 없음. 권장되지 않음.

예시:

[[runners]]
  (...)
  executor = "docker"
[runners.docker]
  network_mode = "bridge"

다른 network_mode 값을 사용하는 경우, 이는 이미 존재하는 Docker 네트워크의 이름으로 간주되어 빌드 컨테이너가 연결됩니다.

이름 해결 중에 Docker는 컨테이너의 /etc/hosts 파일을 서비스 컨테이너의 호스트 이름과 별칭으로 업데이트합니다. 그러나, 서비스 컨테이너는 컨테이너 이름을 해결할 수 없습니다. 컨테이너 이름을 해결하려면 각 작업을 위한 네트워크를 생성해야 합니다.

링크된 컨테이너는 그들의 환경 변수를 공유합니다.

생성된 네트워크의 MTU 재정의

OpenStack의 가상 머신(VM)과 같은 환경에서는 사용자 정의 MTU를 설정해야 할 수 있습니다. Docker 데몬은 docker.json의 MTU를 존준하지 않기 때문에, config.toml에서 network_mtu를 사용하여 정확한 값을 설정할 수 있습니다. 이렇게 함으로써 Docker 데몬은 새로 생성된 네트워크에 대해 올바른 MTU를 사용하도록 지시합니다.

[runners.docker]
  network_mtu = 1402

Docker 이미지 및 서비스 제한

Docker 이미지와 서비스를 제한하려면, allowed_imagesallowed_services 매개변수에 와일드카드 패턴을 지정하십시오.

예를 들어, 개인 Docker 레지스트리에서 이미지만 허용하려면:

[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    allowed_images = ["my.registry.tld:5000/*:*"]
    allowed_services = ["my.registry.tld:5000/*:*"]

개인 Docker 레지스트리의 이미지 디렉터리을 제한하려면:

[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    allowed_images = ["my.registry.tld:5000/ruby:*", "my.registry.tld:5000/node:*"]
    allowed_services = ["postgres:9.4", "postgres:latest"]

서비스 호스트 이름 접근

서비스 호스트 이름에 액세스하려면 .gitlab-ci.ymlservices에 서비스를 추가하십시오.

예를 들어, 응용 프로그램과 API 통합을 테스트하기 위해 Wordpress 인스턴스를 사용하려면, 서비스 이미지로 tutum/wordpress를 사용하십시오:

services:
- tutum/wordpress:latest

작업이 실행되면 tutum/wordpress 서비스를 시작합니다. 빌드 컨테이너에서는 tutum__wordpresstutum-wordpress 호스트 이름으로 액세스할 수 있습니다.

지정된 서비스 별칭 외에도, 실행기(runner)는 서비스 컨테이너에 대한 이미지 이름을 별칭으로 할당합니다. 이러한 별칭 중 하나를 사용할 수 있습니다.

이미지 이름을 기반으로 별칭을 생성하는 실행기(runner)는 다음의 규칙을 사용합니다:

  • : 이후의 모든 것을 제거합니다.
  • 첫 번째 별칭의 경우 슬래시(/)를 두 개의 밑줄(__)로 대체합니다.
  • 두 번째 별칭의 경우 슬래시(/)를 단일 대시(-)로 대체합니다.

개인 서비스 이미지를 사용하는 경우, 실행기(runner)는 지정된 포트를 제거하고 규칙을 적용합니다. registry.gitlab-wp.com:4999/tutum/wordpress 서비스는 registry.gitlab-wp.com__tutum__wordpressregistry.gitlab-wp.com-tutum-wordpress 호스트 이름으로 결과가 표시됩니다.

서비스 구성

데이터베이스 이름을 변경하거나 서비스에 대한 환경 변수를 정의할 수 있습니다.

실행기(runner)가 변수를 전달할 때:

  • 변수는 모든 컨테이너에 전달됩니다. 실행기(runner)는 특정 컨테이너로 변수를 전달할 수 없습니다.
  • 안전 변수는 빌드 컨테이너에 전달됩니다.

구성 변수에 대한 자세한 내용은 해당 Docker Hub 페이지의 각 이미지의 문서를 참조하십시오.

RAM에 디렉터리 마운트

디렉터리를 RAM에 마운트하려면 tmpfs 옵션을 사용할 수 있습니다. 데이터베이스와 같은 많은 I/O 관련 작업을 테스트해야 하는 경우, 이렇게 함으로써 시간을 단축할 수 있습니다.

config.toml 파일에서 tmpfsservices_tmpfs 옵션을 사용하면 각각의 옵션에 대해 별도의 경로를 지정할 수 있습니다. 자세한 내용은 도커 문서를 참조하십시오.

예를 들어, 공식 MySQL 컨테이너의 데이터 디렉터리를 RAM에 마운트하려면 다음과 같이 config.toml을 설정하십시오:

[runners.docker]
  # 주 컨테이너에 대해
  [runners.docker.tmpfs]
      "/var/lib/mysql" = "rw,noexec"
  
  # 서비스에 대해
  [runners.docker.services_tmpfs]
      "/var/lib/mysql" = "rw,noexec"

서비스에서 디렉터리 빌드

GitLab 실행기(runner)는 모든 공유 서비스에 /builds 디렉터리를 마운트합니다.

다양한 서비스 사용에 대한 자세한 내용은 다음을 참조하십시오:

GitLab Runner가 서비스 건강 상태 점검을 수행하는 방법

  • GitLab 16.0에서 다중 포트 점검을 도입했습니다.

서비스가 시작되면 GitLab Runner는 서비스가 응답할 때까지 대기합니다. Docker executor는 서비스 컨테이너의 노출된 서비스 포트에 TCP 연결을 시도합니다.

  • GitLab 15.11 이전에는 첫 번째 노출된 포트만 확인되었습니다.
  • GitLab 16.0 이후에는 첫 20개의 노출된 포트가 확인됩니다.

HEALTHCHECK_TCP_PORT 서비스 변수를 사용하여 특정 포트에서 건강 상태를 확인할 수 있습니다:

job:
  services:
    - name: mongo
      variables:
        HEALTHCHECK_TCP_PORT: "27017"

이것이 어떻게 구현되었는지 확인하려면, 상태 체크 Go 명령어를 사용하십시오.

Docker 드라이버 작업 지정

빌드용 볼륨을 만들 때 Docker 볼륨 드라이버에 제공할 인수를 지정하세요. 예를 들어, 모든 다른 드라이버 특정 옵션과 함께 각 빌드의 공간을 제한하는 데 이러한 인수를 사용할 수 있습니다. 다음 예제는 각 빌드가 사용할 수 있는 용량을 50GB로 설정한 config.toml을 보여줍니다.

[runners.docker]
  [runners.docker.volume_driver_ops]
      "size" = "50G"

컨테이너 빌드 및 캐시 디렉터리 구성

컨테이너 내부에서 데이터가 저장되는 위치를 정의하려면 config.toml[[runners]] 섹션에서 /builds/cache 디렉터리를 구성하세요.

/cache 저장 경로를 수정하는 경우 해당 경로를 config.toml[runners.docker] 섹션에서 volumes = ["/my/cache/"]로 정의해야 지속적으로 마킹하십시오.

기본적으로 Docker executor는 다음 디렉터리에 빌드 및 캐시를 저장합니다:

  • /builds/<namespace>/<project-name>의 빌드
  • 컨테이너 내부의 /cache에 있는 캐시

도커 캐시 지우기

사용하지 않는 컨테이너 및 빌드러가 만든 볼륨을 제거하려면 clear-docker-cache를 사용하세요.

옵션 디렉터리을 보려면 clear-docker-cache help 옵션으로 스크립트를 실행합니다:

clear-docker-cache help

기본 옵션은 모든 사용되지 않는 컨테이너 (덩거린 것 및 참조되지 않은 것) 및 볼륨을 제거하는 prune-volumes입니다.

효율적으로 캐시 리포지터리를 관리하려면 다음을 수행해야 합니다:

  • 일정적으로 cron과 함께 clear-docker-cache를 실행합니다 (예: 매주 한 번).
  • 디스크 공간을 회수하는 동안 성능을 위해 최근 컨테이너 몇 개를 유지하세요.

도커 빌드 이미지 지우기

clear-docker-cache 스크립트는 GitLab Runner에서 태그 지정되지 않은 도커 이미지를 제거하지 않습니다.

도커 빌드 이미지를 지우려면:

  1. 회수할 디스크 공간을 확인합니다:

     clear-docker-cache space
        
     Show docker disk usage
     ----------------------
        
     TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
     Images          14        9         1.306GB   545.8MB (41%)
     Containers      19        18        115kB     0B (0%)
     Local Volumes   0         0         0B        0B
     Build Cache     0         0         0B        0B
    
  2. 사용하지 않는 컨테이너, 네트워크, 이미지(덩거린 것 및 참조되지 않은 것), 및 태그되지 않은 볼륨을 모두 제거하려면 docker system prune을 실행합니다.

지속적인 리포지터리

Docker executor는 컨테이너가 실행될 때 지속적인 리포지터리를 제공합니다. volumes =에 정의된 모든 디렉터리는 빌드 간에 지속적입니다.

volumes 지시문은 다음 유형의 리포지터리를 지원합니다:

  • 동적 리포지터리의 경우 <path>를 사용하세요. <path>는 동일한 프로젝트의 동시 작업에 대한 연속적인 실행 사이에 지속됩니다. 데이터는 사용자 지정 캐시 볼륨에 연결됩니다: runner-<short-token>-project-<id>-concurrent-<concurrency-id>-cache-<md5-of-path>.
  • 호스트 연결된 리포지터리의 경우 <host-path>:<path>[:<mode>]를 사용하세요. <path>는 호스트 시스템의 <host-path>에 바운드됩니다. 선택적으로 <mode>는 이 리포지터리가 읽기 전용 또는 읽기-쓰기 (기본값) 임을 지정합니다.

빌드용 지속적인 리포지터리

/builds 디렉터리를 호스트 연결된 리포지터리로 만들면 다음 위치에 빌드가 저장됩니다: /builds/<short-token>/<concurrent-id>/<namespace>/<project-name>, 여기서:

  • <short-token>은 Runner의 토큰의 줄임말 (첫 8자)
  • <concurrent-id>는 프로젝트의 컨텍스트에서 특정 러너의 로컬 작업 ID를 식별하는 고유 번호입니다.

IPC 모드

Docker executor는 다른 위치를 컨테이너의 IPC 네임스페이스와 공유하는 것을 지원합니다. 이것은 docker run --ipc 플래그에 매핑됩니다. 더 자세한 내용은 Docker 문서의 IPC 설정를 참조하세요.

특권 모드

Docker executor는 빌드 컨테이너의 세부 조정을 허용하는 여러 옵션을 지원합니다. 이 중 하나는 특권 모드 옵션입니다.

특권 모드로 Docker-in-Docker 사용

구성된 특권 플래그는 빌드 컨테이너와 모든 서비스에 전달되어 Docker-in-Docker 방식을 쉽게 사용할 수 있습니다.

먼저 빌드 스크립트 (.gitlab-ci.yml)에서 특권 모드로 Runner를 구성하세요 (config.toml):

[[runners]]
  executor = "docker"
  [runners.docker]
    privileged = true

그런 다음 빌드 스크립트 (.gitlab-ci.yml)를 만들어 Docker-in-Docker 컨테이너를 사용하세요:

image: docker:git
services:
- docker:dind

build:
  script:
  - docker build -t my-image .
  - docker push my-image
caution
특권 모드에서 실행되는 컨테이너에는 보안 위험이 있습니다. 컨테이너가 특권 모드로 실행되면 컨테이너 보안 메커니즘을 비활성화하고 호스트를 특권 상승에 노출시킵니다. 특권 모드에서 컨테이너를 실행하면 컨테이너 이탈 등 보안 문제가 발생할 수 있습니다. 자세한 내용은 Docker 문서의 런타임 특권 및 리눅스 기능을 참조하세요.

데이터 손실을 피하려면 Docker-in-Docker를 TLS로 구성하거나 비활성화할 수 있습니다. 아래와 비슷한 오류를 방지하기 위해:

Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?

제한된 특권 모드로 루트리스 Docker-in-Docker 사용

이 버전에서, 제한된 특권 모드로 Docker-in-Docker 루트리스 이미지만 허용됩니다.

services_privilegedallowed_privileged_services 구성 매개변수는 특권 모드에서 실행할 수 있는 컨테이너를 제한합니다.

제한된 특권 모드로 Docker-in-Docker 루트리스 이미지를 사용하려면:

  1. config.toml에서 러너를 services_privilegedallowed_privileged_services를 사용하도록 구성합니다:

    [[runners]]
      executor = "docker"
      [runners.docker]
        services_privileged = true
        allowed_privileged_services = ["docker.io/library/docker:*-dind-rootless", "docker.io/library/docker:dind-rootless", "docker:*-dind-rootless", "docker:dind-rootless"]
    
  2. .gitlab-ci.yml에서 빌드 스크립트를 편집하여 Docker-in-Docker 루트리스 컨테이너를 사용하도록 설정합니다:

    image: docker:git
    services:
    - docker:dind-rootless
       
    build:
      script:
      - docker build -t my-image .
      - docker push my-image
    

allowed_privileged_services에 나열한 Docker-in-Docker 루트리스 이미지만 특권 모드에서 실행할 수 있습니다. 다른 모든 작업 및 서비스 컨테이너는 특권이 없는 모드로 실행됩니다.

루트리스로 실행되기 때문에, Docker-in-Docker 루트리스 또는 Buildkit 루트리스와 함께 거의 안전하게 사용할 수 있습니다.

보안 문제에 대한 자세한 내용은 Docker executor의 보안 위험을 참조하세요.

Docker ENTRYPOINT 구성

기본적으로 Docker executor는 Docker 이미지의 ENTRYPOINT를 덮어쓰지 않으며, 작업 스크립트를 실행하는 컨테이너를 시작하기 위해 sh 또는 bashCOMMAND로 전달합니다.

작업이 실행되려면 해당 Docker 이미지는 다음을 준수해야 합니다:

  • sh 또는 bashgrep 제공
  • sh/bash를 인수로 전달할 때 셸을 시작하는 ENTRYPOINT 정의

Docker Executor는 작업의 컨테이너를 다음과 같은 명령어의 동등한 결과로 실행합니다:

docker run <이미지> sh -c "echo '작동합니다!'" # 또는 bash

Docker 이미지가 이러한 메커니즘을 지원하지 않는 경우 프로젝트 구성에서 이미지의 ENTRYPOINT덮어쓸 수 있습니다 :

# 동등한
# docker run --entrypoint "" <이미지> sh -c "echo '작동합니다!'"
image:
  name: my-image
  entrypoint: [""]

더 많은 정보는 이미지의 Entrypoint 덮어쓰기Docker에서 CMD 및 ENTRYPOINT 상호 작용 이해를 참조하세요.

작업 스크립트로서의 ENTRYPOINT

ENTRYPOINT를 사용하여 사용자 지정 환경이나 보안 모드에서 빌드 스크립트를 실행하는 Docker 이미지를 만들 수 있습니다.

예를 들어, 빌드 스크립트를 실행하지 않고 사전에 정의된 일련의 명령어를 실행하는 ENTRYPOINT를 사용하는 Docker 이미지를 만들 수 있습니다. 이 빌드 컨테이너를 privileged 모드로 실행하고 실행 환경을 보호합니다.

  1. 새로운 Dockerfile 만들기:

    FROM docker:dind
    ADD / /entrypoint.sh
    ENTRYPOINT ["/bin/sh", "/entrypoint.sh"]
    
  2. ENTRYPOINT로 사용되는 bash 스크립트(entrypoint.sh) 만들기:

    #!/bin/sh
       
    dind docker daemon
        --host=unix:///var/run/docker.sock \
        --host=tcp://0.0.0.0:2375 \
        --storage-driver=vf &
       
    docker build -t "$BUILD_IMAGE" .
    docker push "$BUILD_IMAGE"
    
  3. 이미지를 Docker 레지스트리에 푸시하기

  4. privileged 모드에서 Docker executor 실행. config.toml에서 다음을 정의하세요:

    [[runners]]
      executor = "docker"
      [runners.docker]
        privileged = true
    
  5. 프로젝트에서 다음과 같은 .gitlab-ci.yml을 사용하세요:

    variables:
      BUILD_IMAGE: my.image
    build:
      image: my/docker-build:image
      script:
      - Dummy Script
    

Docker 명령어를 실행하기 위해 Podman 사용

Linux에 설치된 GitLab Runner를 사용하면 작업에서 Docker executor에서 컨테이너 런타임으로 Docker 대신 Podman을 사용할 수 있습니다.

전제 조건:

  1. Linux 호스트에 GitLab Runner를 설치하세요. 시스템 패키지 관리자를 사용하여 GitLab Runner를 설치하면 자동으로 gitlab-runner 사용자를 만듭니다.
  2. GitLab Runner를 실행할 사용자로 로그인하세요. 이때 pam_systemd를 우회하지 않도록 주의하세요. 적절한 사용자로 SSH를 사용할 수 있습니다. 이렇게 하면이 사용자로 systemctl을 실행할 수 있습니다.
  3. 시스템이 rootless Podman 설정에 필수 조건을 충족하는지 확인하세요. 구체적으로 사용자가 /etc/subuid 및 /etc/subgid에 올바른 항목을 가져야 합니다.
  4. Linux 호스트에서 Podman을 설치하세요.
  5. Podman 소켓을 활성화하고 시작하세요:

    systemctl --user --now enable podman.socket
    
  6. Podman 소켓이 수신 대기 중인지 확인하세요:

    systemctl status --user podman.socket
    
  7. Podman의 API에 액세스하는 데 사용되는 Listen 키를 통해 소켓 문자열을 복사하세요.
  8. GitLab Runner 사용자가 로그아웃 한 후에도 Podman 소켓이 사용 가능하도록 확인하세요:

    sudo loginctl enable-linger gitlab-runner
    
  9. GitLab Runner의 config.toml 파일을 편집하고 [runners.docker] 섹션의 host 항목에 소켓 값을 추가하세요. 예시:

    [[runners]]
      name = "podman-test-runner-2022-06-07"
      url = "https://gitlab.com"
      token = "x-XxXXXXX-xxXxXxxxxx"
      executor = "docker"
      [runners.docker]
        host = "unix:///run/user/1012/podman/podman.sock"
        tls_verify = false
        image = "quay.io/podman/stable"
        privileged = true
    

Dockerfile에서 Podman을 사용하여 컨테이너 이미지 빌드

다음 예제는 Podman을 사용하여 컨테이너 이미지를 빌드하고 해당 이미지를 GitLab Container 레지스트리에 푸시하는 방법을 보여줍니다.

Runner의 config.toml에서 기본 컨테이너 이미지는 quay.io/podman/stable로 설정되어 있으므로 CI 작업은 해당 이미지를 사용하여 포함된 명령어를 실행합니다.

variables:
  IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG

before_script:
  - podman login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY

oci-container-build:
  stage: build
  script:
    - podman build -t $IMAGE_TAG .
    - podman push $IMAGE_TAG
  when: manual

Dockerfile에서 Buildah를 사용하여 컨테이너 이미지 빌드

다음 예제는 Buildah를 사용하여 컨테이너 이미지를 빌드하고 해당 이미지를 GitLab Container 레지스트리에 푸시하는 방법을 보여줍니다.

image: quay.io/buildah/stable

variables:
  IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG

before_script:
  - buildah login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY

oci-container-build:
  stage: build
  script:
    - buildah bud -t $IMAGE_TAG .
    - buildah push $IMAGE_TAG
  when: manual

작업을 실행하는 사용자 지정 지정

기본적으로 runner는 컨테이너 내에서 root 사용자로 작업을 실행합니다. 다른, root가 아닌 사용자를 작업을 실행할 유저로 지정하려면 Docker 이미지의 Dockerfile에서 USER 지시문을 사용하세요.

FROM amazonlinux
RUN ["yum", "install", "-y", "nginx"]
RUN ["useradd", "www"]
USER "www"
CMD ["/bin/bash"]

위 Docker 이미지를 사용하여 작업을 실행하면 지정된 사용자로 실행됩니다:

build:
  image: my/docker-build:image
  script:
  - whoami   # www

러너가 이미지를 가져오는 방법 구성

config.toml에서 pull_policy를 구성하여 러너가 도커 이미지를 레지스트리에서 가져오는 방식을 정의합니다. 단일 정책을 설정하거나 여러 가져오기 정책 디렉터리 또는 특정 가져오기 정책을 허용할 수 있습니다.

pull_policy에 다음 값을 사용하세요:

  • always: 로컬 이미지가 있어도 이미지를 항상 가져옵니다. 기본값.
  • if-not-present: 로컬 버전이 없을 때에만 이미지를 가져옵니다.
  • never: 이미지를 가져오지 않고 로컬 이미지만 사용합니다.
[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    pull_policy = "always" # 가능값: always, if-not-present, never

always 가져오기 정책 설정

기본적으로 켜져 있는 always 옵션은 컨테이너를 만들기 전에 항상 이미지를 가져옵니다. 이 옵션을 사용하면 이미지가 최신 상태를 유지하고, 로컬 이미지가 있더라도 오래된 이미지를 사용하지 않도록 합니다.

다음 경우에 이 가져오기 정책을 사용하세요:

  • 러너가 항상 가장 최근의 이미지를 가져와야 하는 경우.
  • 러너가 자동 스케일 또는 GitLab 인스턴스의 공유 러너로 구성되어 있고, 공개적으로 사용 가능한 경우.

러너가 로컬에 저장된 이미지를 사용해야 하는 경우 이 정책을 사용하지 마십시오.

alwaysconfig.tomlpull policy로 설정하세요:

[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    pull_policy = "always"

if-not-present 가져오기 정책 설정

if-not-present 가져오기 정책을 설정하면 러너는 먼저 로컬 이미지가 있는지 확인합니다. 로컬 이미지가 없는 경우에만 러너가 레지스트리에서 이미지를 가져옵니다.

다음 경우에 이 정책을 사용하세요:

  • 로컬 이미지를 사용하지만 로컬 이미지가 없는 경우에만 이미지를 가져오려는 경우.
  • 러너가 무거운 이미지 레이어의 차이를 분석하는 시간을 줄이려는 경우, 그리고 드물게 업데이트되는 이미지인 경우. 이 경우 로컬 Docker 엔진 리포지터리에서 주기적으로 이미지를 매뉴얼으로 제거하여 이미지를 강제로 업데이트해야 합니다.

다음 경우에 이 정책을 사용하지 마십시오:

  • 러너를 사용하는 여러 사용자가 프라이빗 이미지에 액세스할 수 있는 경우의 공유 러너. 보안 문제에 대한 자세한 내용은 사설 도커 이미지를 if-not-present 가져오기 정책으로 사용을 참조하세요.
  • 작업이 자주 업데이트되고 가장 최신 이미지 버전에서 실행되어야 하는 경우. 이 경우 로컬 이미지를 자주 삭제함으로써 네트워크 부하를 줄일 수 있지만 로컬 이미지를 자주 삭제하는 가치를 상쇄시키는 결과가 발생할 수 있습니다.

if-not-present 정책을 config.toml에 설정하세요:

[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    pull_policy = "if-not-present"

never 가져오기 정책 설정

전제 조건:

  • 로컬 이미지에는 설치된 Docker 엔진이 있어야 하며 사용된 이미지의 로컬 사본이 있어야 합니다.

never 가져오기 정책을 사용하여 이미지 가져오기를 비활성화합니다. 사용자는 러너가 실행되는 Docker 호스트에서 매뉴얼으로 가져온 이미지만 사용할 수 있습니다.

다음 경우에 이 정책을 사용하세요:

  • 러너 사용자가 사용하는 이미지를 제어하는 경우.
  • 특정 레지스트리에 공개적으로 사용 가능하지 않은 특정 이미지만 사용할 수 있는 프로젝트에 전용으로 사용되는 프라이빗 러너용.

자동 스케일 Docker 실행자에서는 never 가져오기 정책을 사용하지 마십시오. never 가져오기 정책은 선택한 클라우드 공급업체의 사전 정의된 클라우드 인스턴스 이미지를 사용하는 경우에만 사용할 수 있습니다.

never 정책을 config.toml에 설정하세요:

[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    pull_policy = "if-not-present"

여러 가져오기 정책 설정

들 수 없을 때 실행할 여러 가져오기 정책을 디렉터리으로 나열할 수 있습니다. 러너는 가져오기 정책을 나열된 순서대로 처리하며 가져오기 시도가 성공하거나 디렉터리이 고갈될 때까지 실행합니다. 예를 들어, always 가져오기 정책을 사용하는 러너가 레지스트리를 사용할 수 없는 경우 if-not-present를 두 번째 가져오기 정책으로 추가하여 로컬 캐시된 도커 이미지를 사용할 수 있습니다.

이 가져오기 정책의 보안 영향에 대한 자세한 정보는 사설 도커 이미지를 if-not-present 가져오기 정책으로 사용을 참조하세요.

여러 가져오기 정책을 config.toml에 디렉터리으로 추가하세요:

[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    pull_policy = ["always", "if-not-present"]

Docker 가져오기 정책 허용

.gitlab-ci.yml 파일에서 가져오기 정책을 지정할 수 있습니다. 이 정책은 CI/CD 작업이 이미지를 가져오는 방식을 결정합니다.

.gitlab-ci.yml 파일에서 사용 가능한 가져오기 정책을 제한하려면 allowed_pull_policies를 사용하세요.

예를 들어, alwaysif-not-present 가져오기 정책만 허용하려면 config.toml에 추가하세요:

[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    allowed_pull_policies = ["always", "if-not-present"]
  • allowed_pull_policies를 지정하지 않으면 pull_policy 키워드의 값이 기본값으로 사용됩니다.
  • pull_policy를 지정하지 않으면 기본값은 always입니다.
  • 기존의 pull_policy 키워드allowed_pull_policies에서 지정되지 않은 가져오기 정책을 포함해서는 안됩니다. 그렇게 하면 작업에서 오류가 발생합니다.

이미지 가져오기 오류 메시지

오류 메시지 설명
Pulling docker image registry.tld/my/image:latest ... ERROR: Build failed: Error: image registry.tld/my/image:latest not found 러너가 이미지를 찾을 수 없습니다. always 가져오기 정책이 설정된 경우 표시됩니다.
Pulling docker image local_image:latest ... ERROR: Build failed: Error: image local_image:latest not found 이미지가 로컬에서 빌드되었지만 어떤 공개 또는 기본 Docker 레지스트리에도 없습니다. always 가져오기 정책이 설정된 경우 표시됩니다.
Pulling docker image registry.tld/my/image:latest ... WARNING: Cannot pull the latest version of image registry.tld/my/image:latest : Error: image registry.tld/my/image:latest not found WARNING: Locally found image will be used instead. 러너가 이미지를 가져오는 대신 로컬 이미지를 사용했습니다. always 가져오기 정책이 GitLab Runner 1.8 및 이전 버전에서만 설정된 경우 표시됩니다.
Pulling docker image local_image:latest ... ERROR: Build failed: Error: image local_image:latest not found 이미지를 로컬에서 찾을 수 없습니다. never 가져오기 정책이 설정된 경우 표시됩니다.
WARNING: Failed to pull image with policy "always": Error response from daemon: received unexpected HTTP status: 502 Bad Gateway (docker.go:143:0s) Attempt #2: Trying "if-not-present" pull policy Using locally found image version due to "if-not-present" pull policy 러너가 이미지를 가져오지 못하고 다음에 나열된 가져오기 정책을 사용하여 이미지를 가져오려고 시도합니다. 여러 가져오기 정책이 설정된 경우 표시됩니다.

실패한 풀 다시 시도하기

이미지 풀을 다시 시도하도록 러너를 구성하려면 config.toml에서 동일한 정책을 여러 번 지정하십시오.

예를 들어, 이 구성은 한 번만 풀을 다시 시도합니다.

[runners.docker]
  pull_policy = ["always", "always"]

이 설정은 개별 프로젝트의 .gitlab-ci.yml 파일에 있는 재시도(directive)와 유사하지만, 특정하게 도커 풀이 처음에 실패할 때에만 영향을 미칩니다.

Windows 컨테이너 사용

도커 실행자와 Windows 컨테이너를 사용하기 위해서, 제한 사항, 지원되는 Windows 버전, 그리고 Windows 도커 실행자 구성에 대한 다음 정보를 참조하세요.

Nanoserver 지원

Windows 도우미 이미지에 포함된 PowerShell Core의 지원으로, 도우미 이미지의 nanoserver 변형을 활용할 수 있게 되었습니다.

Windows에서 Docker 실행자의 제한 사항

다음은 Windows 컨테이너를 사용하는 데 제한 사항입니다.

  • Docker-in-Docker는 Docker 자체에서 지원되지 않기 때문에 지원되지 않습니다.
  • 대화형 웹 터미널을 지원하지 않습니다.
  • 호스트 장치 장착을 지원하지 않습니다.
  • 볼륨 디렉터리를 마운트할 때 디렉터리가 있어야 하며, Docker가 컨테이너를 시작하지 못할 경우, 추가 세부 정보를 보려면 #3754를 참조하세요.
  • docker-windows 실행자는 Windows에서 실행 중인 GitLab Runner에서만 실행할 수 있습니다.
  • Windows에서 Linux 컨테이너는 여전히 실험적이므로 지원되지 않습니다. 자세한 내용은 해당 이슈를 참조하세요.
  • Docker의 제한으로 인해, 대상 경로 드라이브 문자가 c:가 아닌 경우 다음에 대한 경로가 지원되지 않습니다:

    이는 f:\\cache_dir와 같은 값이 지원되지 않음을 의미하지만, f:는 지원됩니다. 그러나 대상 경로가 c: 드라이브에 있는 경우에도 경로가 지원됩니다 (예: c:\\cache_dir).

    Docker 데몬이 이미지와 컨테이너를 보관하는 위치를 구성하려면, Docker 데몬의 daemon.json 파일에서 data-root 매개변수를 업데이트하십시오.

    자세한 내용은 구성 파일로 Docker 구성을 참조하세요.

지원되는 Windows 버전

GitLab Runner는 다음 Windows 버전만 지원합니다. 이는 우리의 Windows 지원 수명주기를 따릅니다:

  • Windows Server 2022 LTSC (21H2)
  • Windows Server 2019 LTSC (1809)

미래의 Windows Server 버전에 대해서는 미래 지원 버전 정책이 있습니다.

GitLab Runner가 실행 중인 Windows Server에서 Docker 데몬의 버전을 감지하는 데 Docker를 사용하므로, Windows Server의 버전과 일치하는 OS 버전을 기반으로 한 컨테이너만 실행할 수 있습니다. 예를 들어, 다음의 Windows Server Core 이미지를 사용할 수 있습니다:

  • mcr.microsoft.com/windows/servercore:ltsc2022
  • mcr.microsoft.com/windows/servercore:ltsc2022-amd64
  • mcr.microsoft.com/windows/servercore:1809
  • mcr.microsoft.com/windows/servercore:1809-amd64
  • mcr.microsoft.com/windows/servercore:ltsc2019

지원되는 Docker 버전

GitLab Runner를 실행하는 Windows Server는 최신 버전의 Docker를 실행해야 합니다. GitLab Runner는 Docker를 사용하여 Windows Server 버전을 감지하므로, Docker 17.06과 같은 알려진 Docker 버전은 작동하지 않습니다. Docker는 Windows Server 버전을 식별하지 않으므로 다음과 같은 오류가 발생합니다:

지원되지 않는 Windows Version: Windows Server Datacenter

이 문제에 대한 문제 해결 자세히 보기.

Windows Docker 실행자 구성

note
--docker-volumesDOCKER_VOLUMES 환경 변수를 전달할 때 c:\\cache를 소스 디렉터리로 등록된 러너의 경우, 알려진 문제가 있습니다.

다음은 Windows를 실행하는 간단한 Docker 실행자 구성 예제입니다.

[[runners]]
  name = "windows-docker-2019"
  url = "https://gitlab.com/"
  token = "xxxxxxx"
  executor = "docker-windows"
  [runners.docker]
    image = "mcr.microsoft.com/windows/servercore:1809_amd64"
    volumes = ["c:\\cache"]

Docker 실행자의 다른 구성 옵션에 대해서는 고급 구성 섹션을 참조하세요.

서비스

GitLab Runner 12.9 이상에서 각 작업을 위한 네트워크를 생성하여 서비스를 사용할 수 있습니다.