[IT-방법] 컴포즈 build 옵션 자동화와 CI/CD 연동 – 배포를 손에서 놓는 방법

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

매번 반복되는 배포 명령, 언제까지 직접 입력하실 건가요?

코드 수정을 마친 뒤 터미널을 열고 docker-compose build를 입력한 뒤, 빌드가 끝날 때까지 멍하니 화면만 바라본 적이 있으신가요? 빌드가 성공하면 다시 docker-compose up -d를 입력하며 서비스가 정상적으로 올라오는지 로그를 확인하는 과정은 너무나 익숙한 풍경이에요. 하지만 서비스 규모가 커지고 관리해야 할 컨테이너가 늘어날수록 이 과정은 고통스러운 노동으로 변해요.

단순히 명령어를 입력하는 것이 문제가 아니에요. 실수로 빌드 옵션을 하나 빼먹거나, 잘못된 빌드 컨텍스트를 지정하여 불필요하게 큰 이미지를 생성하는 실수가 발생하면 운영 환경 전체에 치명적인 영향을 줄 수 있어요. 수동 배포는 인간의 실수를 유도하는 가장 확실한 방법이에요. 개발자가 비즈니스 로직에 집중해야 할 시간에 터미널 앞에서 빌드 진행률을 체크하고 있다면, 그것은 이미 자동화가 시급하다는 신호예요.

이제는 배포를 손에서 놓아야 할 때예요. 컴포즈 build 옵션을 정교하게 설정하고 이를 CI/CD 파이프라인과 결합하면, 코드를 푸시하는 것만으로도 검증부터 배포까지 일사천리로 진행되는 환경을 만들 수 있어요. 단순히 명령어를 대신 실행해 주는 수준을 넘어, 빌드 과정 자체를 최적화하고 안정성을 확보하는 것이 진정한 자동화의 목표예요.

이 글을 읽고 나면 다음과 같은 능력을 갖추게 돼요.

  • 효율적인 빌드를 위한 컴포즈 build 옵션의 핵심 설정법을 익혀요.
  • 빌드 컨텍스트를 최적화하여 이미지 생성 속도를 획기적으로 높여요.
  • CI/CD 파이프라인에 빌드 프로세스를 통합하는 실질적인 방법을 배워요.
  • 배포 실패 시 자동으로 이전 상태로 되돌리는 롤백 전략을 세워요.

자동화 시작 전, 반드시 점검해야 할 핵심 개념

무턱대고 스크립트를 짜기 시작하면 금방 한계에 부딪혀요. 자동화를 설계하기 전에 빌드 컨텍스트(Build Context)build 옵션이 정확히 무엇을 의미하는지 명확히 이해해야 해요. 빌드 컨텍스트는 도커 엔진이 빌드 과정에서 사용할 수 있는 파일들의 범위예요. 이 범위가 너무 넓으면 불필요한 파일까지 모두 전송되어 빌드 속도가 느려지고, 너무 좁으면 필요한 설정 파일을 찾지 못해 오류가 발생해요.

또한, 컴포즈 파일 내에서 제공하는 다양한 build 옵션들을 어떻게 조합하느냐에 따라 이미지의 용량과 보안 수준이 완전히 달라져요. 단순히 이미지를 만드는 것을 넘어, 어떻게 하면 가장 가볍고 안전한 이미지를 빠르게 만들 것인가를 고민해야 해요.

자동화 방식을 결정하기 위해 아래의 기준표를 먼저 확인해 보세요. 현재 여러분의 팀 상황에 어떤 방식이 적합한지 판단하는 데 도움이 될 거예요.

구분 단순 쉘 스크립트 CI/CD 도구 활용 추천 대상
구현 난이도 낮음 높음
확장성 낮음 매우 높음
관리 편의성 개인 PC 위주 팀 전체 공유 가능
주요 활용 로컬 개발 단계 운영/스테이징 배포 규모 있는 팀

💡 알아두기
자동화의 첫걸음은 멱등성(Idempotency)을 확보하는 것이에요. 즉, 같은 명령을 여러 번 실행해도 결과가 항상 동일해야 한다는 뜻이에요. 스크립트가 실행될 때마다 환경이 달라진다면 자동화는 오히려 독이 될 수 있어요.

준비가 되었다면, 이제 구체적으로 무엇을 어떻게 자동화할지 설계 단계로 넘어가 볼까요?

실전! 컴포즈 빌드 자동화 5단계 프로세스

자동화는 단순히 명령어를 묶는 것이 아니라, 단계별로 검증하고 최적화하는 과정이에요. 아래의 5단계 프로세스를 따라 차근차근 적용해 보세요.

STEP 1. 빌드 컨텍스트 최적화와 .dockerignore 설정하기

가장 먼저 해야 할 일은 빌드 속도를 늦추는 주범인 불필요한 파일 전송을 막는 것이에요. 도커 빌드를 시작하면 지정된 컨텍스트 폴더 안의 모든 내용이 도커 데몬으로 복사돼요. 만약 프로젝트 폴더에 거대한 node_modules.git 폴더가 있다면 빌드 명령을 내릴 때마다 엄청난 시간이 소요돼요.

.dockerignore 파일을 반드시 작성하세요. 이 파일은 Git의 .gitignore와 비슷하게 작동하며, 빌드 시 제외할 파일 목록을 정의해요. 빌드 컨텍스트를 가볍게 유지하면 네트워크 대역폭을 아끼고 빌드 시간을 수 분에서 수 초로 단축할 수 있어요. 예를 들어 로그 파일, 로컬 설정값, 테스트 결과물 등은 반드시 제외 목록에 넣어야 해요.

STEP 2. build args를 활용한 환경별 동적 빌드 구현

개발 서버, 스테이징 서버, 운영 서버는 각각 설정이 달라야 해요. 이때 매번 Dockerfile을 수정하는 것은 자동화의 흐름을 깨뜨리는 행동이에요. 대신 컴포즈의 build: args 옵션을 사용해 보세요.

컴포즈 파일에서 특정 변수를 정의하고, 이를 Dockerfile 내부의 ARG 지시어와 연결하면 빌드 시점에 동적으로 값을 주입할 수 있어요. 예를 들어 애플리케이션의 버전을 빌드 시점에 넘겨주거나, 특정 환경에 따라 설치할 라이브러리 구성을 다르게 가져갈 수 있어요. 이렇게 하면 하나의 Dockerfile로 여러 환경을 커버할 수 있는 유연성이 생겨요.

STEP 3. 쉘 스크립트를 이용한 빌드 로직 캡슐화

CI/CD 도구를 도입하기 전이라도, 자주 사용하는 명령어 세트를 쉘 스크립트로 만들어 두는 것만으로도 큰 효과를 볼 수 있어요. 단순하게 docker-compose up만 적는 것이 아니라, 다음과 같은 로직을 포함하는 스크립트를 작성해 보세요.

  • 현재 Git 브랜치 확인
  • 기존 빌드 캐시 정리 여부 선택
  • 빌드 명령 수행 및 성공 여부 확인
  • 빌드 성공 시에만 컨테이너 재시작
  • 실패 시 로그를 파일로 저장

💡 알아두기
스크립트를 짤 때는 set -e 옵션을 사용하는 것을 권장해요. 이 옵션은 스크립트 실행 중 어떤 명령어라도 실패하면 즉시 중단되도록 하여, 잘못된 상태로 배포가 진행되는 것을 막아줘요.

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

이제 진정한 자동화의 핵심인 파이프라인을 설계할 차례예요. 개발자가 코드를 main 브랜치에 푸시하면 자동으로 동작하는 흐름을 만들어야 해요. GitHub Actions를 기준으로 한 표준 워크플로우는 다음과 같아요.

  1. Checkout: 소스 코드를 러너(Runner)로 가져와요.
  2. Build & Test: 컴포즈 build 옵션을 사용하여 이미지를 빌드하고, 간단한 유닛 테스트를 실행해요.
  3. Push: 빌드가 성공하면 생성된 이미지를 Docker Registry(예: Docker Hub, AWS ECR)에 태그를 붙여 업로드해요.
  4. Deploy: 운영 서버에 SSH로 접속하거나 에이전트를 통해 새로운 이미지를 가져와(Pull) 컨테이너를 교체해요.

이 과정에서 가장 중요한 것은 이미지 태그 관리예요. latest 태그만 사용하면 어떤 버전이 배포되었는지 추적하기 어려워져요. Git의 커밋 해시(Commit Hash)를 태그로 사용하여 버전을 고유하게 관리하는 것이 실무의 정석이에요.

STEP 5. 멀티 스테이지 빌드(Multi-stage Build) 적용

마지막 단계는 이미지의 효율성을 극대화하는 것이에요. 빌드할 때 필요한 컴파일러, SDK, 소스 코드 등은 최종 실행 환경에는 필요하지 않아요. 멀티 스테이지 빌드 기능을 활용하면, 빌드 전용 이미지에서 결과물만 뽑아내어 아주 가벼운 런타임 이미지로 옮길 수 있어요.

예를 들어, Java 애플리케이션을 빌드할 때 Maven 이미지에서 jar 파일을 생성하고, 실행 단계에서는 용량이 훨씬 작은 JRE 이미지를 사용하는 방식이에요. 이렇게 하면 이미지 크기가 1GB에서 100MB로 줄어들기도 해요. 이미지 크기가 작아지면 네트워크 전송 속도가 빨라지고, 이는 곧 전체 배포 시간의 단축으로 이어져요.

⚠️ 주의
멀티 스테이지 빌드를 적용할 때, 빌드 단계에서 생성된 보안 인증서나 비밀 키가 최종 이미지에 포함되지 않도록 주의해야 해요. 결과물(Artifacts)만 정확히 복사하는 것이 핵심이에요.

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

자동화를 구축하다 보면 예상치 못한 오류에 부딪히기 마련이에요. 가장 빈번하게 발생하는 문제들을 정리해 두었으니, 문제가 생겼을 때 빠르게 참고해 보세요.

자주 하는 실수와 해결법

  • 실수: 빌드 컨텍스트에 너무 많은 파일을 포함함
    → 왜 발생하는가: .dockerignore를 작성하지 않아 불필요한 데이터까지 전송됨
    해결법: .dockerignore를 작성하여 node_modules, .git, 로그 파일 등을 반드시 제외하세요.
  • 실수: 이미지 태그를 항상 ‘latest’로만 사용함
    → 왜 발생하는가: 어떤 버전이 배포되었는지 확인이 불가능하고 롤백이 매우 어려움
    해결법: Git 커밋 해시나 시멘틱 버저닝(v1.0.1 등)을 사용하여 고유한 태그를 부여하세요.
  • 실수: 빌드 시 환경 변수를 Dockerfile에 하드코딩함
    → 왜 발생하는가: 보안에 취약하며 환경별로 이미지를 새로 만들어야 함
    해결법: 컴포즈의 build args를 통해 빌드 시점에 주입하거나, 런타임에는 environment 옵션을 사용하세요.
  • 실수: 빌드 캐시를 너무 과하게 신뢰함
    → 왜 발생하는가: 소스 코드가 바뀌었는데도 예전 레이어를 사용하여 변경사항이 반영 안 됨
    해결법: 캐시가 꼬인 것 같다면 –no-cache 옵션을 사용하여 깨끗하게 다시 빌드하세요.
  • 실수: CI/CD 파이프라인에서 테스트 단계를 건너뜀
    → 왜 발생하는가: 빠른 배포만을 우선시하다가 버그가 있는 이미지를 배포함
    해결법: 빌드 직후 반드시 자동화된 테스트(Unit/Integration Test) 단계를 거치도록 설계하세요.

자주 묻는 질문

Q. 빌드 속도가 너무 느린데 어떻게 개선할 수 있을까요?

A. 가장 먼저 .dockerignore를 점검하여 컨텍스트 크기를 줄이세요. 그 다음, Dockerfile 내에서 자주 바뀌지 않는 명령(예: 라이브러리 설치)을 위쪽에 배치하여 레이어 캐싱을 극대화하는 것이 중요해요. 멀티 스테이지 빌드 도입도 큰 도움이 됩니다.

Q. build args와 environment의 차이가 무엇인가요?

A. build args는 이미지를 만드는 과정(Build-time)에 사용되는 변수이고, environment는 이미지가 실행되는 과정(Run-time)에 사용되는 변수예요. 보안이 필요한 비밀번호 등은 build args에 넣지 말고 런타임 환경 변수로 관리해야 해요.

Q. CI/CD 도구가 없으면 자동화를 포기해야 하나요?

Q. 빌드 중에 오류가 나면 운영 중인 서비스가 멈추나요?

A. 아니요, 쉘 스크립트로 빌드와 실행을 분리하고, 빌드가 성공했을 때만 기존 컨테이너를 교체하도록 작성하면 서비스 중단 없이 안전하게 배포할 수 있어요.

A. 아니요, 정상적인 CI/CD 파이프라인은 새 이미지를 완전히 빌드하고 검증한 뒤에 기존 컨테이너를 교체해요. 빌드 중 오류가 나면 파이프라인이 중단될 뿐, 이미 돌아가고 있는 서비스에는 영향이 가지 않아요.

자동화로 되찾은 개발자의 여유

배포 자동화는 단순히 명령어를 대신 쳐주는 기능이 아니에요. 그것은 서비스의 안정성을 담보하고, 개발자가 더 가치 있는 일에 집중할 수 있도록 만드는 문화의 변화예요. 오늘 살펴본 내용들을 하나씩 적용해 나가다 보면, 어느새 터미널 앞에서 초조하게 기다리는 시간 대신 더 나은 코드를 고민하는 시간을 갖게 될 거예요.

✅ 핵심 요약

  • .dockerignore를 통해 빌드 컨텍스트를 최소화하세요.
  • build args로 환경별 유연한 빌드 환경을 구축하세요.
  • 멀티 스테이지 빌드로 이미지 용량을 획기적으로 줄이세요.
  • Git 커밋 해시를 사용하여 이미지 태그를 고유하게 관리하세요.
  • CI/CD 파이프라인에 테스트와 롤백 전략을 반드시 포함하세요.

자동화는 한 번에 완성되지 않아요. 처음에는 작은 쉘 스크립트부터 시작해서, 점진적으로 CI/CD 도구를 도입하고, 최종적으로는 전체 파이프라인을 정교하게 다듬어 나가는 과정이 필요해요.

지금 바로 실행해 보세요:

  • 오늘 할 일: 현재 프로젝트의 .dockerignore 파일이 제대로 설정되어 있는지 확인하기
  • 이번 주 할 일: 자주 쓰는 배포 명령어를 쉘 스크립트로 만들어 보기
  • 실행 직전 할 일: GitHub Actions나 GitLab CI의 기초 튜토리얼 살펴보기

가장 자주 반복하는 명령 하나부터 스크립트로 옮겨 보세요. 그 작은 시작이 여러분의 배포 환경을 완전히 바꿔 놓을 거예요.

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

댓글 남기기