
수동 배포의 굴레에서 벗어나야 하는 이유
새로운 코드를 작성하고 서버에 반영하려 할 때, 익숙하게 터미널을 열고 docker-compose up --build를 입력하고 있지는 않나요? 분명히 코드를 수정했는데 서버에는 이전 버전이 그대로 돌아가고 있어서 당황했던 경험은 누구에게나 있을 거예요. 빌드 옵션을 깜빡했거나, 빌드 컨텍스트가 꼬여서 엉뚱한 파일을 참조하고 있을 때 발생하는 이 문제는 단순한 실수를 넘어 배포 프로세스 전체의 신뢰도를 떨어뜨리는 원인이 돼요.
매번 수동으로 명령어를 입력하다 보면 오타가 날 수도 있고, 빌드 인자(build args)를 빠뜨려 환경 설정이 잘못될 위험도 커져요. 특히 서비스 규모가 커지고 마이크로서비스 구조로 넘어가게 되면, 관리해야 할 컨테이너가 늘어나면서 이러한 수동 작업은 재앙에 가까운 업무 부하로 다가오게 됩니다. 이제는 사람이 직접 명령어를 치는 단계를 넘어, 시스템이 알아서 판단하고 움직이는 구조를 만들어야 해요.
이 글을 읽고 나면 반복적인 명령 입력에서 해방되어 훨씬 안정적인 배포 환경을 구축할 수 있어요. 컴포즈 build 옵션 자동화의 핵심 원리를 이해하고, 실무에서 바로 쓸 수 있는 스크립트와 파이프라인 설계법을 익히게 될 거예요.
이 글에서 다루는 핵심 내용
- 빌드 컨텍스트 최적화와 효율적인 옵션 설정법
- 환경 변수를 활용한 빌드 인자 자동화 기술
- 로컬과 서버를 잇는 배포 스크립트 작성 가이드
- CI/CD 파이프라인과 연동하여 배포를 자동화하는 전략
자동화를 위한 기초 체력 다지기
본격적인 자동화 스크립트를 작성하기 전에, 우리가 제어해야 할 대상이 무엇인지 정확히 파악해야 해요. 도커 컴포즈 환경에서 빌드 프로세스를 자동화한다는 것은 단순히 명령어 한 줄을 실행하는 것이 아니라, 빌드 컨텍스트(Build Context), 빌드 인자(Build Args), 그리고 이미지 태그 관리라는 세 가지 축을 시스템화하는 것을 의미해요.
먼저 빌드 컨텍스트를 이해해야 해요. 빌드 컨텍스트는 도커 데몬이 빌드 작업을 수행하기 위해 클라이언트로부터 전송받는 파일들의 범위를 말해요. 이 범위가 너무 넓으면 빌드 속도가 느려지고, 너무 좁으면 필요한 파일을 찾지 못해 빌드가 실패하게 되지요. 따라서 자동화의 첫걸음은 이 범위를 명확히 정의하고 불필요한 파일을 제외하는 작업부터 시작해야 합니다.
빌드 컨텍스트를 최적화하면 빌드 속도가 비약적으로 상승해요. 프로젝트 루트 디렉토리에 있는 불필요한 로그 파일, 로컬 데이터베이스 파일, 혹은 거대한 node_modules 폴더가 빌드 과정에 포함되지 않도록 주의해야 합니다.
또한, 빌드 인자를 어떻게 전달할지도 결정해야 해요. 개발 환경, 스테이징 환경, 운영 환경마다 다른 설정값을 주입해야 하는데, 이를 수동으로 입력하는 대신 환경 변수(.env)와 연동하여 자동으로 주입되도록 설계해야 합니다.
자동화 수준별 비교 분석
| 자동화 단계 | 주요 특징 | 장점 | 단점 |
|---|---|---|---|
| 수동 입력 | 매번 명령어를 직접 입력 | 즉각적인 제어 가능 | 휴먼 에러 발생 확률 매우 높음 |
| 쉘 스크립트 | 작성된 .sh 파일을 실행 | 반복 작업 제거, 일관성 확보 | 로컬 환경 의존성 존재 |
| CI/CD 연동 | 코드 푸시 시 자동 실행 | 완전 자동화, 검증 단계 포함 | 초기 설정 복잡도 높음 |
자신의 현재 상황이 어디에 해당하는지 먼저 판단해 보세요. 만약 혼자서 작은 프로젝트를 운영 중이라면 쉘 스크립트만으로도 충분한 효과를 볼 수 있고, 팀 단위의 협업이 이루어지고 있다면 반드시 CI/CD 파이프라인을 구축해야 합니다.
컴포즈 빌드 자동화 실행 5단계
이제 본격적으로 자동화 시스템을 설계하고 구축해 볼 시간이에요. 이론을 넘어 실무에서 바로 사용할 수 있는 구체적인 단계별 실행 전략을 공개합니다.
STEP 1. 빌드 컨텍스트 최적화와 .dockerignore 활용
자동화의 첫 단추는 빌드 컨텍스트를 가볍게 만드는 것이에요. 프로젝트 폴더 전체를 빌드 컨텍스트로 지정하면 도커는 모든 파일을 읽어 데몬으로 전송하려고 시도해요. 이때 .git 폴더나 로컬에 쌓인 대용량 로그, 혹은 빌드 결과물인 dist 폴더 등이 포함되면 빌드 시간이 기하급수적으로 늘어납니다.
이를 방지하기 위해 프로젝트 루트에 반드시 .dockerignore 파일을 생성해야 해요. 이 파일에는 빌드 과정에서 필요 없는 파일 목록을 나열합니다. 예를 들어, 다음과 같은 항목들은 반드시 제외하는 것이 좋아요.
.git/: 버전 관리 이력은 빌드에 필요 없어요.node_modules/: 빌드 단계에서 새로 설치하는 것이 안전해요.*.log: 실행 로그는 컨테이너 이미지에 포함될 필요가 없어요..env.local: 로컬 개인 설정이 운영 이미지에 포함되면 보안 위험이 커요.
이렇게 컨텍스트를 정제하면 빌드 명령을 내렸을 때 전송되는 데이터 양이 줄어들어 전체적인 배포 속도가 눈에 띄게 빨라집니다.
STEP 2. 빌드 인자(Build Args)와 환경 변수 연동
환경마다 다른 설정값을 수동으로 입력하는 것은 자동화의 적이에요. docker-compose.yml 파일의 build 섹션에서 args를 활용하면, 실행 시점에 값을 동적으로 주입할 수 있어요. 이를 위해 프로젝트 루트에 .env 파일을 두고 관리하는 방식을 권장합니다.
예를 들어, 서비스의 버전을 빌드 시점에 고정하고 싶다면 다음과 같이 구성할 수 있어요.
docker-compose.yml 예시:build:
context: .
args:
APP_VERSION: ${VERSION}
이렇게 설정하면
.env 파일에 적힌 VERSION=1.2.0 값을 읽어와 빌드 시점에 주입하게 됩니다.이 방식을 사용하면 스크립트 하나로 ‘버전 관리-빌드-배포’를 한 번에 처리할 수 있게 됩니다. 매번 명령어를 수정할 필요 없이 환경 변수만 갈아 끼우면 되니까요.
STEP 3. 안정성을 더하는 쉘 스크립트 작성
로컬 환경이나 단일 서버에서 자동화를 구현할 때는 쉘 스크립트가 가장 강력한 도구예요. 단순히 명령어를 나열하는 것이 아니라, 실패 시 중단되는 안전장치를 포함하는 것이 핵심입니다.
다음은 실무에서 바로 응용 가능한 배포 스크립트의 구조 예시예요.
#!/bin/bash
set -e # 명령어가 하나라도 실패하면 즉시 중단합니다.
echo "🚀 빌드 프로세스를 시작합니다..."
# 1. 이전 이미지 정리 (선택 사항)
docker-compose down
# 2. 빌드 및 실행 (args 포함)
VERSION=$(grep VERSION .env | cut -d '=' -f2)
docker-compose build --build-arg APP_VERSION=$VERSION
# 3. 컨테이너 실행
docker-compose up -d
echo "✅ 배포가 성공적으로 완료되었습니다!"
여기서 set -e는 정말 중요해요. 만약 빌드 과정에서 네트워크 오류나 문법 오류로 실패했는데도 다음 명령어가 실행되어 구버전 컨테이너가 뜨거나 서비스가 엉망이 되는 상황을 막아주기 때문이에요.
STEP 4. CI/CD 파이프라인(GitHub Actions) 연동
팀 프로젝트라면 이제 클라우드 기반의 자동화를 고려해야 해요. GitHub Actions를 사용하면 코드가 메인 브랜치에 합쳐지는 순간, 서버가 스스로 빌드하고 배포하게 만들 수 있습니다. 전체적인 흐름은 다음과 같아요.
- 코드 푸시(Push) 발생
- GitHub Actions 워크플로우 트리거
- Docker 이미지 빌드 및 Docker Hub/ECR에 푸시
- 대상 서버에 SSH 접속 후 최신 이미지 Pull 및 컨테이너 재시작
이 과정에서 docker-compose build 옵션을 직접 실행하기보다는, 이미 빌드된 이미지를 서버에서 받아오는 ‘Build Once, Deploy Anywhere’ 전략을 쓰는 것이 훨씬 안정적이에요. 빌드는 CI 서버에서 엄격하게 검증하고, 서버는 검증된 이미지를 가져다 쓰기만 하는 구조를 만드는 것이죠.
STEP 5. 멀티 스테이지 빌드를 통한 이미지 경량화
마지막 단계는 빌드된 결과물의 품질을 높이는 것이에요. 멀티 스테이지 빌드(Multi-stage Build)를 적용하면 최종 이미지 크기를 획기적으로 줄일 수 있어요. 빌드할 때만 필요한 컴파일러, 소스 코드, 라이브러리들을 최종 이미지에는 제외하고, 실행에 꼭 필요한 바이너리 파일만 남기는 기술이에요.
이렇게 하면 이미지 크기가 수 기가바이트(GB)에서 수백 메가바이트(MB) 단위로 줄어들고, 이는 곧 네트워크 전송 시간 단축과 서버의 저장 공간 절약으로 이어집니다. 자동화된 파이프라인의 마지막 퍼즐은 바로 이 최적화 단계라고 할 수 있어요.
자주 하는 실수와 해결법
자동화를 구축하다 보면 예상치 못한 곳에서 장애가 발생하곤 해요. 가장 빈번하게 발생하는 실수 5가지를 정리했습니다.
- ❌ 실수:
.dockerignore를 설정하지 않아 빌드 속도가 너무 느림
→ 왜 발생하는가: 불필요한 대용량 파일들이 빌드 컨텍스트에 포함되어 매번 전송되기 때문이에요.
→ ✅ 해결법: 프로젝트 루트에.dockerignore를 만들고node_modules,.git등을 반드시 제외하세요. - ❌ 실수: 빌드 인자(args)를
docker-compose.yml에 정의하지 않음
→ 왜 발생하는가: 환경 변수를 넘겨줘도 컴포즈 파일에서 이를 받아줄 통로가 없기 때문이에요.
→ ✅ 해결법:build: args:섹션을 통해 사용할 인자 이름을 명시하세요. - ❌ 실수: 스크립트 실행 중 오류가 났는데도 계속 진행됨
→ 왜 발생하는가: 쉘 스크립트의 기본 설정은 명령어가 실패해도 다음 줄을 실행하기 때문이에요.
→ ✅ 해결법: 스크립트 상단에set -e를 추가하여 즉시 중단되도록 만드세요. - ❌ 실수: 캐시 때문에 수정된 코드가 반영되지 않음
→ 왜 발생하는가: 도커가 이전 빌드 레이어를 재사용하면서 변경 사항을 감지하지 못할 때가 있어요.
→ ✅ 해결법:docker-compose build --no-cache명령어로 완전히 새로 빌드하거나, 캐시를 깨뜨릴 수 있는 인자를 사용하세요. - ❌ 실수: 권한 문제로 이미지 빌드 실패
→ 왜 발생하는가: CI/CD 환경이나 특정 사용자가 도커 소켓에 접근할 권한이 없기 때문이에요.
→ ✅ 해결법: 해당 사용자를docker그룹에 추가하거나, 실행 시sudo권한을 적절히 관리하세요.
자주 묻는 질문
Q. docker-compose build와 up의 차이가 무엇인가요?
build는 이미지를 생성하는 과정이고, up은 생성된 이미지를 바탕으로 컨테이너를 실행하는 과정이에요. 코드가 바뀌었다면 반드시 --build 옵션을 붙여서 up을 하거나, build를 먼저 실행한 뒤 up을 해야 변경 사항이 반영됩니다.
Q. .env 파일을 어디에 두는 것이 가장 안전한가요?
로컬 개발 시에는 프로젝트 루트에 두는 것이 편리하지만, 운영 환경에서는 보안을 위해 서버의 특정 경로에 따로 보관하고 배포 스크립트가 이를 참조하도록 설계하는 것이 훨씬 안전해요.
Q. 빌드 컨텍스트를 설정할 때 주의할 점은 무엇인가요?
너무 넓게 잡으면 빌드 속도가 느려지고, 너무 좁게 잡으면 Dockerfile 내부에서 COPY 명령어를 쓸 때 파일을 찾지 못해 에러가 발생해요. Dockerfile이 위치한 디렉토리를 기준으로 필요한 파일들만 포함되도록 경로를 잘 계산해야 합니다.
Q. CI/CD 연동 시 이미지를 어디에 저장해야 하나요?
Docker Hub 같은 공용 저장소도 좋지만, 기업 환경이라면 AWS ECR이나 Google Artifact Registry 같은 클라우드 전용 저장소를 사용하는 것이 속도와 보안 측면에서 훨씬 유리해요.
Q. 멀티 스테이지 빌드가 꼭 필요한가요?
운영용 이미지를 만든다면 강력히 추천해요. 빌드 도구들을 모두 제거한 가벼운 이미지는 보안 취약점을 줄여줄 뿐만 아니라, 배포 속도도 훨씬 빨라지기 때문이에요.
자동화로 완성하는 지속 가능한 배포 환경
지금까지 컴포즈 빌드 옵션 자동화의 핵심부터 실무 적용법까지 상세히 살펴보았어요. 처음에는 스크립트를 짜고 파이프라인을 연결하는 과정이 번거롭게 느껴질 수 있지만, 한 번 구축해두면 여러분의 퇴근 시간이 달라질 거예요. 수동 작업에서 오는 불안함을 없애고, 시스템이 주는 안정성을 누려보시길 바랍니다.
.dockerignore로 빌드 컨텍스트를 가볍게 유지하세요.- 빌드 인자는
.env와args를 통해 자동화하세요. - 쉘 스크립트에는 반드시
set -e를 포함해 안전장치를 만드세요. - CI/CD 연동 시에는 빌드와 배포 단계를 분리하여 관리하세요.
- 멀티 스테이지 빌드로 이미지 크기와 보안을 동시에 잡으세요.
오늘 바로 실천할 수 있는 단계별 로드맵을 제안할게요.
- 오늘 할 일: 현재 사용 중인 명령어들을 모아 아주 간단한
deploy.sh파일을 만들어 보세요. - 이번 주 할 일:
.dockerignore를 정밀하게 설정하여 빌드 속도가 얼마나 개선되는지 확인해 보세요. - 실행 직전 할 일: GitHub Actions를 이용해 코드를 올리면 자동으로 빌드가 시작되는 환경을 구축해 보세요.
가장 자주 반복하는 명령 하나부터 스크립트로 옮겨 보세요. 작은 변화가 모여 거대한 운영의 효율을 만듭니다.
관련하여 더 깊이 있는 내용이 궁금하다면 도커 컴포즈 기본 개념 완벽 정리 — 개념부터 실무 활용까지 한눈에 보는 가이드 글을 함께 읽어보시는 것을 추천해요.