본문 바로가기
개발환경, 인프라/Docker

[Docker] .gitlab-ci.yml, 잡컨테이너, docker-compose

by Pendine 2026. 1. 24.
728x90
반응형

깃랩 CI 문제

가장 어려웠던 내용.
파일들이 들어있는 폴더를 마운트 했으나, 해당 경로의 파일을 찾으려고 하면,
디렉토리라는 오류 문구가 일관되게 출력되는 현상.
깃랩 ci에 잡 컨테이너에 생성한 폴더에 들어있는 폴더를
도커 컴포즈에서 마운트 했으나, 도커 컴포즈를 통해 생성된 컨테이너에서는
폴더 또는 파일을 찾을 수 없음.

원인 : ci의 동작범위, 파일 동작시의 호스트PC 나 도커의 동작 방법을 모름.

오류 정리 :
예상:
.gitlab-ci.yml을 이용해서 잡 컨테이너 안에서 도커컴포즈 파일을 실행하고,
잡 컨테이너가 도커컴포즈 파일을 실행하니,
도커컴포즈가 잡컨테이너를 호스트PC로 인식하고,
도커 컴포즈 파일에 정의된 볼륨을 마운트하는 경로가 잡 컨테이너인 줄 알았음
실제:
도커컴포즈 실행은 도커 데몬에 의해 실행되고,
도커 데몬은 도커 컴포즈의 볼륨 경로를 도커가 설치된 호스트PC를 개발서버로 인식함.
도커 데몬은 잡 컨테이너의 폴더에 있는 파일을 보지 못하고,
호스트PC의 폴더에 접근하려고하지만, 권한 부족 및 격리환경으로 인해 호스트PC에 접근하지 못함.
도커 데몬은 정의된 경로를 찾지 못하면 해당 경로를 생성함.
결과적으로 도커데몬은 스스로 비어있는 폴더를 생성하고, 해당 폴더 내에서 파일을 찾으려고 하기 때문에 오류가 발생.

"DinD 환경에서의 볼륨 마운트 불일치 문제"

  1. 상황: GitLab Runner(Docker Executor) 내에서 docker-compose 실행.
  2. 원인: 잡 컨테이너 내에서 생성한 파일 경로는 도커 데몬이 관리하는 호스트 서버의 파일 시스템과 격리되어 있음.
  3. 현상: 도커 데몬은 컴포즈 파일의 경로를 호스트 서버 기준으로 해석하여, 잡 컨테이너 내부의 데이터를 보지 못하고 빈 디렉토리를 마운트함.
  4. 해결: 볼륨 마운트(volumes) 대신 docker cp 명령어를 사용하여 잡 컨테이너의 로컬 파일을 실행 중인 타겟 컨테이너로 직접 주입함.

총 정리: 왜 내 인증서는 경로 텍스트로만 나왔나?

구분 빌드 (Dockerfile COPY) 실행 (Compose Volumes) 직접 주입 (docker cp)
기준 위치 잡 컨테이너 (현재 폴더) 호스트 PC (서버 루트/상대경로) 잡 컨테이너 (현재 폴더)
데이터 전달 방식 파일을 복사해서 이미지에 구움 호스트와 컨테이너를 실시간 연결 파일을 컨테이너로 강제 전송
인증서 관리 이미지 재빌드 필요 (불편) 파일만 바꾸면 됨 (편함) 스크립트로 자동화 (편함)
보안 이미지에 Key가 남음 (위험) 이미지에 남지 않음 (안전) 이미지에 남지 않음 (안전)
DinD 환경 결과 성공 (100%) 실패 (경로만 출력됨) 성공 (100%)

ci, docker-compose 스크립트

# 개발환경(테스트) 리버스프록시 담당 nginx
# nginx-dev 컨테이너가 없을 때 만 동작
init-nginx-dev:
  stage: init-nginx
  rules:
    - if : $CI_COMMIT_BRANCH != "main"
  script:
    - echo "--- Forcefully cleaning up old containers by name ---"
    - docker rm -f front-dev nginx-dev || echo "Old containers not found or already removed, proceeding."
    - echo "--- Creating certs directory ---"
    - mkdir -p /certs

    # [수정 포인트] cp 대신 cat을 써서 '파일 안의 내용'을 읽어와 새 파일로 저장합니다.
    - cat "${dev_server_cert_pem}" > /certs/cert.pem
    - cat "${dev_server_key_pem}" > /certs/key.pem

    # 마지막 줄 개행 강제 추가 (Nginx 안전장치)
    - echo "" >> /certs/cert.pem
    - echo "" >> /certs/key.pem

    # [검증] 용량이 57바이트가 아니라 1000바이트 이상인지 확인
    - ls -al /certs/

    # [검증] 잡 컨테이너의 파일 내용 확인.
    - echo "print - cert"
    - cat /certs/cert.pem

    - echo "print - key"
    - cat /certs/key.pem

    # [생성] nginx-dev 컨테이너 생성
    - echo "--- Starting container via docker-compose ---"
    - docker-compose -f docker-compose.nginx-dev.yml up -d --force-recreate --remove-orphans

    - echo "--- Waiting for Nginx to start with default config ---"
    - sleep 3

    # [설정] nginx-dev 컨테이너에 개발PC 접속용 리버스 프록시 설정파일 주입
    - echo "--- Copying custom config and removing default ---"
    - docker cp ./nginx/local.conf nginx-dev:/etc/nginx/conf.d/local.conf

    # [설정] nginx-dev 컨테이너 초기화시 기본 프록시 설정파일 제거
    - docker exec nginx-dev rm -f /etc/nginx/conf.d/default.conf

    # [설정] nginx-dev 컨테이너에서 사용할 로컬 네트워크용 인증서 주입
    - echo "mkdir in nginx-dev::/etc/nginx/certs"
    - docker exec nginx-dev mkdir -p /etc/nginx/certs
    - echo "create file in nginx-dev container cert,key.pem"
    - docker cp /certs/cert.pem nginx-dev:/etc/nginx/certs/cert.pem
    - docker cp /certs/key.pem nginx-dev:/etc/nginx/certs/key.pem

    # [설정] nginx-dev 컨테이너에서 사용할 로컬 네트워크용 인증서 주입 확인
    - docker exec nginx-dev ls -al /etc/nginx/certs

    # [설정] nginx-dev 컨테이너에 주입된 로컬 네트워크 인증서 파일 내용 출력
    - echo "print - container - cert"
    - docker exec nginx-dev cat /etc/nginx/certs/cert.pem
    - echo "print - container - key"
    - docker exec nginx-dev cat /etc/nginx/certs/key.pem

    - echo "--- init-nginx-dev job completed successfully! ---"

.gitlab-ci.yml

services:
  nginx-dev:
    image: nginx:latest
    container_name: nginx-dev
    ports:
      - "8443:8443"
      - "7443:7443"

    # 아래의 볼륨 설정으로 인해서
    # 잡컨테이너만 있고
    # 호스트PC에는 없는
    # 경로를 찾아서 넣으려고함.

    # 깃랩ci에서 컨테이너에 직접 파일넣기.
    # volumes:
    #   - ./certs:/etc/nginx/certs/
    restart: always
    networks:
      - shared_net

networks:
  shared_net:
    external: true
    name: devnet

docker-compose.nginx-dev.yml

깃랩 ci 의 스크립트에서 인증서 파일 내용이 제대로 출력돼도,
docker-compose를 통해 마운트하면 경로가 출력되는 이유.

깃랩 ci의 인증서에서는 깃랩 러너가 잡 컨테이너 에서 스크립트를 실행한 결과가 출력되고 (파일이 있음)
docker-compose에서는 도커 데몬이 호스트 PC 에서 실행된 결과가 출력되기 때문에 (파일이 없음 → 경로가 없으면 생성함)

요약

도커 컴포즈 파일을 실행할 땐 도커 데몬이 동작함으로 인해,
(필요한 파일을 정리해놓은 잡 컨테이너가 아닌데다, 격리된 환경이라 접근하지 못하는) 호스트PC의 경로로 접근하려고 하니,
(접근할 수 없어, 존재하지 않는 경로라고 판단하니) 필요한 파일은 스크립트로 컨테이너에 직접 주입할 것.

728x90
반응형

댓글