Docker Build 문제 해결

Docker Build 문제 해결

GitLab CI에서 Docker 이미지를 빌드하다 보면 "Docker daemon에 연결할 수 없다", "인증서를 검증하지 못했다" 같은 오류를 자주 만나게 돼요. 특히 Docker-in-Docker(dind)를 사용할 때 이런 문제가 잘 생기죠. 이 글은 Docker Build와 관련해 겪는 대표적인 오류들을 모아, 각각 어떤 상황에서 발생하고 어떻게 해결하는지 설명할게요.

출처: 문서

본문

오류: docker: Cannot connect to the Docker daemon at tcp://docker:2375

이 오류는 Docker-in-Docker v19.03 이상을 사용할 때 흔합니다.

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

이 오류는 Docker가 자동으로 TLS로 시작되기 때문에 발생해요.

이 오류는 Kubernetes executor에서 Docker-in-Docker 서비스가 완전히 시작되기 전에 접근하려 할 때도 발생할 수 있어요. 더 자세한 설명은 이슈 27215를 참고하세요.

Docker no such host 오류

docker: error during connect: Post https://docker:2376/v1.40/containers/create: dial tcp: lookup docker on x.x.x.x:53: no such host 같은 오류를 볼 수 있어요.

이 문제는 서비스의 이미지 이름에 레지스트리 호스트 이름이 포함될 때 발생할 수 있어요. 예를 들어:

default:
  image: docker:24.0.5-cli
  services:
    - registry.hub.docker.com/library/docker:24.0.5-dind

서비스의 호스트 이름은 전체 이미지 이름에서 파생돼요. 하지만 서비스 호스트 이름 docker가 더 짧은 형태로 기대됩니다. 서비스 해석과 접근을 허용하려면 서비스 이름 docker에 명시적 별칭을 추가하세요.

default:
  image: docker:24.0.5-cli
  services:
    - name: registry.hub.docker.com/library/docker:24.0.5-dind
      alias: docker

오류: Cannot connect to the Docker daemon at unix:///var/run/docker.sock

dind 서비스에 접근하는 docker 명령을 실행하려 할 때 다음 오류가 보일 수 있어요.

$ docker ps
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

job에 다음 환경 변수가 정의되어 있는지 확인하세요.

  • DOCKER_HOST
  • DOCKER_TLS_CERTDIR (선택)
  • DOCKER_TLS_VERIFY (선택)

Docker 클라이언트를 제공하는 이미지도 업데이트하고 싶을 수 있어요. 예를 들어 docker/compose 이미지는 더 이상 사용되지 않으며 docker로 교체해야 합니다.

러너 이슈 30944에 설명된 대로, 이 오류는 job이 이전에 사용되지 않는 Docker --link 파라미터에서 파생된 DOCKER_PORT_2375_TCP 같은 환경 변수에 의존했다면 발생할 수 있어요. 다음 경우에 job이 이 오류로 실패합니다.

오류: unauthorized: incorrect username or password

이 오류는 사용되지 않는 변수인 CI_BUILD_TOKEN을 사용할 때 나타나요.

Error response from daemon: Get "https://registry-1.docker.io/v2/": unauthorized: incorrect username or password

이 오류가 사용자에게 나타나지 않게 하려면:

  • CI_JOB_TOKEN을 대신 사용하세요.
  • gitlab-ci-token/CI_BUILD_TOKEN에서 $CI_REGISTRY_USER/$CI_REGISTRY_PASSWORD로 바꾸세요.

연결 중 오류: no such host

이 오류는 dind 서비스가 시작에 실패했을 때 나타나요.

error during connect: Post "https://docker:2376/v1.24/auth": dial tcp: lookup docker on 127.0.0.11:53: no such host

job 로그에 mount: permission denied (are you root?)가 나타나는지 확인하세요. 예를 들어:

Service container logs:
2023-08-01T16:04:09.541703572Z Certificate request self-signature ok
2023-08-01T16:04:09.541770852Z subject=CN = docker:dind server
2023-08-01T16:04:09.556183222Z /certs/server/cert.pem: OK
2023-08-01T16:04:10.641128729Z Certificate request self-signature ok
2023-08-01T16:04:10.641173149Z subject=CN = docker:dind client
2023-08-01T16:04:10.656089908Z /certs/client/cert.pem: OK
2023-08-01T16:04:10.659571093Z ip: can't find device 'ip_tables'
2023-08-01T16:04:10.660872131Z modprobe: can't change directory to '/lib/modules': No such file or directory
2023-08-01T16:04:10.664620455Z mount: permission denied (are you root?)
2023-08-01T16:04:10.664692175Z Could not mount /sys/kernel/security.
2023-08-01T16:04:10.664703615Z AppArmor detection and --privileged mode might break.
2023-08-01T16:04:10.665952353Z mount: permission denied (are you root?)

이것은 GitLab Runner가 dind 서비스를 시작할 권한이 없음을 나타냅니다.

  • config.tomlprivileged = true가 설정되어 있는지 확인하세요.
  • CI job이 이 privileged 러너를 사용할 수 있는 올바른 Runner tags를 가지고 있는지 확인하세요.

오류: cgroups: cgroup mountpoint does not exist: unknown

Docker Engine 20.10에서 도입된 알려진 비호환성이 있어요.

호스트가 Docker Engine 20.10 이상을 사용할 때, 20.10보다 오래된 버전의 docker:dind 서비스는 예상대로 동작하지 않습니다.

서비스 자체는 문제없이 시작되지만, 컨테이너 이미지를 빌드하려 하면 다음 오류가 발생합니다.

cgroups: cgroup mountpoint does not exist: unknown

이 문제를 해결하려면 docker:dind 컨테이너를 최소 20.10.x 버전(예: docker:24.0.5-dind)으로 업데이트하세요.

반대 구성(docker:24.0.5-dind 서비스와 19.06.x 이하 버전의 호스트 Docker Engine)은 문제없이 동작합니다. 가장 좋은 전략은 job 환경 버전을 자주 테스트하고 최신 버전으로 업데이트하는 것이에요. 그러면 새 기능과 개선된 보안을 얻을 수 있고, 이 특정 경우에는 러너 호스트의 기본 Docker Engine 업그레이드가 job에 투명하게 적용됩니다.

오류: failed to verify certificate: x509: certificate signed by unknown authority

커스텀 또는 프라이빗 인증서(예: Zscaler 인증서)를 사용하는 Docker-in-Docker 환경에서 docker builddocker pull 같은 Docker 명령을 실행하면 이 오류가 나타날 수 있어요.

error pulling image configuration: download failed after attempts=6: tls: failed to verify certificate: x509: certificate signed by unknown authority

이 오류는 Docker-in-Docker 환경의 Docker 명령이 두 개의 분리된 컨테이너를 사용하기 때문에 발생합니다.

  • 빌드 컨테이너는 Docker 클라이언트(/usr/bin/docker)를 실행하고 job의 스크립트 명령을 실행해요.
  • 서비스 컨테이너 (종종 svc로 불림)는 대부분의 Docker 명령을 처리하는 Docker 데몬을 실행해요.

조직에서 커스텀 인증서를 사용하면 두 컨테이너 모두 이 인증서가 필요합니다. 두 컨테이너 모두에 올바른 인증서 구성이 없으면 외부 레지스트리나 서비스에 연결하는 Docker 작업이 인증서 오류로 실패합니다.

이 문제를 해결하려면:

루트 인증서를 CA_CERTIFICATE라는 CI/CD 변수로 저장하세요. 인증서는 다음 형식이어야 합니다.

-----BEGIN CERTIFICATE-----
(certificate content)
-----END CERTIFICATE-----

Docker 데몬을 시작하기 전에 서비스 컨테이너가 인증서를 설치하도록 파이프라인을 구성하세요. 예를 들어:

image_build:
  stage: build
  image:
    name: docker:19.03
  variables:
    DOCKER_HOST: tcp://localhost:2375
    DOCKER_TLS_CERTDIR: ""
    CA_CERTIFICATE: "$CA_CERTIFICATE"
  services:
    - name: docker:19.03-dind
      command:
        - /bin/sh
        - -c
        - |
          echo "$CA_CERTIFICATE" > /usr/local/share/ca-certificates/custom-ca.crt && \
          update-ca-certificates && \
          dockerd-entrypoint.sh || exit
  script:
    - docker info
    - docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD $DOCKER_REGISTRY
    - docker build -t "${DOCKER_REGISTRY}/my-app:${CI_COMMIT_REF_NAME}" .
    - docker push "${DOCKER_REGISTRY}/my-app:${CI_COMMIT_REF_NAME}"

더 알아보기 (Learn more)

Docker-in-Docker의 기본 사용법이 궁금하다면 Docker 이미지로 Docker executor 사용하기 문서를, CI job 토큰으로 레지스트리 인증을 설정하는 방법은 CI job 토큰 문서를 참고하세요.