도커 실행자

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

GitLab Runner은 도커 이미지에서 작업을 실행하기 위해 도커 실행자를 사용합니다.

도커 실행자를 사용하여 다음을 수행할 수 있습니다:

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

도커 실행자는 각 작업을 별도 및 격리된 컨테이너에서 실행하기 위해 도커 엔진을 사용합니다. 실행자가 도커 엔진에 연결하려면 다음을 사용합니다:

도커 실행자 워크플로우

도커 실행자는 Alpine Linux을 기반으로 한 특수 도커 이미지를 사용하여 준비, 작업 전, 작업 후 단계를 실행합니다. 특수 도커 이미지의 정의를 보려면 GitLab Runner 저장소를 참조하세요.

도커 실행자는 작업을 여러 단계로 분할합니다:

  1. 준비: 서비스를 생성하고 시작합니다.
  2. 작업 전: 이전 단계에서 캐시를 복원하고 아티팩트를 다운로드합니다. 특수 도커 이미지에서 실행됩니다.
  3. 작업: 러너에 구성된 도커 이미지에서 빌드를 실행합니다.
  4. 작업 후: 캐시를 생성하고 GitLab으로 아티팩트를 업로드합니다. 특수 도커 이미지에서 실행됩니다.

지원되는 구성

도커 실행자는 다음 구성을 지원합니다.

Windows 구성의 알려진 문제 및 추가 요구 사항에 대해서는 Windows 컨테이너 사용를 참조하세요.

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

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

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

참고: GitLab Runner는 도커 엔진 API v1.25를 사용하여 도커 엔진과 통신합니다. 이는 Linux 서버의 도커의 최소 지원 버전1.13.0이어야 함을 의미하며, Windows 서버의 경우 더 최신 버전이어야 함을 나타냅니다. (Windows 서버 버전 식별을 위한 자세한 내용은 #supported-docker-versions를 참조하세요.)

도커 실행자 사용

도커 실행자를 사용하려면 config.toml에서 실행자로서 도커를 정의하세요.

다음 예시는 도커를 실행자로서 정의하고 예시 구성을 보여줍니다. 이러한 값에 대한 자세한 정보는 고급 구성을 참조하세요.

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"

이미지 및 서비스 구성

전제 조건:

  • 작업이 실행되는 이미지는 해당 운영 체제의 작동 쉘을 가져야 합니다. 지원되는 쉘은 다음과 같습니다:

도커 실행자를 구성하려면 .gitlab-ci.ymlconfig.toml에서 도커 이미지 및 서비스를 정의하세요.

다음 키워드를 사용하세요:

  • image: 러너가 작업을 실행하는 데 사용하는 도커 이미지의 이름
    • 로컬 도커 엔진에서 이미지 또는 Docker Hub의 이미지를 입력하세요. 자세한 내용은 Docker 문서를 참조하세요.
    • 이미지 버전을 정의하려면 콜론(:)을 사용하여 태그를 추가하세요. 태그를 지정하지 않으면 Docker는 버전으로 latest를 사용합니다.
  • services: 다른 컨테이너를 생성하고 image에 연결하는 추가 이미지입니다. 서비스 유형에 대한 자세한 내용은 서비스를 참조하세요.

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

모든 작업에 러너가 사용하는 이미지와 빌드 시간에 사용할 서비스 목록을 정의합니다.

예시:

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를 정의하지 않으면 러너는 config.toml에서 정의된 image를 사용합니다.

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

러너가 실행하는 모든 작업에 이미지 및 서비스를 추가하려면 config.toml[runners.docker]를 업데이트합니다. 만약 .gitlab-ci.yml에서 image를 정의하지 않으면 러너는 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 작업에 연결하려면 네트워크를 구성해야 합니다.

네트워크를 구성하려면 다음 중 하나를 수행할 수 있습니다:

  • 추천. 러너를 각 작업에 대해 네트워크를 생성하도록 구성합니다.
  • 컨테이너 링크를 정의합니다. 컨테이너 링크는 Docker의 기존 기능입니다.

각 작업에 대해 네트워크 생성

러너를 각 작업에 대해 네트워크를 생성하도록 구성할 수 있습니다.

이 네트워킹 모드를 활성화하면 러너는 각 작업에 대해 사용자 정의 Docker 브릿지 네트워크를 생성하고 사용합니다. 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

기본 Docker 주소 풀을 설정하려면 dockerd에서 default-address-pool을 사용하세요. 네트워크에서 이미 CIDR 범위를 사용하고 있는 경우 Docker 네트워크가 호스트의 다른 네트워크, 특히 다른 Docker 네트워크와 충돌할 수 있습니다.

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

러너는 작업 컨테이너를 해결하기 위해 build 별칭을 사용합니다.

러너가 각 작업에 대해 네트워크 생성 방법

작업이 시작되면 러너가:

  1. <network>와 유사한 브릿지 네트워크를 생성합니다(Docker 명령 docker network create <network>과 유사함).
  2. 서비스와 컨테이너를 브릿지 네트워크에 연결합니다.
  3. 작업이 끝나면 네트워크를 제거합니다.

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

컨테이너 링크를 사용하여 네트워크 구성

Docker의 기존 컨테이너 링크와 기본 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를 설정하여 새로 생성된 네트워크에 올바른 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 호스트명으로 액세스할 수 있습니다.

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

러너는 이미지 이름을 기반으로 별칭을 생성하기 위해 다음 규칙을 사용합니다:

  • : 이후의 모든 것이 제거됩니다.
  • 첫 번째 별칭의 경우, 슬래시(/)는 더블 언더스코어(__)로 바뀝니다.
  • 두 번째 별칭의 경우, 슬래시(/)는 싱글 대시(-)로 바뀝니다.

개인 서비스 이미지를 사용하는 경우, 러너는 지정된 포트를 제거하고 규칙을 적용합니다. 서비스 registry.gitlab-wp.com:4999/tutum/wordpress는 호스트명 registry.gitlab-wp.com__tutum__wordpressregistry.gitlab-wp.com-tutum-wordpress로 결과가 나옵니다.

서비스 구성

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

러너가 변수를 전달할 때:

  • 변수는 모든 컨테이너에 전달됩니다. 러너는 특정 컨테이너에 변수를 전달할 수 없습니다.
  • 보안 변수는 빌드 컨테이너에 전달됩니다.

구성 변수에 대한 자세한 정보는 각 이미지의 Docker Hub 페이지에서 제공된 문서를 참조하세요.

RAM에 디렉터리 마운트

tmpfs 옵션을 사용하여 RAM에 디렉터리를 마운트할 수 있습니다. 이는 데이터베이스와 같은 입출력 관련 작업이 많은 경우 시간을 단축시킵니다.

러너 구성에서 tmpfsservices_tmpfs 옵션을 사용하면 각각의 옵션을 가진 여러 경로를 지정할 수 있습니다. 자세한 내용은 Docker 문서를 참조하세요.

예를 들어, RAM에 데이터 디렉터리를 마운트하려면 공식 MySQL 컨테이너의 config.toml을 구성하세요:

[runners.docker]
  # 주 컨테이너용
  [runners.docker.tmpfs]
      "/var/lib/mysql" = "rw,noexec"

  # 서비스용
  [runners.docker.services_tmpfs]
      "/var/lib/mysql" = "rw,noexec"

서비스에 디렉터리 빌드

GitLab 러너는 모든 공유 서비스에 /builds 디렉터리를 마운트합니다.

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

GitLab 러너가 서비스 건강 상태 확인을 수행하는 방법

서비스가 시작된 후, GitLab 러너는 서비스가 응답할 때까지 대기합니다. Docker 실행자는 서비스 컨테이너의 노출된 서비스 포트에 대한 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 실행기는 다음 디렉토리에 빌드 및 캐시를 저장합니다.

  • /builds/<namespace>/<project-name>에 빌드가 저장됩니다.
  • 컨테이너 내의 /cache에 캐시가 저장됩니다.

Docker 캐시 지우기

러너에 의해 생성된 사용되지 않는 컨테이너 및 볼륨을 제거하려면 clear-docker-cache를 사용하세요.

옵션 목록을 보려면 스크립트를 help 옵션으로 실행하세요.

clear-docker-cache help

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

캐시 저장을 효율적으로 관리하려면 다음을 수행해야 합니다.

  • cron을 사용하여 clear-docker-cache를 정기적으로 실행합니다(예: 매주 한 번).
  • 디스크 공간을 회수하면서 성능을 유지하기 위해 최근 컨테이너 몇 개를 유지합니다.

Docker 빌드 이미지 지우기

러너에 의해 태그가 지정되지 않기 때문에 clear-docker-cache 스크립트는 Docker 이미지를 제거하지 않습니다.

Docker 빌드 이미지를 지우려면:

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

     clear-docker-cache space
    
     Docker 디스크 사용량 표시
     ----------------------
        
     유형            전체     활성      크기      회수 가능
     이미지         14       9         1.306GB   545.8MB (41%)
     컨테이너      19       18        115kB      0B (0%)
     로컬 볼륨     0        0         0B        0B
     빌드 캐시     0        0         0B        0B
    
  2. 모든 사용되지 않는 컨테이너, 네트워크, 이미지(둔거 및 미참조), 그리고 태그가 지정되지 않은 볼륨을 제거하려면 docker system prune을 실행하세요.

지속적인 저장

Docker 실행기는 컨테이너 실행 중에 지속적인 저장을 제공합니다.
volumes =에 정의된 모든 디렉토리는 빌드 간에 지속적입니다.

volumes 지시어는 다음 유형의 저장을 지원합니다:

  • 동적 저장을 위해 <경로>를 사용합니다. <경로>는 동일한 동시 작업을 위해 프로젝트의 각 실행에서 지속됩니다. 이 데이터는 사용자 정의 캐시 볼륨에 연결됩니다: runner-<short-token>-project-<id>-concurrent-<concurrency-id>-cache-<md5-of-path>.
  • 호스트 바운드 저장을 위해 <호스트-경로>:<경로>[:<모드>]를 사용합니다. <경로>는 호스트 시스템의 <호스트-경로>에 바운드됩니다. 선택적인 <모드>는 이 저장이 읽기 전용 또는 읽기/쓰기(기본)임을 지정합니다.

빌드를 위한 지속적인 저장

/builds 디렉토리를 호스트 바운드 저장으로 만든 경우, 빌드는 다음 위치에 저장됩니다: /builds/<short-token>/<concurrent-id>/<namespace>/<project-name>에서 저장됩니다.

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

IPC 모드

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

특권 모드

Docker 실행기는 빌드 컨테이너를 세심하게 조정할 수 있는 여러 옵션을 지원합니다. 이 중 하나는 privileged 모드입니다.

특권 모드를 사용하여 Docker-in-Docker 사용

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

먼저 러너(config.toml)를 privileged 모드로 실행하도록 구성합니다.

[[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

경고: 특권 모드에서 실행되는 컨테이너에는 보안 위험이 있습니다.
특권 모드에서 컨테이너를 실행하면 컨테이너 보안 메커니즘을 비활성화하고 호스트 시스템이 권한 상승에 노출됩니다.
특권 모드에서 컨테이너를 실행하면 컨테이너 탈출로 이어질 수 있습니다. 자세한 내용은 Docker 문서의 런타임 특권 및 Linux 권한에 대해 참조하세요.

docker:2375에서 Docker 데몬에 연결할 수 없는 오류를 피하려면, Docker in Docker를 TLS로 구성하거나 TLS를 비활성화해야 할 수 있습니다.

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

제한된 권한 모드를 가진 rootless Docker-in-Docker 사용

이 버전에서는 Docker-in-Docker rootless 이미지만 특권 모드로 서비스를 실행할 수 있습니다.

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

제한된 권한 모드를 가진 rootless Docker-in-Docker를 사용하려면:

  1. config.toml에서 runner를 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 rootless 컨테이너로 수정합니다.

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

allowed_privileged_services 목록에 나열된 Docker-in-Docker rootless 이미지만 특권 모드에서 실행됩니다. 다른 모든 컨테이너는 일반 모드로 실행됩니다.

루트가 아니기 때문에, Docker-in-Docker rootless나 Buildkit rootless와 같은 특권 모드 이미지를 사용하는 건 _거의 안전_합니다.

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

Docker ENTRYPOINT 구성

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

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

  • sh 또는 bashgrep
  • sh/bash를 매개변수로 전달하면 셸을 시작하는 ENTRYPOINT를 정의합니다.

Docker Executor는 다음 명령어의 동등한 형식으로 작업의 컨테이너를 실행합니다.

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

만약 Docker 이미지가 이 메커니즘을 지원하지 않는다면, 프로젝트 구성에서 이미지의 ENTRYPOINT재정의할 수 있습니다. 다음은 해당 방법입니다:

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

자세한 내용은 이미지의 ENTRYPOINT 재정의Docker에서 CMD 및 ENTRYPOINT가 상호 작용하는 방식 이해을 참조하십시오.

작업 스크립트를 ENTRYPOINT로 사용

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

예를 들어, 빌드 스크립트를 실행하지 않는 ENTRYPOINT를 사용하는 Docker 이미지를 만들어 Docker 이미지를 빌드하기 위해 미리 정의된 명령어 집합을 실행하는 Docker 이미지를 만들 수 있습니다. 빌드 컨테이너를 특권 모드로 실행하고, runner의 빌드 환경을 안전하게 할 수 있습니다.

  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. config.toml에서 Docker executor를 특권 모드로 실행합니다. 다음과 같이 정의합니다:

    [[runners]]
      executor = "docker"
      [runners.docker]
        privileged = true
    
  5. 프로젝트에서 다음 .gitlab-ci.yml을 사용합니다:

    variables:
      BUILD_IMAGE: my.image
    build:
      image: my/docker-build:image
      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. 시스템이 루트가 아닌 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 컨테이너 레지스트리에 푸시합니다.

기본 컨테이너 이미지인 Runner config.toml은 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 컨테이너 레지스트리에 푸시하는 방법을 보여줍니다.

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 사용자로 작업을 실행합니다. 작업을 다른 비루트 사용자로 실행하려면 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

Runner가 이미지를 가져오는 방법 구성하기

config.toml에서 pull 정책을 구성하여 Runner가 레지스트리에서 Docker 이미지를 가져오는 방식을 정의하세요. pull_policy에 단일 정책, 정책 목록, 또는 특정 pull 정책 허용할 수 있습니다.

pull_policy에 다음 값 중 하나를 사용하세요:

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

always pull 정책 설정

기본적으로 활성화된 always 옵션은 컨테이너를 생성하기 전에 항상 이미지를 가져옵니다. 이 옵션은 이미지가 최신 상태인지 확인하고 로컬 이미지가 존재해도 오래된 이미지를 사용하지 않도록 합니다.

이 pull 정책을 사용하여:

  • Runner가 항상 최신 이미지를 가져와야 하는 경우
  • Runner가 자동 확장 또는 GitLab 인스턴스의 공유 Runner로 구성된 경우

다음과 같이 config.toml에서 pull policyalways를 설정하세요:

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

if-not-present pull 정책 설정

if-not-present pull 정책을 설정하면 Runner는 먼저 로컬 이미지를 확인한 후 로컬 이미지가 없으면 레지스트리에서 이미지를 가져옵니다.

if-not-present 정책을 사용하여:

  • 로컬 이미지를 사용하되 로컬 이미지가 없을 때만 이미지를 가져옵니다.
  • 무거우면서 드물게 업데이트되는 이미지의 이미지 레이어 차이를 분석하는 시간을 줄입니다. 이 경우 로컬 Docker Engine 저장소에서 정기적으로 이미지를 수동으로 제거하여 이미지를 업데이트하도록 강제해야 합니다.

다음과 같이 config.toml에서 if-not-present 정책을 설정하세요:

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

never 풀 정책 설정

전제 조건:

  • 로컬 이미지에는 설치된 Docker Engine과 사용된 이미지의 로컬 복사본이 있어야 합니다.

never 풀 정책을 설정하면 이미지 풀이 비활성화됩니다. 사용자들은 Docker 실행기가 실행되는 Docker 호스트에서 수동으로 풀려진 이미지만 사용할 수 있습니다.

never 풀 정책 사용 사례:

  • 실행기 사용자가 사용하는 이미지를 제어하기 위해.
  • 특정 레지스트리에 공개적으로 사용되지 않는 특정 이미지만 사용할 수 있는 프로젝트에 전용으로 할당된 비공개 실행기의 경우.

자동스케일링 Docker 실행기에 never 풀 정책을 사용하지 마세요. never 풀 정책은 사전 정의된 클라우드 인스턴스 이미지를 사용할 때에만 사용할 수 있습니다.

config.tomlnever 정책 설정:

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

여러 풀 정책 설정

풀이 실패할 경우 실행할 여러 풀 정책을 목록으로 지정할 수 있습니다. 실행기는 나열된 순서대로 풀 정책을 처리하며 성공적인 풀 시도가 이루어질 때까지 또는 목록이 고갈될 때까지 계속됩니다. 예를 들어, 실행기가 always 풀 정책을 사용하고 레지스트리를 사용할 수 없을 때, if-not-present를 두 번째 풀 정책으로 추가하여 로컬로 캐시된 Docker 이미지를 사용할 수 있습니다.

이 풀 정책의 보안 상의 영향에 대한 정보는 다음을 참조하세요: if-not-present 풀 정책으로 비공개 Docker 이미지 사용.

여러 풀 정책을 설정하려면 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에 지정되지 않은 풀 정책을 포함해서는 안 됩니다. 그렇지 않으면 작업이 오류가 발생합니다.

실패한 풀 다시 시도하기

실패한 이미지 풀을 재시도하도록 실행기를 구성하려면 config.toml에서 동일한 정책을 여러 번 지정하세요.

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

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

이 설정은 개별 프로젝트의 .gitlab-ci.yml 파일에서 재시도 지시어와 유사하지만, 특별히 Docker 풀이 처음에 실패한 경우에만 적용됩니다.

Windows 컨테이너 사용

도커 실행기를 사용하여 Windows 컨테이너를 사용하려면 제한, 지원되는 Windows 버전 및 Windows Docker 실행기 구성에 대한 다음 정보를 참고하세요.

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에서 실행하는 컨테이너는 Docker 데몬이 실행 중인 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 버전을 감지합니다.

GitLab Runner에서 작동하지 않는 알려진 Docker 버전은 Docker 17.06이며, Docker가 Windows Server 버전을 식별하지 못하여 다음 오류가 발생합니다:

지원되지 않는 Windows 버전: Windows Server Datacenter

이 문제에 대한 troubleshooting 자세히 읽기.

Windows Docker 실행기 구성

주의: --docker-volumes 또는 DOCKER_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 및 이후 버전에서는 작업마다 네트워크 생성하기를 활성화하여 서비스를 사용할 수 있습니다.