[IT-방법] 컴포즈 build 옵션 자동화와 CI/CD 연동 – 반복되는 배포 작업을 완전히 손에서 놓는 기술

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

매일 반복되는 빌드 명령, 언제까지 직접 입력하실 건가요?

퇴근을 앞둔 금요일 저녁, 마지막으로 서버에 코드를 반영하려고 터미널을 켭니다. 평소처럼 docker-compose build 명령어를 치려고 하는데, 갑자기 어제와는 다른 환경 변수가 필요하다는 사실이 떠오릅니다. 급하게 –build-arg 옵션을 추가하고, 컨텍스트 경로를 수정하느라 명령어는 점점 길어집니다. 겨우 명령어를 완성해서 실행했는데, 이번에는 빌드 컨텍스트 용량이 너무 커서 전송 속도가 느려지는 바람에 한참을 기다려야 하네요.

이런 경험, 개발자라면 누구나 한 번쯤 겪어보셨을 거예요. 단순히 명령어 한 줄을 더 치는 것이 문제가 아닙니다. 매번 사람이 직접 옵션을 입력하고 컨텍스트를 확인하는 과정에서 결정적인 오타나 설정 누락이 발생할 수 있다는 점이 진짜 위험 요소예요. 이런 작은 실수가 운영 환경에서는 서비스 중단이라는 거대한 사고로 이어지기도 하거든요.

이제는 손이 기억하는 명령어가 아니라, 시스템이 알아서 처리하는 체계를 만들어야 할 때예요. 컴포즈 build 옵션 자동화는 단순히 편해지기 위한 수단이 아니라, 배포의 안정성을 확보하기 위한 필수적인 과정입니다. 빌드 컨텍스트를 최적화하고, CI/CD 파이프라인에 이 과정을 녹여내면 여러분은 더 이상 배포 명령어를 입력하며 가슴을 졸이지 않아도 돼요.

이 글에서는 반복되는 수동 배포의 굴레를 끊어내고, 사람이 개입하지 않아도 안전하게 컨테이너가 빌드되고 배포되는 환경을 만드는 방법을 구체적으로 다룰게요.

  • 빌드 컨텍스트 최적화를 통한 빌드 속도 개선 방법
  • 컴포즈 build 옵션의 핵심 설정과 자동화 스크립트 작성법
  • CI/CD 도구를 활용한 배포 파이프라인 설계 전략
  • 배포 실패 시 즉시 대응할 수 있는 롤백 자동화 기술

자동화의 첫걸음, 무엇을 먼저 준비해야 할까요?

본격적으로 자동화 스크립트를 짜거나 CI/CD 도구를 도입하기 전에, 우리가 다루는 도구들의 작동 원리를 정확히 이해해야 해요. 무작정 툴을 가져다 쓴다고 해서 마법처럼 배포가 저절로 되는 것은 아니니까요. 특히 도커 컴포즈(Docker Compose)의 빌드 메커니즘을 모른 채 자동화를 시도하면, 오히려 디버깅하기 힘든 복잡한 에러만 늘어날 수 있어요.

반드시 이해해야 할 핵심 개념

가장 먼저 정리해야 할 것은 빌드 컨텍스트(Build Context)예요. 빌드 컨텍스트는 도커 데몬이 빌드를 수행하기 위해 클라이언트로부터 전달받는 파일들의 집합을 의미해요. 만약 프로젝트 루트 폴더 전체를 컨텍스트로 지정해 버리면, 불필요한 로그 파일이나 대용량 데이터까지 모두 빌드 엔진으로 전송하게 되어 성능이 급격히 떨어지게 돼요.

두 번째는 빌드 옵션(Build Options)이에요. build-arg를 통해 빌드 시점에만 필요한 변수를 주입하거나, target 옵션을 사용해 멀티 스테이지 빌드 중 특정 단계까지만 빌드하도록 제어하는 기능들이죠. 이 옵션들을 어떻게 자동화할지가 이번 작업의 핵심입니다.

💡 알아두기
자동화를 시작하기 전, 현재 여러분의 프로젝트에서 .dockerignore 파일이 제대로 설정되어 있는지 반드시 확인하세요. 불필요한 파일을 제외하는 것만으로도 빌드 효율을 50% 이상 높일 수 있습니다.

배포 방식별 특징 비교

현재 여러분의 팀이 어떤 단계에 있는지 아래 표를 통해 확인해 보세요. 어떤 방향으로 나아가야 할지 판단하는 기준이 될 거예요.

비교 항목 수동 명령어 방식 쉘 스크립트 방식 CI/CD 자동화 방식
실행 주체 개발자 직접 입력 로컬/서버 스크립트 전용 빌드 서버/도구
휴먼 에러 위험 매우 높음 낮음 매우 낮음
환경 일관성 개인마다 다름 스크립트 기준 통일 완벽한 표준화 가능
도입 난이도 없음 낮음 중간 이상

처음부터 거대한 CI/CD 시스템을 구축하려고 하면 지치기 쉬워요. 우선은 쉘 스크립트로 자주 쓰는 옵션을 묶는 것부터 시작해서, 점진적으로 GitHub Actions나 GitLab CI 같은 도구로 확장하는 전략을 추천드려요.

실전! 빌드 및 배포 자동화 단계별 가이드

이제 이론을 넘어 실제로 동작하는 시스템을 만들어 볼 차례예요. 단순히 명령어를 복사하는 수준을 넘어, 유지보수가 가능하고 확장이 용이한 구조를 설계하는 데 집중해 보세요.

STEP 1. 빌드 컨텍스트 최적화와 환경 정리

자동화의 첫 번째 단추는 가장 가벼운 빌드 환경을 만드는 것이에요. 컨텍스트가 무거우면 빌드 단계마다 파일 전송 시간이 길어지고, 이는 곧 CI/CD 파이프라인의 전체 실행 시간 증가로 이어집니다.

먼저 프로젝트 루트에 .dockerignore 파일을 생성하세요. 여기에 `node_modules`, `.git`, `*.log`, `tmp`와 같은 불필요한 폴더와 파일을 명시해야 해요. 이렇게 하면 도커 엔진이 빌드할 때 필요한 파일만 딱 골라서 가져가기 때문에 속도가 눈에 띄게 빨라집니다.

또한, 멀티 스테이지 빌드를 활용해 최종 이미지의 크기를 줄이는 설계도 병행해야 해요. 빌드 시에만 필요한 컴파일러나 라이브러리는 첫 번째 스테이지에서만 사용하고, 실행 스테이지에서는 결과물인 바이너리나 정적 파일만 복사해 오는 방식이죠. 이 과정을 자동화하면 매번 최적화된 이미지를 얻을 수 있습니다.

STEP 2. 컴포즈 build 옵션의 체계적 관리

컴포즈 파일(`docker-compose.yml`) 내의 build 섹션을 정적이지 않게 구성하는 것이 핵심이에요. 하드코딩된 값들은 자동화의 가장 큰 적입니다.

예를 들어, 애플리케이션 버전을 결정하는 인자값은 반드시 args를 사용해 주입하도록 설계하세요.

구체적인 구성 예시는 다음과 같아요:

  • context: 빌드 작업의 시작점이 되는 디렉토리 경로를 지정합니다.
  • dockerfile: 기본 Dockerfile 외에 특정 환경(예: dev, prod)을 위한 별도의 Dockerfile이 있다면 경로를 명시합니다.
  • args: 빌드 시점에 동적으로 변하는 값(예: API_URL, VERSION)을 전달합니다.

이렇게 구성해 두면, 나중에 스크립트나 CI 도구에서 값만 바꿔 넣어주면 되기 때문에 매우 유연한 대응이 가능해져요.

STEP 3. 쉘 스크립트를 이용한 로컬 자동화 구현

CI/CD 도구를 쓰기 전, 개발자 로컬 환경에서도 일관된 빌드를 수행할 수 있도록 쉘 스크립트를 만드세요. 단순한 명령어 나열이 아니라 에러 처리가 포함된 견고한 스크립트여야 해요.

스크립트 작성 시 주의할 점은 다음과 같아요:

  1. set -e 옵션을 사용하여 명령어가 하나라도 실패하면 즉시 중단되도록 만드세요.
  2. 환경 변수를 외부 파일(`.env`)에서 읽어오도록 설정하여 보안과 편의성을 동시에 잡으세요.
  3. 빌드 전 기존의 미사용 이미지를 정리하는 명령(`docker image prune -f`)을 포함해 디스크 공간을 관리하세요.

이 단계가 완료되면, 개발자는 복잡한 옵션을 고민할 필요 없이 `./deploy.sh` 한 줄만 실행하면 됩니다. 이것이 자동화의 첫 번째 승리예요.

STEP 4. CI/CD 파이프라인 연동 (GitHub Actions 예시)

이제 로컬의 성공을 클라우드 환경으로 확장할 차례예요. GitHub Actions를 예로 들면, 코드가 `main` 브랜치에 푸시될 때 자동으로 빌드가 시작되도록 설정할 수 있습니다.

파이프라인은 보통 다음과 같은 순서로 흐르게 됩니다:

  • Checkout: 최신 코드를 가져옵니다.
  • Login: 도커 레지스트리(Docker Hub, ECR 등)에 로그인합니다.
  • Build & Push: 컴포즈 옵션을 활용해 이미지를 빌드하고 레지스트리에 업로드합니다.
  • Deploy: 운영 서버에 접속하여 `docker-compose pull`과 `up -d`를 실행합니다.

이 과정에서 캐시 기능을 활용하는 것이 매우 중요해요. GitHub Actions의 `cache` 액션을 사용하여 빌드 레이어를 저장해 두면, 다음 빌드 시 중복된 작업을 건너뛰어 시간을 획기적으로 단축할 수 있습니다.

STEP 5. 배포 검증과 자동 롤백 전략

자동화의 완성은 배포가 성공했는지 확인하고, 문제가 생기면 되돌리는 능력에 달려 있어요. 배포가 끝났다고 해서 바로

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

자동화 시스템을 구축하다 보면 예상치 못한 벽에 부딪히기 마련이에요. 많은 개발자가 공통적으로 겪는 실수들을 정리했으니, 여러분의 상황과 비교해 보세요.

자주 하는 실수와 해결법

빌드 컨텍스트에 너무 많은 파일을 포함함
왜 발생하는가: 프로젝트 폴더의 모든 파일을 도커 데몬으로 전송하려고 시도하기 때문이에요.
해결법: .dockerignore 파일을 작성하여 불필요한 로그, 데이터, 의존성 폴더를 철저히 제외하세요.

빌드 인자(build-arg)를 이미지에 고정함
왜 발생하는가: 보안을 위해 필요한 환경 변수를 Dockerfile 내부에 직접 써놓았기 때문이에요.
해결법: 변수는 반드시 ARGENV를 조합하여 실행 시점에 주입받도록 설계하세요.

CI/CD 파이프라인에서 캐시를 전혀 활용하지 않음
왜 발생하는가: 매번 깨끗한 환경에서 빌드하도록 설정하여 매번 모든 레이어를 새로 생성하기 때문이에요.
해결법: CI 도구가 제공하는 캐시 저장소를 연동하여 이전 빌드 결과물을 재사용하세요.

배포 성공 여부를 단순히 프로세스 실행으로만 판단함
왜 발생하는가: 컨테이너는 떴지만 내부 애플리케이션은 에러로 인해 무한 재시작 중일 수 있기 때문이에요.
해결법: 컴포즈의 healthcheck 기능을 활용해 실제 서비스 가능 상태를 검증하세요.

이미지 태그를 ‘latest’로만 관리함
왜 발생하는가: 가장 최신 이미지를 가져오는 것이 편하다고 생각하기 때문이에요.
해결법: Git 커밋 해시나 시맨틱 버전을 태그로 사용하여 추적 가능한 이미지를 만드세요.

비밀번호나 API 키를 이미지 레이어에 남김
왜 발생하는가: 빌드 과정 중에 간단하게 설정하기 위해 환경 변수로 값을 직접 넣었기 때문이에요.
해결법: 보안이 필요한 정보는 빌드 시점이 아닌, 컨테이너 실행 시점에 Secret 기능을 통해 주입하세요.

자주 묻는 질문

Q. 컴포즈 build 옵션을 자동화하면 빌드 속도가 정말 빨라지나요?

네, 맞아요. 빌드 컨텍스트를 최적화하고 CI/CD의 캐싱 기능을 제대로 활용하면, 매번 처음부터 다시 빌드하는 것보다 훨씬 빠르게 작업을 끝낼 수 있어요. 특히 레이어 캐싱은 빌드 시간을 수 분에서 수 초 단위로 줄여주기도 합니다.

Q. 쉘 스크립트와 CI/CD 도구 중 무엇을 먼저 도입해야 할까요?
가장 효율적인 순서는 로컬에서 사용할 수 있는 쉘 스크립트를 먼저 만드는 거예요. 스크립트로 동작이 검증되면, 그 스크립트의 로직을 그대로 CI/CD 도구(예: GitHub Actions)의 단계로 옮기기만 하면 되거든요.

Q. 빌드 시 전달하는 ARG와 실행 시 전달하는 ENV의 차이가 무엇인가요?
ARG는 이미지를 만드는 빌드 단계에서만 사용할 수 있는 변수예요. 반면 ENV는 이미지가 만들어진 후 컨테이너가 실제로 돌아갈 때 애플리케이션이 참조하는 변수입니다. 용도에 맞춰 구분해서 써야 해요.

Q. 보안이 중요한 환경에서는 어떻게 자동화를 해야 하나요?
비밀번호나 인증 키 같은 민감한 정보는 절대로 Dockerfile이나 이미지 레이어에 넣어서는 안 돼요. CI/CD 도구의 ‘Secrets’ 기능을 사용해 빌드 시점에 주입하거나, 런타임에 외부 보안 저장소에서 가져오도록 설계해야 합니다.

Q. 롤백이 실패할 경우를 대비한 플랜 B는 무엇인가요?
자동화 시스템이 실패할 때를 대비해, 관리자가 수동으로 이전 버전의 이미지를 즉시 실행할 수 있는 ‘Emergency Manual Command’를 문서화해 두는 것이 가장 중요해요.

이제 당신의 배포는 스스로 움직입니다

지금까지 컴포즈의 빌드 옵션을 최적화하고, 이를 자동화하여 안정적인 배포 환경을 구축하는 전체 과정을 살펴보았어요. 처음에는 설정할 것이 많아 보여 막막할 수 있지만, 한 번 제대로 구축해 놓은 자동화 시스템은 여러분의 퇴근 시간을 앞당겨줄 뿐만 아니라 서비스의 안정성까지 책임져 줄 거예요.

✅ 핵심 요약

  • .dockerignore 최적화: 빌드 컨텍스트를 가볍게 유지하여 전송 속도 향상
  • 동적 옵션 활용: build-arg와 target 옵션으로 유연한 빌드 환경 구축
  • 단계적 자동화: 로컬 쉘 스크립트부터 CI/CD 파이프라인으로 확장
  • 검증 시스템 구축: healthcheck를 통해 단순 실행이 아닌 실제 서비스 상태 확인
  • 안전한 롤백: 고유한 이미지 태그 관리와 자동 롤백 로직 마련

자동화는 한 번에 완성되는 것이 아니라, 운영하면서 계속 다듬어가는 과정이에요. 처음부터 완벽한 파이프라인을 만들려고 애쓰기보다는, 가장 자주 반복하는 명령 하나부터 스크립트로 옮겨 보세요. 그 작은 시작이 거대한 데브옵스 환경의 밑거름이 됩니다.

오늘 바로 터미널을 열어 여러분의 프로젝트 루트에 .dockerignore 파일을 만드는 것부터 시작해 보시는 건 어떨까요?

관련하여 더 깊이 있는 내용이 궁금하시다면 아래 글을 참고해 보세요.
도커 컴포즈 기본 개념 완벽 정리 — 개념부터 실무 활용까지 한눈에 보는 가이드

댓글 남기기