[IT-방법] 컴포즈 build 옵션 자동화와 CI/CD 연동 – 반복적인 배포 수동 작업을 끝내는 실무 가이드

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

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

금요일 오후, 퇴근을 앞두고 마지막 배포 명령어를 입력했어요. 그런데 갑자기 서비스가 멈췄습니다. 확인해 보니 빌드 시 전달해야 했던 build argument 하나를 빼먹은 것이 화근이었어요. 수동으로 명령어를 치다 보니 발생한 아주 사소한 실수였지만, 그 결과는 서버 다운이라는 뼈아픈 대가로 돌아왔습니다.

이런 경험은 개발자라면 누구나 한 번쯤 겪어봤을 거예요. 매번 터미널에 길게 나열된 옵션을 복사해서 붙여넣고, 빌드 컨텍스트가 제대로 설정되었는지 눈으로 확인하는 과정은 생각보다 많은 에너지를 소모해요. 단순히 귀찮은 문제를 넘어, 사람이 하는 일인 만큼 실수가 발생할 확률이 매우 높다는 점이 가장 큰 위험 요소예요.

이제는 컴포즈 build 옵션 자동화를 통해 이러한 불안 요소를 제거해야 해요. 빌드 환경을 코드로 관리하고, 사람이 개입할 여지를 줄이는 것이 안정적인 서비스 운영의 핵심입니다. 자동화는 단순히 편해지기 위한 도구가 아니라, 서비스의 가동 시간을 지키기 위한 최소한의 방어선이에요.

이 글에서는 반복적인 배포 작업을 효율적으로 바꾸기 위한 구체적인 전략을 다뤄요. 다음과 같은 내용을 중심으로 이야기를 풀어갈게요.

  • 수동 배포가 초래하는 기술적 부채와 위험성
  • 자동화가 반드시 필요한 핵심 빌드 옵션 정리
  • 파이프라인 설계와 스크립트 작성법
  • 실패를 대비한 검증 및 롤백 전략

자동화 시작 전 반드시 체크해야 할 기본 개념

자동화 시스템을 구축하기 전에 먼저 내가 무엇을 자동화할 것인지 명확히 정의해야 해요. 무턱대고 스크립트부터 짜기 시작하면, 나중에 환경이 변했을 때 수정하기가 매우 까다로워집니다. 가장 먼저 이해해야 할 것은 빌드 컨텍스트(Build Context)build 옵션의 관계예요.

빌드 컨텍스트는 도커 엔진이 빌드를 수행하기 위해 로컬에서 전송받는 파일들의 범위를 의미해요. 이 범위가 너무 넓으면 빌드 속도가 현저히 느려지고, 불필요한 데이터가 이미지에 포함되어 보안 위험까지 발생할 수 있어요. 따라서 무엇을 포함하고 무엇을 제외할지 결정하는 단계가 자동화의 출발점이라고 할 수 있어요.

💡 알아두기
빌드 컨텍스트를 최적화하는 가장 쉬운 방법은 .dockerignore 파일을 사용하는 것이에요. Git의 .gitignore처럼, 빌드 시 불필요한 파일이 도커 데몬으로 전송되지 않도록 차단해 줍니다.

또한, 프로젝트의 규모와 배포 빈도에 따라 어떤 수준의 자동화를 도입할지 결정해야 해요. 모든 팀이 거대한 CI/CD 시스템을 가질 필요는 없거든요. 현재 우리 팀의 상황에 맞는 적절한 자동화 수준을 선택하는 것이 중요해요.

자동화 방식 적합한 상황 장점 단점
로컬 쉘 스크립트 1인 개발자 또는 소규모 프로젝트 구축 비용이 거의 없음 팀원 간 공유 및 동기화 어려움
Makefile 활용 다양한 명령어를 표준화하고 싶을 때 명령어 체계가 명확해짐 Makefile 문법 학습 필요
CI/CD 파이프라인 협업 중인 팀 또는 상용 서비스 완전 자동화 및 높은 안정성 초기 설정 및 유지보수 공수 발생

자동화를 준비하면서 스스로에게 던져야 할 질문들이 있어요. “빌드 시 매번 바뀌는 변수가 있는가?”, “어디까지를 빌드 컨텍스트로 볼 것인가?”, “실패했을 때 이전 상태로 돌아가는 경로가 마련되어 있는가?”와 같은 질문들이에요. 이 질문들에 대한 답을 준비했다면, 이제 본격적인 설계 단계로 넘어갈 준비가 된 것이에요.

단계별 빌드 자동화 실행 가이드

이제 실무에서 바로 적용할 수 있는 자동화 단계를 하나씩 살펴볼게요. 단순히 명령어를 자동화하는 것을 넘어, 시스템의 구조를 어떻게 잡아야 하는지에 집중해서 설명할게요.

STEP 1. 빌드 컨텍스트 최적화와 .dockerignore 설계

자동화의 첫 번째 단계는 빌드 속도를 결정하는 컨텍스트를 관리하는 것이에요. 많은 개발자가 실수하는 부분 중 하나가 프로젝트 폴더 전체를 빌드 컨텍스트로 사용하는 것이에요. 만약 프로젝트 안에 대용량 로그 파일, 로컬 데이터베이스 파일, 혹은 node_modules 같은 무거운 폴더가 포함되어 있다면, 도커는 빌드를 시작하기도 전에 이 모든 파일을 복사하느라 시간을 다 써버려요.

주의
컨텍스트 크기가 커지면 네트워크 대역폭을 많이 사용하고, CI 서버의 디스크 공간을 순식간에 채울 수 있어요. 반드시 필요한 파일만 빌드 프로세스에 참여하도록 필터링해야 해요.

.dockerignore 파일을 작성할 때는 단순히 용량만 줄이는 것이 아니라, 보안 측면도 고려해야 해요. 예를 들어, .env 파일이나 개인 키 파일이 실수로 이미지 안에 포함되어 레지스트리에 올라간다면 대형 사고로 이어질 수 있어요. 따라서 명시적으로 제외 목록을 관리하는 습관을 들여야 해요.

STEP 2. Compose 파일 내 build 옵션 정교화

도커 컴포즈 파일(docker-compose.yml)을 작성할 때, 단순히 build: . 이라고만 적는 것은 자동화를 포기하는 것과 같아요. 빌드 옵션을 세밀하게 설정해야 상황에 따라 유연하게 대처할 수 있어요.

가장 유용한 옵션은 args(빌드 인수)예요. 빌드 시점에만 필요한 환경 변수를 전달할 수 있어, 하나의 Dockerfile로 개발용과 운영용 이미지를 구분해서 만들 수 있어요. 또한, target 옵션을 사용하면 멀티 스테이지 빌드(Multi-stage build)의 특정 단계까지만 빌드하도록 지정할 수 있어 매우 효율적이에요.

예를 들어, 개발 환경에서는 디버깅 도구가 포함된 스테이지를 사용하고, 운영 환경에서는 최종 결과물만 담긴 가벼운 스테이지를 사용하도록 자동화할 수 있어요. 이렇게 하면 운영 환경의 보안성을 높이면서도 개발의 편의성을 동시에 잡을 수 있어요.

STEP 3. 쉘 스크립트를 활용한 빌드 자동화 기초

CI/CD 도구를 도입하기 전에, 먼저 로컬에서 사용할 수 있는 쉘 스크립트를 만드는 것부터 시작해 보세요. 이 단계는 자동화의 프로토타입을 만드는 과정이라고 생각하면 돼요. 스크립트에는 단순히 명령어만 넣는 것이 아니라, 에러 처리 로직이 반드시 포함되어야 해요.

추천
스크립트 상단에 set -e 명령어를 넣어보세요. 이 명령어는 스크립트 실행 중 어떤 명령어라도 에러를 반환하면 즉시 실행을 중단시켜 줍니다. 에러가 발생했는데도 다음 명령어가 실행되어 버리면, 잘못된 이미지가 생성되거나 배포되는 끔찍한 상황이 생길 수 있어요.

스크립트의 흐름은 보통 다음과 같이 구성해요. 첫째, 이전 빌드 아티팩트 정리, 둘째, 필요한 빌드 인수 생성, 셋째, 도커 컴포즈 빌드 실행, 넷째, 생성된 이미지의 태그 부여 및 푸시, 다섯째, 결과 확인 단계예요. 이렇게 구조화된 스크립트는 나중에 그대로 CI/CD 파이프라인의 실행 단계로 옮겨갈 수 있어요.

STEP 4. GitHub Actions를 이용한 CI/CD 파이프라인 설계

이제 로컬 스크립트를 클라우드 환경으로 옮겨볼 시간이에요. GitHub Actions는 설정이 간편하고 커뮤니티가 활발해 가장 추천하는 도구예요. 파이프라인을 설계할 때는 ‘빌드-테스트-배포’의 3단계 원칙을 지키는 것이 좋아요.

먼저, 코드가 푸시되면 자동으로 빌드가 시작되도록 트리거를 설정해요. 이때 build-args를 통해 환경을 구분하고, 빌드가 완료되면 이미지 레지스트리에 푸시하도록 구성해요. 여기서 중요한 것은 이미지 태그 관리예요. 단순히 latest 태그만 사용하면 어떤 버전이 배포되었는지 추적하기가 매우 어려워져요. Git의 커밋 해시(Commit Hash)나 버전 번호를 태그로 사용하여, 문제가 생겼을 때 정확히 어떤 시점의 코드로 돌아가야 할지 알 수 있게 해야 해요.

STEP 5. 배포 검증 및 자동화 확장

빌드와 푸시가 끝났다고 해서 모든 과정이 끝난 것은 아니에요. 자동화의 완성은 ‘배포된 서비스가 정상적으로 작동하는가?’를 확인하는 단계에 있어요. 배포 직후에 간단한 헬스 체크(Health Check) 스크립트를 실행하여 서비스가 응답하는지 확인하는 과정을 파이프라인에 추가하세요.

만약 헬스 체크에 실패한다면, 즉시 이전 버전의 이미지로 롤백(Rollback)하도록 설계해야 해요. 이것이 진정한 의미의 자동화예요. 사람이 개입하지 않아도 시스템이 스스로 문제를 감지하고 안전한 상태로 돌아가는 것, 그것이 우리가 추구해야 할 자동화의 최종 목표입니다.

💡 알아두기
이미지 캐시를 활용하면 빌드 시간을 획기적으로 줄일 수 있어요. CI 환경에서는 매번 새로운 환경에서 빌드가 일어나므로 로컬 캐시를 사용할 수 없는데, 이때 cache_from 옵션을 사용하여 기존에 레지스트리에 올라가 있는 이미지를 캐시로 활용하도록 설정하는 것이 핵심 팁이에요.

자주 하는 실수와 해결법

자동화 시스템을 운영하다 보면 예상치 못한 변수들이 나타나곤 해요. 가장 흔하게 발생하는 실수들을 정리했으니, 문제를 겪고 있다면 확인해 보세요.

  • 빌드 컨텍스트에 불필요한 파일이 포함되어 속도가 느려짐
    왜 발생하는가: .dockerignore 파일을 작성하지 않거나 범위를 너무 넓게 잡았기 때문이에요.
    ✅ 해결법: .dockerignore 파일을 만들어 로그, 임시 파일, node_modules 등을 반드시 제외하세요.
  • 빌드 인수(args) 전달 누락으로 인한 런타임 에러
    왜 발생하는가: 스크립트나 CI 환경에서 변수 환경 설정이 잘못되어 인수가 전달되지 않았기 때문이에요.
    ✅ 해결법: 스크립트 실행 전 변수가 제대로 정의되었는지 echo 명령어로 출력하여 확인하는 단계를 넣으세요.
  • CI 환경에서 캐시를 사용하지 못해 빌드가 매번 오래 걸림
    왜 발생하는가: CI 서버는 매번 깨끗한 상태에서 시작하므로 로컬의 빌드 캐시를 인식하지 못해요.
    ✅ 해결법: docker-compose build 시 –cache-from 옵션을 사용하여 레지스트리의 이미지를 캐시로 지정하세요.
  • 이미지 태그를 ‘latest’로만 관리하여 롤백 불가
    왜 발생하는가: 새로운 이미지가 덮어씌워지면 이전 상태로 되돌릴 수 있는 식별자가 없기 때문이에요.
    ✅ 해결법: Git 커밋 해시나 시맨틱 버저닝(SemVer)을 사용하여 고유한 태그를 부여하세요.
  • 잘못된 빌드 컨텍스트 경로 설정으로 파일 못 찾음
    왜 발생하는가: docker-compose.yml 파일의 위치와 build context의 상대 경로가 일치하지 않기 때문이에요.
    ✅ 해결법: 경로를 절대 경로로 생각하고 구조화하거나, 프로젝트 루트를 기준으로 경로를 명확히 설정하세요.

자주 묻는 질문

Q. 컴포즈 build 옵션을 자동화하면 보안상 위험하지 않나요?

오히려 그 반대예요. 수동으로 명령어를 입력하다 보면 실수로 비밀번호가 포함된 파일을 이미지에 넣을 수 있지만, 자동화된 파이프라인과 .dockerignore를 사용하면 위험 요소를 사전에 차단할 수 있어 훨씬 안전해요.

Q. 쉘 스크립트만으로도 충분할까요?
프로젝트 규모가 작다면 충분해요. 하지만 팀원이 늘어나고 배포 주기가 짧아진다면, 히스토리 관리와 협업을 위해 GitHub Actions 같은 전문 CI/CD 도구로 넘어가는 것을 권장해요.

Q. 빌드 속도를 높이는 가장 효과적인 방법은 무엇인가요?
멀티 스테이지 빌드를 활용해 이미지 크기를 줄이고, 빌드 캐시(cache-from)를 적극적으로 활용하는 것이 가장 확실한 방법이에요.

Q. 롤백은 어떻게 자동화하나요?
배포 단계 이후에 헬스 체크 스크립트를 실행하고, 이 스크립트의 결과값이 실패(exit code non-zero)일 경우 이전 버전의 이미지 태그로 다시 배포하는 명령을 수행하도록 파이프라인을 구성하면 돼요.

지속 가능한 자동화를 위한 로드맵

지금까지 컴포즈 build 옵션 자동화의 핵심 전략을 살펴보았어요. 자동화는 한 번 구축하고 끝나는 것이 아니라, 서비스가 성장함에 따라 계속해서 다듬어 나가야 하는 과정이에요. 처음부터 완벽한 시스템을 만들려고 욕심내기보다는, 가장 반복적이고 실수가 잦은 부분부터 하나씩 자동화해 나가는 것이 중요해요.

✅ 핵심 요약

  • .dockerignore로 빌드 컨텍스트를 가볍게 유지하기
  • build args와 target 옵션으로 빌드 환경 세분화하기
  • 쉘 스크립트에 에러 처리(set -e) 로직 반드시 포함하기
  • Git 커밋 해시를 활용해 이미지 태그를 고유하게 관리하기
  • CI/CD 파이프라인에 반드시 헬스 체크와 롤백 전략 넣기

오늘 당장 실행할 수 있는 작은 단계부터 시작해 보세요. 무엇부터 해야 할지 막막하다면 아래 단계를 따라가 보세요.

  • 오늘 할 일: 현재 사용하는 배포 명령어에서 자주 쓰는 옵션들을 모아 간단한 .sh 파일을 만들어 보세요.
  • 이번 주 할 일: .dockerignore 파일을 정교하게 다듬어 빌드 속도가 얼마나 개선되는지 확인해 보세요.
  • 실행 직전 할 일: 팀원들과 배포 스크립트를 공유하고, 동일한 환경에서 실행되는지 검증해 보세요.

가장 자주 반복하는 명령 하나부터 스크립트로 옮기는 것, 그것이 자동화로 향하는 가장 빠른 길이에요. 반복되는 수동 작업에서 해방되어 더 가치 있는 코드 작성에 집중할 수 있기를 응원해요.

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

댓글 남기기