[IT-방법] 컴포즈 build 옵션 자동화와 CI/CD 연동 – 반복되는 배포 업무를 줄이는 실무 전략

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

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

금요일 오후 늦은 시간, 코드 한 줄을 수정하고 배포를 준비하는데 갑자기 빌드 컨텍스트 오류가 발생해요. 당황해서 명령어를 다시 입력해 보지만, 이번에는 build args가 누락되었다는 메시지가 화면을 가득 채웁니다. 매번 똑같은 명령어를 복사해서 붙여넣고, 빌드가 끝날 때까지 멍하니 모니터를 바라보는 이 상황은 개발자라면 누구나 한 번쯤 겪어본 피로한 일상이에요.

단순히 명령어를 입력하는 것 자체는 어렵지 않아요. 하지만 서비스 규모가 커지고 관리해야 할 마이크로서비스가 늘어날수록, 사람이 직접 개입하는 순간 실수가 생길 확률은 기하급수적으로 높아집니다. 특정 환경 변수가 빠지거나, 엉뚱한 경로를 빌드 컨텍스트로 지정하는 사소한 실수가 전체 시스템의 장애로 이어지기도 해요. 수동 빌드는 단순한 반복을 넘어, 시스템의 안정성을 위협하는 잠재적 위험 요소가 됩니다.

이제는 손으로 직접 명령어를 치는 시대에서 벗어나, 빌드 옵션과 컨텍스트를 정의하고 이를 자동화된 파이프라인에 태우는 단계로 나아가야 해요. 자동화를 구축하면 빌드 환경이 코드와 함께 버전 관리되고, 누가 배포하더라도 항상 동일한 결과물을 얻을 수 있습니다. 배포 과정에서 발생하는 스트레스를 줄이고, 오로지 비즈니스 로직을 개발하는 데에만 집중할 수 있는 환경을 만드는 것이 목표예요.

이 글에서는 다음과 같은 내용을 구체적으로 다뤄요.

  • 반복되는 빌드 작업을 없애기 위한 자동화 대상 정리
  • 도커 컴포즈 build 옵션을 정교하게 설계하는 방법
  • 쉘 스크립트와 CI/CD를 활용한 파이프라인 구축 전략
  • 실패 없는 배포를 위한 검증 및 롤백 프로세스

자동화 설계를 위한 사전 준비와 체크리스트

자동화를 시작하기 전에 가장 먼저 해야 할 일은 현재의 빌드 과정을 객관적으로 분석하는 것이에요. 무턱대고 스크립트를 짜기 시작하면, 나중에 조건이 바뀔 때마다 스크립트 자체를 수정해야 하는 번거로움이 생깁니다. 빌드 프로세스의 각 단계를 원자 단위로 분해해서 바라보는 과정이 반드시 선행되어야 해요.

자동화 수준에 따른 선택 기준

현재 팀의 규모와 서비스의 복잡도에 따라 어떤 방식의 자동화를 도입할지 결정해야 합니다. 모든 프로젝트에 거창한 CI/CD 툴이 필요한 것은 아니에요. 아래 비교 표를 통해 우리 상황에 가장 적합한 단계가 어디인지 확인해 보세요.

자동화 단계 주요 특징 추천 대상 장점
수동 빌드 직접 명령어 입력 개인 프로젝트 설정이 필요 없음
쉘 스크립트 명령어 묶음 실행 소규모 팀 빠른 적용, 낮은 비용
CI/CD 파이프라인 이벤트 기반 자동 실행 실무 서비스 운영팀 안정성 극대화, 이력 관리

성공적인 자동화를 위한 3가지 전제 조건

자동화 시스템을 구축하기 전에 아래 항목들이 준비되어 있는지 반드시 체크해 보세요. 이 준비가 부족하면 자동화 스크립트가 오히려 유지보수의 짐이 될 수 있어요.

  • 명확한 빌드 컨텍스트 정의: Dockerfile이 위치한 경로와 빌드에 필요한 파일들이 어디에 있는지 명확히 구분되어 있어야 해요.
  • 환경 변수 관리 체계: 빌드 시점에 주입해야 하는 ARG와 실행 시점에 필요한 ENV를 구분하여 관리할 수 있어야 합니다.
  • 멱등성 확보: 동일한 명령어를 여러 번 실행해도 시스템이 망가지지 않고 항상 같은 상태를 유지해야 해요.
💡 알아두기
빌드 컨텍스트(Build Context)란 도커 클라이언트가 도커 데몬에게 빌드에 필요한 파일들을 전달하는 범위를 말해요. 이 범위가 너무 넓으면 불필요한 파일까지 전송되어 빌드 속도가 현저히 느려지니 주의해야 합니다.

컴포즈 빌드 자동화의 핵심 실행 단계

이제 본격적으로 수동 작업을 자동화로 전환하는 과정을 살펴볼게요. 단순히 명령어를 묶는 것을 넘어, 어떻게 하면 컨테이너 운영 환경을 견고하게 설계할 수 있는지 단계별로 깊이 있게 다뤄보겠습니다.

STEP 1. docker-compose.yml의 build 옵션 정밀 설계

자동화의 출발점은 docker-compose.yml 파일 내의 build 섹션을 얼마나 정교하게 작성하느냐에 달려 있어요. 많은 개발자가 단순히 context: .만 적고 넘어가지만, 실제 운영 환경에서는 훨씬 더 세밀한 설정이 필요합니다.

우선 context는 빌드에 필요한 파일들이 모여 있는 최상위 디렉토리를 지정해야 해요. 이때 주의할 점은 컨텍스트 경로가 너무 넓으면 안 된다는 것이에요. 예를 들어 프로젝트 루트 전체를 컨텍스트로 잡으면, 무거운 .git 폴더나 node_modules까지 모두 도커 데몬으로 전송되면서 빌드 시간이 몇 분씩 늘어날 수 있습니다. 가장 좋은 방법은 빌드에 꼭 필요한 파일들만 모아놓은 특정 디렉토리를 컨텍스트로 지정하는 것이에요.

또한 dockerfile 경로를 명시적으로 지정하여, 하나의 디렉토리 내에서 여러 종류의 이미지를 빌드할 수 있는 구조를 만드세요. args 옵션을 활용하면 빌드 시점에 주입할 변수들을 관리할 수 있는데, 이는 버전 번호나 환경 설정(dev, staging, prod)을 동적으로 넘길 때 매우 유용합니다. 아래는 최적화된 빌드 설정의 예시 구조예요.

💡 알아두기
build: args로 넘기는 값은 Dockerfile 내에서 ARG 명령어로 선언되어 있어야만 사용할 수 있다는 점을 꼭 기억하세요.

STEP 2. 빌드 컨텍스트 최적화와 .dockerignore 활용

빌드 속도를 획기적으로 높이는 방법은 전송할 데이터의 양을 줄이는 것이에요. 이를 위해 .dockerignore 파일을 반드시 작성해야 합니다. 이 파일은 Git의 .gitignore와 유사한 역할을 하지만, 도커 빌드 프로세스에 특화되어 있어요.

빌드 과정에서 제외해야 할 항목은 크게 세 가지로 나눌 수 있습니다. 첫째는 .git과 같은 버전 관리 데이터이고, 둘째는 node_modules, venv와 같은 의존성 폴더이며, 셋째는 로그 파일이나 임시 파일들입니다. 이들을 제외하지 않으면 도커 데몬으로 수백 메가바이트의 데이터가 전송되면서 네트워크와 I/O 부하를 일으켜요. 실제로 많은 팀이 빌드 단계에서 정체 현상을 겪는 이유가 바로 이 컨텍스트 최적화 실패에 있습니다.

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

매번 복잡한 옵션을 기억하기 어렵다면, 이를 캡슐화한 쉘 스크립트를 만드세요. 단순히 docker-compose build를 실행하는 스크립트가 아니라, 실행 전후의 상태를 관리하는 스마트한 스크립트가 되어야 합니다.

예를 들어, deploy.sh라는 파일을 만들고 다음과 같은 로직을 담아보세요. 스크립트는 먼저 현재 작업 디렉토리가 맞는지 확인하고, 필요한 환경 변수 파일(.env)이 존재하는지 체크합니다. 그 다음 docker-compose build --pull 명령어를 사용하여 항상 최신 베이스 이미지를 가져오도록 설정하고, 빌드가 성공하면 자동으로 docker-compose up -d를 실행하도록 만듭니다. 이렇게 하면 개발자는 ./deploy.sh라는 명령어 하나만으로 안전한 배포를 수행할 수 있게 돼요.

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

스크립트가 로컬 환경의 자동화라면, CI/CD는 팀 전체의 자동화입니다. GitHub Actions를 예로 들어볼게요. 코드가 특정 브랜치(예: main)에 push되면 자동으로 빌드와 배포가 시작되도록 파이프라인을 설계할 수 있습니다.

파이프라인 설계 시 가장 중요한 것은 ‘보안’‘격리’예요. 도커 레지스트리에 로그인하기 위한 자격 증명은 절대로 코드에 직접 적지 말고, GitHub의 Secrets 기능을 활용해 주입해야 합니다. 또한, 빌드 환경(Runner)의 리소스를 고려하여 병렬 빌드를 설정하거나, 빌드 캐시를 활용하는 설정을 추가하면 배포 시간을 크게 단축할 수 있어요.

전형적인 CI/CD 흐름은 다음과 같아요.

  1. 코드 Push 및 Pull Request 발생
  2. CI 워크플로우 실행: Lint 체크, Unit Test 수행
  3. 테스트 통과 시 Build 단계: docker-compose build 실행 및 이미지 생성
  4. 이미지 Push 단계: 빌드된 이미지를 Docker Hub나 AWS ECR로 전송
  5. CD 단계: 운영 서버에 접속하여 docker-compose pull 및 재시작 명령 전달

STEP 5. 이미지 태깅 전략과 아티팩트 관리

자동화된 빌드 시스템에서 가장 흔히 발생하는 문제는

자주 하는 실수와 해결법

자동화 시스템을 처음 구축할 때는 예상치 못한 곳에서 장애가 발생하곤 합니다. 실무에서 가장 빈번하게 발생하는 5가지 사례와 그 해결책을 정리했어요.

  • 실수: 빌드 컨텍스트에 너무 많은 파일이 포함됨
    왜 발생하는가: .dockerignore를 작성하지 않아 node_modules나 로그 파일이 포함되어 전송 속도가 느려짐
    해결법: 프로젝트 루트에 .dockerignore를 생성하고 불필요한 디렉토리를 명시적으로 제외하세요.
  • 실수: 빌드 시 전달한 ARG 값이 Dockerfile에서 무시됨
    왜 발생하는가: Dockerfile 내부에 ARG 선언을 누락함
    해결법: docker-compose.ymlargsDockerfileARG 변수명을 일치시키고 선언을 확인하세요.
  • 실수: CI/CD 환경에서 환경 변수가 누락됨
    왜 발생하는가: 로컬의 .env 파일을 CI 서버로 복사하지 않음
    해결법: CI 도구의 Secrets 기능을 통해 변수를 주입하거나, 빌드 시점에 환경 변수 파일을 동적으로 생성하세요.
  • 실수: 캐시 문제로 인해 수정 사항이 반영되지 않음
    왜 발생하는가: 이전 빌드의 레이어 캐시가 최신 소스 코드를 덮어씌움
    해결법: --no-cache 옵션을 사용하거나, Dockerfile 내에서 의존성 설치 단계를 소스 코드 복사 단계보다 앞선 위치에 배치하여 캐시 효율을 높이세요.
  • 실수: 이미지 태그가 latest로 고정됨
    왜 발생하는가: 배포 시 버전 관리 로직이 구현되지 않음
    해결법: Git 커밋 해시를 기반으로 한 동적 태깅 시스템을 구축하세요.

자주 묻는 질문

Q. 빌드 컨텍스트를 줄이는 것이 왜 그렇게 중요한가요?

도커 빌드는 클라이언트가 파일을 압축해서 데몬에게 보내는 과정부터 시작해요. 컨텍스트가 1GB라면 빌드를 시작하기도 전에 네트워크 전송에만 수 분이 소요됩니다. 이는 개발자의 흐름을 끊고 CI/CD 비용을 높이는 원인이 됩니다.

Q. build: argsenvironment:의 차이점이 무엇인가요?

build: args는 이미지를 만드는 과정(Build-time)에 필요한 변수이고, environment:는 컨테이너가 실행되는 과정(Run-time)에 필요한 변수예요. 이미 빌드된 이미지 내부에는 args 값이 남지 않으므로 용도를 정확히 구분해야 합니다.

Q. 쉘 스크립트만으로 충분할까요, 아니면 꼭 CI/CD를 써야 할까요?
규모가 아주 작다면 스크립트만으로도 충분합니다. 하지만 팀 협업이 시작되고 배포 이력을 관리해야 한다면, 코드 변경과 배포가 유기적으로 연결되는 CI/CD 도입이 필수적이에요.

Q. docker-compose build 명령어가 너무 느린데 방법이 없을까요?
먼저 .dockerignore를 확인하시고, 그 다음 Dockerfile의 레이어 순서를 점검하세요. 자주 바뀌지 않는 명령(패키지 매니저 설치 등)을 상단에 배치하면 캐시를 통해 속도를 높일 수 있습니다.

Q. 자동화 배포 중 오류가 나면 어떻게 대처해야 하나요?
가장 좋은 방법은 이전 버전의 이미지를 유지하는 것입니다. 태깅 전략을 통해 이전 버전의 이미지 주소를 알고 있다면, docker-compose up 명령에 해당 태그를 명시하여 즉시 롤백할 수 있어요.

효율적인 운영을 위한 다음 단계

자동화는 한 번에 완성되는 것이 아니라, 지속적으로 개선해 나가는 과정이에요. 처음부터 완벽한 파이프라인을 만들려고 욕심내기보다는, 가장 귀찮고 반복적인 작업 하나를 골라 스크립트로 만드는 것부터 시작해 보세요.

✅ 핵심 요약

  • .dockerignore를 작성하여 빌드 컨텍스트 크기를 최소화하세요.
  • docker-compose.ymlbuild: args를 활용해 빌드 환경을 유연하게 만드세요.
  • latest 태그 대신 Git 커밋 해시를 사용한 고유 태깅을 생활화하세요.
  • 쉘 스크립트로 명령어를 캡슐화하여 실행 실수를 방지하세요.
  • CI/CD 파이프라인을 통해 배포 프로세스를 코드와 연결하세요.
  • 실패를 대비한 이미지 롤백 전략을 항상 염두에 두세요.

오늘 당장 무엇을 해야 할지 막막하다면, 다음의 단계별 로드맵을 따라가 보세요.

  • 오늘 할 일: 현재 사용 중인 빌드 명령어를 메모장에 정리하고, 불필요한 파일이 빌드에 포함되는지 docker history로 확인해 보세요.
  • 이번 주 할 일: 반복되는 명령어를 담은 간단한 deploy.sh 파일을 만들어 팀원들과 공유해 보세요.
  • 실행 직전 할 일: GitHub Actions나 GitLab CI를 활용해 코드가 Push될 때 자동으로 빌드가 돌아가는 환경을 구축해 보세요.

가장 자주 반복하는 명령 하나부터 스크립트로 옮겨 보세요. 작은 자동화가 모여 여러분의 소중한 개발 시간을 확보해 줄 거예요. 배포의 공포에서 벗어나 더 가치 있는 코드에 집중하는 즐거움을 누리시길 바랍니다.

도커 컴포즈의 기초가 아직 부족하다면, 도커 컴포즈 기본 개념 완벽 정리 — 개념부터 실무 활용까지 한눈에 보는 가이드 글을 먼저 읽어보시는 것을 추천해요.

댓글 남기기