[IT-방법] 컴포즈 build 옵션 자동화와 CI/CD 연동 – 수동 배포의 굴레에서 벗어나는 실전 기술

build 옵션과 빌드 컨텍스트를 설명하는 자동화와 CI/CD 연동 대표 이미지

수동 배포의 굴레에서 벗어나야 하는 이유

금요일 저녁 퇴근을 앞두고 갑작스러운 버그 수정 요청이 들어왔을 때, 터미널을 열어 컴포즈 build 옵션 자동화를 고려하지 못한 채 하나씩 명령어를 입력하며 초조해해 본 적 있으신가요? 빌드 명령어를 입력하고, 로그가 올라가는 것을 지켜보며, 혹시나 에러가 나지 않을까 가슴을 졸이는 그 시간은 개발자의 에너지를 엄청나게 갉아먹어요.

단순히 명령어를 한두 번 치는 것이 문제가 아니에요. 빌드 컨텍스트가 너무 커서 전송 시간이 길어지거나, 환경 변수가 꼬여서 엉뚱한 설정으로 배포되는 실수는 누구나 할 수 있거든요. 이런 사소한 실수가 모여 서비스 장애로 이어지면 그 뒷감당은 온전히 개발자의 몫이 되죠. 이제는 사람이 직접 명령어를 치는 시대가 아니라, 시스템이 알아서 정확하게 빌드하고 배포하는 환경을 만들어야 해요.

우리가 컴포즈 build 옵션 자동화를 달성하면 얻게 되는 이득은 명확해요. 첫째, 단순 반복 작업에서 해방되어 더 가치 있는 로직 개발에 집중할 수 있어요. 둘째, 사람이 개입할 때 발생하는 휴먼 에러를 원천 차단할 수 있죠. 셋째, CI/CD 파이프라인과 결합하여 코드 push만으로 안정적인 배포가 가능해져요.

이 글에서는 단순히 명령어 하나를 실행하는 수준을 넘어, 실무에서 즉시 적용 가능한 수준의 자동화 전략을 다뤄볼게요.

  • 빌드 컨텍스트 최적화를 통한 속도 향상 방법
  • 쉘 스크립트와 Makefile을 이용한 명령어 패키징
  • GitHub Actions를 활용한 CI/CD 파이프라인 설계
  • 실패를 대비한 배포 검증 및 롤백 전략

자동화 시작 전 반드시 점검할 핵심 요소

무작정 스크립트를 짜기 시작하면 나중에 관리하기 힘든 스파게티 코드가 되기 십상이에요. 자동화를 설계하기 전에 우리가 제어해야 할 대상이 무엇인지 명확히 정의하는 과정이 꼭 필요해요. 특히 빌드 컨텍스트(Build Context)빌드 옵션(Build Options)의 차이를 정확히 아는 것이 시작이에요.

빌드 컨텍스트는 도커 엔진이 빌드 시 참조할 파일들의 범위를 말해요. 이 범위가 너무 넓으면 불필요한 파일까지 모두 전송하게 되어 빌드 속도가 급격히 느려져요. 반면 빌드 옵션은 Dockerfile의 위치, 전달할 인자(args), 타겟 스테이지 등을 결정하는 설정값들이죠. 이 두 가지를 어떻게 조합하느냐에 따라 자동화 스크립트의 복잡도가 완전히 달라져요.

💡 알아두기
도커 컴포즈에서 빌드 자동화를 구현할 때는 단순히 명령어를 실행하는 것이 아니라, 환경에 따른 가변적인 인자값을 어떻게 안전하게 주입할 것인가에 초점을 맞춰야 해요.

자동화 도구를 선택하기 전에 아래 표를 보고 현재 팀의 상황에 맞는 방향을 결정해 보세요.

구분 로컬 스크립트 방식 CI/CD 도구 방식
구현 난이도 낮음 (단순 쉘 스크립트) 높음 (YAML 설정 필요)
관리 대상 개인 또는 팀 로컬 환경 중앙 집중식 서버/클라우드
신뢰도 환경에 따라 편차 큼 매우 높고 일관적임
추천 대상 1인 개발자, 소규모 프로젝트 협업 팀, 상용 서비스 운영

만약 지금 당장 반복되는 명령어 때문에 스트레스를 받고 있다면 로컬 스크립트부터 시작하는 것이 현명해요. 하지만 서비스 규모가 커지고 협업 인원이 늘어난다면 결국 CI/CD 파이프라인으로 넘어가야 한다는 점을 기억해 두세요.

단계별 컴포즈 빌드 자동화 실전 가이드

이제 본격적으로 자동화 시스템을 구축해 볼까요? 단순히 명령어를 모아두는 것이 아니라, 효율적이고 안전한 구조를 만드는 것이 핵심이에요. 총 5단계의 과정을 통해 점진적으로 자동화 수준을 높여가 볼게요.

STEP 1. 빌드 컨텍스트 최적화로 속도 잡기

자동화의 첫 단추는 빌드 속도를 높이는 것이에요. 아무리 빠른 CI 서버를 써도 빌드 컨텍스트가 무거우면 아무 소용이 없거든요. 가장 먼저 해야 할 일은 .dockerignore 파일을 작성하는 것이에요. 프로젝트 내의 node_modules, .git, 로그 파일, 임시 파일들을 반드시 제외해야 해요.

컨텍스트가 가벼워지면 도커 엔진으로 파일을 전송하는 시간이 획기적으로 줄어들고, 빌드 캐시 활용도도 높아져요. 컨텍스트 경로를 설정할 때는 항상 상대 경로를 기준으로 하되, Dockerfile의 위치와 컴포즈 파일의 위치를 일관성 있게 유지하는 것이 좋아요. 이렇게 하면 나중에 스크립트에서 경로를 수정할 일이 거의 없어져요.

STEP 2. 쉘 스크립트와 Makefile로 명령어 패키징하기

매번 긴 명령어를 입력하는 대신, 짧은 별칭(alias)이나 스크립트를 만들어 보세요. 초보자라면 `.sh` 파일을, 조금 더 구조화된 관리를 원한다면 Makefile을 추천해요.

예를 들어, Makefile을 사용하면 다음과 같이 간단하게 빌드와 실행을 묶을 수 있어요.

💡 알아두기
Makefile은 명령어를 그룹화하고 의존성을 관리하기에 아주 탁월해요. build:
docker-compose build --pull
up:
docker-compose up -d
처럼 작성해 두면, 터미널에서 make build 한 줄로 모든 준비가 끝나죠.

스크립트를 작성할 때는 반드시 에러 체크 로직을 넣으세요. 빌드가 실패했는데도 다음 단계인 실행(up)으로 넘어가지 않도록 set -e 옵션을 쉘 스크립트 상단에 추가하는 것이 필수예요.

STEP 3. 환경 변수와 빌드 인자(args) 자동 주입

자동화의 가장 큰 난관은 ‘환경에 따라 달라지는 값’을 처리하는 거예요. 개발(dev), 스테이징(staging), 운영(prod) 환경마다 DB 주소나 API 키가 다를 텐데, 이걸 매번 손으로 수정할 수는 없죠. 이때 활용하는 것이 build args.env 파일이에요.

docker-compose.yml 파일 내에 build: args: 섹션을 만들고, 실제 값은 환경 변수에서 가져오도록 설정하세요. 그리고 CI/CD 도구에서는 각 환경에 맞는 .env 파일을 생성하거나, 보안 저장소(Secrets)에 있는 값을 주입하도록 설계해야 해요. 이렇게 하면 코드 수정 없이 환경 설정만으로 유연한 배포가 가능해져요.

STEP 4. GitHub Actions를 활용한 CI/CD 파이프라인 구축

이제 로컬을 넘어 클라우드에서 자동으로 돌아가는 파이프라인을 만들 차례예요. GitHub Actions를 기준으로 설명하자면, 다음과 같은 흐름을 설계해야 해요.

  1. Checkout: 최신 코드를 가져옵니다.
  2. Build Context Check: 빌드 전에 불필요한 파일이 포함되지 않았는지 검사합니다.
  3. Docker Build & Push: 컴포즈 옵션을 활용해 이미지를 빌드하고, Docker Hub나 AWS ECR 같은 레지스트리에 저장합니다.
  4. Deploy: 운영 서버에 접속하여 새로운 이미지를 pull 받고 컨테이너를 재시작합니다.

이 과정에서 가장 중요한 것은 이미지 태그 관리예요. 단순히 latest 태그만 사용하면, 문제가 생겼을 때 어떤 버전으로 되돌려야 할지 알 수 없게 돼요. 커밋 해시(Commit Hash)나 버전 번호를 태그로 사용하는 습관을 들여야 해요.

STEP 5. 배포 후 자동 검증(Health Check) 단계 추가

빌드가 성공하고 컨테이너가 떴다고 해서 배포가 끝난 게 아니에요. 컨테이너는 실행되었지만 내부 애플리케이션이 에러로 인해 계속 재시작(CrashLoopBackOff)되고 있을 수도 있거든요. 그래서 반드시 Health Check 단계를 자동화 프로세스에 포함해야 해요.

도커 컴포즈의 healthcheck: 옵션을 사용하여 컨테이너가 정상적인 상태인지 스스로 판단하게 만드세요. 파이프라인 마지막 단계에서 docker inspect 명령어로 상태를 확인하거나, 간단한 curl 명령어로 특정 API 엔드포인트가 응답하는지 체크하는 로직을 넣는 것이 가장 확실해요.

실무 적용 시나리오 예시

만약 여러분이 웹 서비스를 운영 중이라면, 다음과 같은 워크플로우를 완성할 수 있어요.

  • 개발자가 코드를 push하면 GitHub Actions가 즉시 동작해요.
  • 자동으로 빌드 컨텍스트를 최적화하여 이미지를 생성해요.
  • 생성된 이미지는 버전 태그와 함께 레지스트리에 저장돼요.
  • 운영 서버의 컴포즈 파일이 업데이트되고 새 이미지를 가져와요.
  • 서비스가 정상 응답을 보내는지 마지막으로 확인한 후 배포를 완료해요.

이 모든 과정이 단 5분 만에 자동으로 이루어지는 모습, 상상만 해도 짜릿하지 않나요?

자주 하는 실수와 해결법 및 FAQ

자동화 시스템을 처음 구축하다 보면 예상치 못한 곳에서 장애가 발생하곤 해요. 미리 알고 있으면 당황하지 않을 수 있는 대표적인 실수들을 정리해 드릴게요.

자주 하는 실수와 해결법

빌드 컨텍스트에 너무 많은 파일이 포함됨
왜 발생하는가: .dockerignore 설정을 누락하거나 범위를 너무 넓게 잡아서 불필요한 데이터까지 도커 엔진으로 전송하기 때문이에요.
✅ 해결법: 프로젝트 루트에 반드시 .dockerignore를 만들고, node_modules, .git, build, dist, logs 등을 엄격하게 제외하세요.

환경 변수(ENV)와 빌드 인자(ARG)를 혼동함
왜 발생하는가: 빌드 시점에 필요한 값(ARG)과 컨테이너 실행 시점에 필요한 값(ENV)의 개념이 섞였기 때문이에요.
✅ 해결법: Dockerfile 안에서 ARG는 빌드 중에만 사용되고 사라진다는 점을 명심하고, 실행 시 필요한 설정은 ENV로 정의하세요.

CI/CD 환경과 로컬 환경의 설정 불일치
왜 발생하는가: 로컬에서는 잘 되는데 서버에서만 안 되는 경우로, 주로 경로(Path) 설정이나 권한 문제 때문이에요.
✅ 해결법: 가능한 한 절대 경로보다는 프로젝트 루트를 기준으로 한 상대 경로를 사용하고, 스크립트 실행 권한(chmod +x)을 반드시 체크하세요.

이미지 캐시 문제로 인한 업데이트 실패
왜 발생하는가: 소스 코드는 바뀌었는데 도커가 기존 캐시를 사용하여 옛날 버전의 이미지를 계속 사용하기 때문이에요.
✅ 해결법: 빌드 시 --no-cache 옵션을 사용하거나, 자주 바뀌는 레이어를 Dockerfile의 가장 아랫부분에 배치하여 캐시 효율을 최적화하세요.

민감한 정보(Secret)의 코드 노출
왜 발생하는가: API 키나 DB 비밀번호를 .env 파일에 넣고 그대로 Git에 push하기 때문이에요.
✅ 해결법: 민감한 정보는 절대로 코드 저장소에 올리지 마세요. GitHub Secrets나 AWS Secrets Manager 같은 전문 보안 도구를 활용해야 해요.

자주 묻는 질문

Q. CI/CD 도구를 반드시 써야 하나요? 그냥 쉘 스크립트만 써도 되지 않을까요?
개인 프로젝트나 아주 작은 규모라면 쉘 스크립트만으로도 충분해요. 하지만 팀 단위 협업을 하거나 배포의 안정성을 높이고 싶다면, 로그를 남기고 단계별 성공/실패를 추적할 수 있는 CI/CD 도구를 쓰는 것이 장기적으로 훨씬 유리해요.

Q. 컴포즈 빌드 속도를 올리는 가장 효과적인 방법은 무엇인가요?
가장 먼저 .dockerignore를 점검하시고요, 그다음으로는 Dockerfile의 레이어 순서를 최적화하는 것이에요. 잘 변하지 않는 라이브러리 설치 단계(예: npm install)를 소스 코드 복사 단계보다 위에 두면 캐시를 아주 잘 활용할 수 있어요.

Q. 배포 중에 오류가 나면 어떻게 자동으로 되돌리나요?
가장 쉬운 방법은 이전 버전의 이미지 태그를 남겨두는 것이에요. 파이프라인 설계 시, 새 배포가 실패하면 기존에 돌아가던 이미지 태그로 docker-compose up -d를 다시 실행하는 스크립트를 작성해 두면 빠르게 복구할 수 있어요.

Q. Docker Compose Build 옵션이 너무 많아서 헷갈려요.
처음에는 context(어디서 가져올지)와 dockerfile(어떤 파일을 쓸지) 두 가지만 확실히 잡으세요. 나머지는 필요할 때 하나씩 추가해도 늦지 않아요.

자동화로 만드는 여유로운 개발 환경

지금까지 컴포즈 build 옵션 자동화의 핵심부터 실전 파이프라인 설계까지 상세히 살펴보았어요. 자동화는 단순히 명령어를 줄이는 작업이 아니라, 개발자가 ‘안심하고’ 코드를 push할 수 있는 신뢰 시스템을 구축하는 과정이에요.

✅ 핵심 요약

  • 빌드 컨텍스트 최적화: .dockerignore를 통해 불필요한 파일 전송 방지
  • 명령어 패키징: Makefile이나 쉘 스크립트로 반복 작업 단순화
  • 환경 변수 분리: ARG와 ENV를 활용하여 환경별 설정 자동화
  • CI/CD 연동: GitHub Actions 등으로 배포 파이프라인 구축
  • 안전장치 마련: Health Check와 버전 태그 관리로 롤백 대비

자동화는 한 번에 완성되지 않아요. 처음에는 작은 쉘 스크립트 하나로 시작해서, 점차 CI/CD와 연동하며 시스템을 키워나가는 것이 가장 실패 없는 방법이에요. 오늘 바로 여러분이 가장 자주 반복하는 명령어 하나부터 스크립트로 옮겨 보는 건 어떨까요? 그 작은 시작이 여러분의 퇴근 시간을 앞당겨 줄 거예요.

🚀 다음 단계로 나아가기

  • 오늘 할 일: 현재 프로젝트의 .dockerignore 파일 점검하기
  • 이번 주 할 일: 자주 쓰는 build 명령어를 Makefile로 묶어보기
  • 실행 직전 할 일: GitHub Actions에서 간단한 build 테스트 실행해 보기

더 깊이 있는 도커 활용법이 궁금하다면, 도커 컴포즈 기본 개념 완벽 정리 — 개념부터 실무 활용까지 한눈에 보는 가이드를 먼저 읽어보시는 것을 추천해요.

댓글 남기기