[IT-방법] 컴포즈 build 옵션 자동화와 CI/CD 연동 – 반복 빌드에서 해방되는 배포 전략

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

반복되는 수동 배포, 언제까지 직접 하실 건가요?

금요일 저녁, 퇴근을 10분 앞둔 시점에 긴급한 코드 수정 요청이 들어왔어요. 평소처럼 터미널을 열고 docker compose build 명령어를 입력하고, 빌드가 끝나기를 초조하게 기다립니다. 빌드가 완료되면 다시 docker compose up -d를 입력해 컨테이너를 교체해요. 이 과정은 단순해 보이지만, 매번 수동으로 입력하다 보면 명령어를 하나 빼먹거나 엉뚱한 환경 변수를 적용하는 실수를 저지르기 쉬워요.

이런 실수는 단순한 번거로움을 넘어 서비스 장애로 이어질 수 있어요. 빌드 컨텍스트가 너무 커서 빌드 시간이 불필요하게 길어지거나, 로컬 환경과 서버 환경의 설정이 달라 배포 직후에 에러가 터지는 상황은 모든 개발자가 겪어본 악몽이죠. 이제는 사람이 직접 명령어를 입력하는 단계를 넘어, 시스템이 스스로 빌드하고 검증하며 배포하는 구조를 만들어야 해요.

컴포즈 build 옵션 자동화를 구현하면 배포 과정에서 발생하는 인간의 실수를 원천 차단할 수 있어요. 빌드 컨텍스트를 최적화해 속도를 높이고, CI/CD 파이프라인을 통해 코드가 머지되는 순간 자동으로 서비스가 업데이트되는 환경을 구축하는 것이 목표예요. 이 글을 읽고 나면 단순 반복 작업에서 완전히 벗어날 수 있는 실무적인 로드맵을 갖게 될 거예요.

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

  • 빌드 컨텍스트 최적화를 통한 빌드 속도 개선 방법
  • 환경 변수와 build args를 활용한 유연한 설정 자동화
  • 쉘 스크립트와 CI/CD 도구를 이용한 전체 배포 흐름 설계
  • 배포 실패를 대비한 검증 및 롤백 전략

자동화를 시작하기 전 꼭 알아야 할 기본 지식

본격적인 자동화 스크립트를 작성하기 전에, 우리가 제어해야 할 대상이 무엇인지 명확히 이해해야 해요. 단순히 명령어를 실행하는 것과, 빌드 컨텍스트(Build Context)를 관리하는 것은 차원이 다른 문제입니다. 빌드 컨텍스트란 도커 데몬이 빌드 과정에서 사용할 수 있는 파일들의 집합을 의미해요. 이 범위가 너무 넓으면 불필요한 파일까지 모두 도커 엔진으로 전송되어 빌드 시간이 기하급수적으로 늘어납니다.

또한, 컴포즈 파일 내에서 사용하는 build 옵션args의 차이를 아는 것도 중요해요. environment는 컨테이너가 실행될 때 사용되는 변수이지만, args는 이미지를 만드는 빌드 시점에만 유효한 변수예요. 이 둘을 혼동하면 빌드 단계에서 필요한 설정값이 누락되어 이미지가 생성되지 않는 문제가 발생해요.

💡 알아두기
자동화 수준을 결정할 때는 현재 팀의 규모와 배포 빈도를 먼저 고려하세요. 혼자 운영하는 프로젝트라면 쉘 스크립트로도 충분하지만, 여러 명이 협업한다면 반드시 CI/CD 도구를 도입해야 해요.

현재 운영 환경에 맞는 자동화 수준을 결정하기 위해 아래 비교 표를 참고해 보세요.

자동화 단계 주요 방식 장점 단점
수동 배포 직접 명령어 입력 초기 설정 비용 없음 실수 가능성 매우 높음
스크립트 기반 .sh 파일 실행 명령어 일관성 유지 실행 환경 의존적임
CI/CD 연동 GitHub Actions 등 활용 완전 자동화, 히스토리 관리 초기 파이프라인 구축 필요

자동화를 준비할 때 반드시 체크해야 할 사전 준비 리스트예요.

  • 도커 및 도커 컴포즈 설치 확인
  • 프로젝트 루트 디렉터리에 .dockerignore 파일 존재 여부
  • 환경 변수를 관리할 .env 파일 구조 설계
  • 배포 대상 서버의 SSH 접근 권한 및 인증키 준비
  • 버전 관리 시스템(Git) 사용 및 브랜치 전략 수립

이 준비 과정이 탄탄해야 나중에 파이프라인을 구축할 때 예상치 못한 오류로 고생하지 않아요. 특히 빌드 컨텍스트를 미리 정리해두지 않으면 자동화를 도입해도 빌드 속도가 느려져서 결국 무용지물이 될 수 있으니 주의하세요.

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

이제 이론을 넘어 실제로 배포 프로세스를 자동화하는 과정을 단계별로 살펴볼게요. 이 과정은 단순히 명령어를 묶는 것을 넘어, 효율적이고 안전한 이미지를 만드는 데 초점을 맞춰요.

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

자동화의 첫 단추는 빌드 속도를 결정짓는 컨텍스트 관리예요. 많은 개발자가 실수하는 부분 중 하나가 프로젝트 루트 전체를 빌드 컨텍스트로 사용하는 거예요. 만약 프로젝트 폴더 안에 거대한 node_modules, 로그 파일, 혹은 로컬 테스트용 데이터베이스 파일이 들어있다면, 도커는 빌드를 시작할 때마다 이 모든 파일을 도커 데몬으로 전송하려고 시도해요. 이 과정에서 엄청난 네트워크 대역폭과 시간이 낭비됩니다.

이를 해결하려면 반드시 .dockerignore 파일을 작성해야 해요. 이 파일은 Git의 .gitignore와 비슷하게 작동하지만, 도커 빌드 시 제외할 파일들을 지정해요. 아래는 권장되는 설정 예시예요.

💡 알아두기
.dockerignore에는 반드시 node_modules, .git, *.log, tmp 디렉터리 등을 포함시켜야 빌드 속도가 눈에 띄게 빨라져요.

효과적인 컨텍스트 관리를 통해 빌드 시간을 50% 이상 단축할 수 있어요. 파일 크기를 줄이는 것은 단순히 속도뿐만 아니라, 이미지 보안 측면에서도 매우 중요해요. 민감한 설정 파일이나 비밀 키가 이미지 레이어에 포함되는 것을 방지할 수 있기 때문이죠.

STEP 2. build args와 환경 변수를 활용한 유연한 설정

서버마다 설정이 다른데, 매번 docker-compose.yml 파일을 수정하는 것은 자동화의 취지에 어긋나요. 우리는 build args를 사용해 이미지 빌드 시점에 동적인 값을 주입해야 해요. 예를 들어, 개발(dev) 환경과 운영(prod) 환경에서 서로 다른 API 주소를 사용해야 한다면 다음과 같이 구성할 수 있어요.

먼저, docker-compose.yml 파일에 args 섹션을 추가해요.

services:
app:
build:
context: .
args:
- APP_ENV=${APP_ENV}
- API_URL=${API_URL}

그다음, 프로젝트 루트에 .env 파일을 만들고 실제 값을 입력해요. 이렇게 하면 컴포즈 파일은 그대로 둔 채, .env 파일의 내용만 바꿔서 다양한 환경에 대응할 수 있어요. 이때 주의할 점은 build args는 빌드할 때만 존재한다는 사실이에요. 만약 컨테이너가 실행된 후에도 앱 내부에서 이 값을 읽어야 한다면, 반드시 environment 섹션에도 해당 값을 넘겨주어야 해요.

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

CI/CD를 구축하기 전, 먼저 로컬이나 단일 서버에서 사용할 수 있는 쉘 스크립트를 만들어 보세요. 이 스크립트는 명령어를 순차적으로 실행할 뿐만 아니라, 간단한 로직을 포함해 배포 안정성을 높여줍니다. 단순히 docker compose up을 실행하는 게 아니라, 기존 컨테이너의 상태를 확인하고 안전하게 교체하는 로직이 필요해요.

아래는 실무에서 바로 활용 가능한 기본적인 deploy.sh 스크립트의 구조 예시예요.

#!/bin/bash
# 1. 환경 변수 로드
export APP_ENV=production

# 2. 빌드 시작
echo "🚀 빌드를 시작합니다..."
docker compose build --pull

# 3. 컨테이너 교체 (중단 없이 실행하기 위해 up -d 사용)
echo "🔄 컨테이너를 업데이트합니다..."
docker compose up -d

# 4. 상태 확인
echo "🔍 상태를 점검합니다..."
sleep 5
docker compose ps

스크립트를 통해 배포를 진행하면 명령어를 잘못 입력할 확률이 거의 사라져요. 또한, 빌드 전후에 알림을 보내거나 로그를 기록하는 기능을 추가하여 배포 프로세스를 더 투명하게 관리할 수 있어요.

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

이제 진정한 자동화의 꽃인 CI/CD 단계예요. 코드를 GitHub에 push하면 자동으로 빌드부터 배포까지 이어지는 흐름을 만들어야 해요. GitHub Actions를 사용하면 별도의 서버 구축 없이도 강력한 자동화 기능을 누릴 수 있어요.

파이프라인의 핵심은 워크플로우(Workflow) 파일 설정이에요. .github/workflows/deploy.yml 파일을 생성하고 다음과 같은 흐름을 정의하세요.

  • 코드 변경 사항 감지 (Push/Merge)
  • 도커 이미지 빌드 및 테스트 실행
  • 빌드된 이미지를 Docker Hub나 AWS ECR 같은 레지스트리에 업로드(Push)
  • 운영 서버에 접속하여 새로운 이미지를 Pull 받고 컨테이너 재시작

이 과정에서 서버 접속을 위해 SSH 키를 사용하게 되는데, 이때 보안이 매우 중요해요. GitHub Secrets 기능을 사용하여 SSH Private Key, 서버 IP, 접속 계정 등을 안전하게 저장하고 호출해야 해요. 절대로 코드에 직접 비밀번호나 키를 적어서는 안 됩니다.

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

자동화의 완성은 배포가 성공했는지 확인하고, 실패했을 때 얼마나 빨리 복구하느냐에 달려 있어요. 빌드와 배포가 끝났다고 해서 바로 성공이라고 단정 지으면 안 돼요. 컨테이너가 실행은 되었지만, 내부 애플리케이션이 에러를 뱉으며 무한 재시작(CrashLoopBackOff) 상태에 빠질 수 있기 때문이죠.

이를 방지하기 위해 Healthcheck 기능을 활용하세요. docker-compose.yml 파일에 컨테이너가 정상인지 판단할 수 있는 기준(예: 특정 URL에 200 OK 응답이 오는지)을 정의해두면, 도커가 스스로 상태를 모니터링할 수 있어요.

⚠️ 주의
자동 배포 환경에서는 항상 이전 버전의 이미지를 로컬에 남겨두는 전략을 사용하세요. 만약 새 버전 배포 후 헬스체크에 실패하면, 즉시 이전 이미지로 docker compose up -d를 실행해 서비스를 복구해야 합니다.

실제 운영 환경에서는 배포 직후 약 1~2분간 로그를 모니터링하는 단계를 파이프라인에 포함하는 것이 가장 안전해요. 자동화는 단순히 ‘편리함’을 넘어 ‘안정성’을 보장하기 위한 도구임을 잊지 마세요.

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

자동화를 구축하다 보면 예상치 못한 벽에 부딪히곤 해요. 많은 개발자가 반복적으로 겪는 실수들과 그 해결책을 정리해 보았어요.

자주 하는 실수와 해결법

실수: 빌드 컨텍스트에 너무 많은 파일을 포함시켜 빌드가 매우 느림
왜 발생하는가: .dockerignore 파일을 작성하지 않아 node_modules나 대용량 로그 파일까지 모두 도커 데몬으로 전송하기 때문이에요.
해결법: 프로젝트 루트에 .dockerignore 파일을 만들고, 불필요한 디렉터리와 확장자를 명확히 등록하세요.

실수: build args로 넘긴 값이 컨테이너 실행 시점에 사라짐
왜 발생하는가: build args는 빌드 시점에만 유효하며, 컨테이너가 실행된 이후의 환경 변수(environment)와는 별개이기 때문이에요.
해결법: 빌드 시점과 실행 시점 모두 값이 필요하다면, args와 environment 양쪽에 모두 해당 값을 설정해야 해요.

실수: CI/CD 과정에서 비밀번호나 API 키가 노출됨
왜 발생하는가: .env 파일을 그대로 깃허브에 올리거나, 워크플로우 파일에 값을 직접 입력했기 때문이에요.
해결법: 모든 민감 정보는 GitHub Secrets나 별도의 비밀 관리 도구(Vault 등)를 통해 주입하세요.

실수: 새 이미지를 빌드했는데 예전 버전이 계속 실행됨
왜 발생하는가: 태그(Tag)를 사용하지 않고 항상 ‘latest’ 태그만 사용하여, 캐시 문제나 태그 덮어쓰기로 인해 구버전이 호출되는 경우예요.
해결법: 커밋 해시(Commit Hash)나 버전 번호를 이미지 태그로 사용하여 각 빌드마다 고유한 이름을 부여하세요.

실수: 배포 후 서비스가 죽었지만 알 수 없음
왜 발생하는가: 배포 명령만 수행하고, 컨테이너의 실제 실행 상태나 애플리케이션 로그를 확인하는 단계를 생략했기 때문이에요.
해결법: 파이프라인 마지막 단계에 헬스체크 명령어나 로그 검사 단계를 반드시 추가하세요.

자주 묻는 질문

Q. 도커 컴포즈 빌드 옵션을 자동화하면 정말 안전한가요?

네, 사람이 수동으로 입력할 때 발생하는 오타나 누락을 방지할 수 있어 훨씬 안전해요. 다만, 자동화된 스크립트 자체가 잘못 작성되면 오류가 더 빠르게 확산될 수 있으므로, 초기 설계 단계에서 충분한 테스트가 필요해요.

Q. 빌드 속도를 더 높이는 방법은 없나요?

레이어 캐싱을 적극 활용해야 해요. Dockerfile 작성 시 자주 바뀌지 않는 패키지 설치 단계(예: npm install)를 소스 코드 복사 단계보다 위쪽에 배치하면, 소스 코드가 바뀌더라도 패키지 설치 레이어는 재사용되어 속도가 매우 빨라져요.

Q. GitHub Actions 외에 추천하는 CI/CD 도구가 있나요?

프로젝트 규모와 인프라에 따라 달라요. 클라우드 환경이라면 AWS CodePipeline이나 Google Cloud Build가 통합성이 좋고, 자체 서버를 운영한다면 Jenkins나 GitLab CI가 강력한 기능을 제공해요.

Q. .env 파일은 서버에 어떻게 전달하나요?

가장 권장하는 방법은 서버의 특정 경로에 파일을 미리 안전하게 생성해두고, 컴포즈 실행 시 해당 파일을 참조하게 하는 거예요. 또는 CI/CD 도구가 실행 시점에 Secrets를 읽어 .env 파일을 동적으로 생성하도록 설계할 수도 있어요.

Q. 빌드 컨텍스트와 이미지의 차이가 무엇인가요?

빌드 컨텍스트는 도커 엔진에 전달되는 ‘재료(파일들)’이고, 이미지는 그 재료를 가지고 완성된 ‘결과물(스냅샷)’이에요. 컨텍스트가 크면 재료를 나르는 데 시간이 오래 걸리는 것이고, 이미지가 크면 결과물을 저장하고 배포하는 데 시간이 오래 걸리는 거예요.

이제 자동화된 배포의 세계로 뛰어드세요

지금까지 컴포즈 build 옵션 자동화부터 CI/CD 연동까지, 반복적인 작업을 줄이고 안정성을 높이는 방법을 자세히 살펴보았어요. 처음에는 환경 변수를 설정하고 파이프라인을 짜는 과정이 복잡하게 느껴질 수 있지만, 한 번 구축해두면 여러분의 소중한 시간을 지켜주는 강력한 자산이 될 거예요.

✅ 핵심 요약

  • .dockerignore를 통해 빌드 컨텍스트를 최적화하여 속도를 높이세요.
  • build args와 environment를 구분하여 유연한 환경 설정을 만드세요.
  • 쉘 스크립트로 로컬 배포 프로세스를 먼저 표준화하세요.
  • GitHub Actions 같은 CI/CD 도구로 전체 흐름을 자동화하세요.
  • 헬스체크와 롤백 전략을 통해 배포의 안정성을 확보하세요.

자동화는 한 번에 완성되는 것이 아니라, 운영하면서 계속 다듬어가는 과정이에요. 오늘 당장 모든 것을 자동화하려 하기보다, 가장 귀찮고 자주 반복하는 명령어 하나부터 스크립트로 옮겨 보는 건 어떨까요?

오늘 할 일: 현재 프로젝트의 .dockerignore 파일 상태를 점검하고 불필요한 파일이 들어있는지 확인하세요.
이번 주 할 일: 자주 쓰는 배포 명령어를 묶은 간단한 .sh 스크립트를 작성해 보세요.
실행 직전 할 일: CI/CD 환경에 적용할 민감한 정보들을 GitHub Secrets에 등록할 준비를 하세요.

작은 자동화가 모여 여러분의 퇴근 시간을 앞당겨줄 거예요. 지금 바로 첫 번째 스크립트를 작성해 보세요!

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

댓글 남기기