[IT-방법] 컴포즈 build 옵션 실전 구축 가이드 – 컨테이너 운영을 위한 단계별 설정법

build 옵션과 빌드 컨텍스트를 설명하는 실전 구축 가이드 대표 이미지

왜 내 도커 빌드는 항상 이렇게 느리고 불안할까요

어제까지만 해도 잘 돌아가던 서버를 업데이트하려고 docker-compose build 명령어를 입력했는데, 한참을 기다려도 진행률이 올라가지 않아 당황한 적이 있으신가요? 분명히 코드 몇 줄만 바꿨을 뿐인데 빌드 시간이 10분, 20분씩 늘어나는 경험은 1인 개발자에게 큰 스트레스로 다가와요. 심지어는 빌드가 끝나기도 전에 메모리 부족으로 서버가 멈춰버리기도 하죠.

이런 문제의 90% 이상은 잘못 설정된 빌드 컨텍스트에서 시작돼요. 도커는 빌드를 시작할 때 지정된 디렉터리의 모든 파일을 도커 데몬으로 전송하는데, 이때 필요 없는 거대한 데이터 파일이나 로그, 혹은 node_modules 같은 의존성 폴더까지 통째로 보내버리기 때문이에요. 불필요한 파일이 많아질수록 빌드 속도는 느려지고, 네트워크 대역폭은 낭비되며, 보안상 위험한 설정 파일까지 이미지에 포함될 위험이 커져요.

단순히 명령어를 실행하는 것을 넘어, 컴포즈 build 옵션 실전 구축을 제대로 이해하면 서버 운영의 질이 완전히 달라져요. 빌드 시간을 단축하여 개발 생산성을 높이고, 딱 필요한 파일만 포함된 가벼운 이미지를 만들어 운영 비용까지 아낄 수 있거든요.

이번 가이드에서는 운영 서버에 바로 적용할 수 있는 구체적인 실무 노하우를 담았어요. 다음 내용을 차근차근 따라오시면 됩니다.

  • 빌드 컨텍스트의 개념과 올바른 디렉터리 구조 설계법
  • 도커 컴포즈에서 build 옵션을 활용한 정밀한 제어 방법
  • 이미지 크기를 줄이고 빌드 속도를 높이는 최적화 기술
  • 실제 운영 환경에서 마주하는 빌드 오류 해결 전략

빌드 시작 전 반드시 체크해야 할 사전 준비 사항

무턱대고 docker-compose.yml 파일을 수정하기 전에, 현재 내 프로젝트의 상태와 도커의 동작 원리를 먼저 점검해야 해요. 준비 없이 설정을 변경했다가는 오히려 기존에 잘 돌아가던 이미지까지 깨뜨릴 수 있거든요. 특히 1인 개발자라면 환경 설정 하나가 서버 전체의 가용성에 직결된다는 점을 명심해야 해요.

가장 먼저 확인해야 할 것은 빌드 컨텍스트(Build Context)에 대한 이해예요. 빌드 컨텍스트란 도커 엔진이 이미지를 만들기 위해 참조하는 파일들의 범위를 의미해요. 보통 docker-compose.yml 파일이 있는 위치를 기준으로 설정되는데, 이 범위가 너무 넓으면 빌드 성능이 급격히 떨어져요.

💡 알아두기
빌드 컨텍스트는 도커 데몬으로 전송되는 파일의 집합이에요. 이 폴더 안에 있는 모든 파일은 ‘전송’ 단계에서 시간이 소요되므로, 최대한 가볍게 유지하는 것이 핵심이에요.

또한, 현재 프로젝트에서 이미지를 가져다 쓸 것인지(Pull), 아니면 직접 만들 것인지(Build)에 대한 전략이 서 있어야 해요. 아래 표를 통해 상황에 맞는 선택 기준을 확인해 보세요.

구분 이미지 가져오기 (image) 이미지 직접 구축 (build)
주요 용도 DB, Nginx 등 기성 소프트웨어 내가 작성한 애플리케이션 코드
장점 설정이 매우 간편하고 빠름 내 입맛에 맞는 커스텀 가능
단점 코드 변경 사항을 반영할 수 없음 Dockerfile 관리 및 빌드 시간 필요
권장 상황 표준 환경이 필요한 경우 로직 변경이 잦은 서비스 운영 시

준비가 끝났다면 다음 단계에서 실제 프로젝트 구조를 어떻게 잡아야 효율적인지 구체적인 사례와 함께 살펴볼게요. 단순히 파일을 모아두는 것이 아니라, 빌드 효율성을 고려한 설계가 핵심이에요.

컴포즈 build 옵션을 활용한 5단계 실전 구축 절차

이제 본격적으로 실전에 들어가 볼게요. 이론적인 내용보다는 실제 프로젝트 환경에서 어떻게 파일을 배치하고, docker-compose.yml을 어떻게 작성해야 하는지에 집중해서 설명할게요. 우리는 Node.js 기반의 웹 서비스를 운영한다고 가정하고 진행할게요.

STEP 1. 효율적인 디렉터리 및 파일 구조 설계

가장 흔히 하는 실수가 모든 파일을 루트 디렉터리에 몰아넣고 빌드 컨텍스트를 설정하는 것이에요. 이렇게 하면 프로젝트의 모든 설정 파일과 테스트 코드, 심지어는 로그 파일까지 도커 데몬으로 전송되어 빌드 속도가 느려져요. 따라서 애플리케이션 코드와 빌드 설정을 분리하는 구조를 추천해요.

이상적인 구조 예시는 다음과 같아요:

  • /my-project (루트 디렉터리)
  • /my-project/app (실제 애플리케이션 소스 코드)
  • /my-project/docker (Dockerfile 및 관련 설정 파일 보관)
  • /my-project/docker-compose.yml (컴포즈 설정 파일)
  • /my-project/.dockerignore (빌드 제외 파일 목록)

이렇게 구조를 잡으면 docker-compose.yml에서 빌드 컨텍스트를 ./app으로 지정함으로써, 불필요한 루트 디렉터리의 파일들을 빌드 과정에서 완전히 배제할 수 있어요. 이는 빌드 시간 단축뿐만 아니라 이미지의 보안성까지 높여주는 아주 좋은 습관이에요.

STEP 2. 최적화된 Dockerfile 작성하기

Dockerfile은 이미지의 레시피와 같아요. 레시피가 엉망이면 결과물인 이미지도 무겁고 비효율적이게 되죠. 여기서 핵심은 레이어 캐싱(Layer Caching)을 극대화하는 거예요. 도커는 Dockerfile의 각 명령어를 레이어로 저장하는데, 이전 레이어와 내용이 같다면 다시 실행하지 않고 캐시를 사용해요.

잘못된 예시는 의존성 설치(npm install)와 소스 코드 복사(COPY . .)를 한꺼번에 하는 것이에요. 코드가 한 줄만 바뀌어도 매번 모든 라이브러리를 다시 설치해야 하니까요. 아래와 같은 순서로 작성하는 것이 정석이에요.

  1. 베이스 이미지 설정 (예: node:18-alpine)
  2. 패키지 관리 파일만 먼저 복사 (package.json, package-lock.json)
  3. 의존성 설치 수행 (npm install)
  4. 그다음에 나머지 전체 소스 코드 복사 (COPY . .)

이렇게 하면 소스 코드가 수정되어도 npm install 단계는 캐시를 사용하여 즉시 통과하므로 빌드 시간이 획기적으로 줄어들어요.

STEP 3. docker-compose.yml의 build 옵션 정밀 제어

이제 핵심인 docker-compose.yml 설정을 살펴볼게요. 단순히 build: .이라고 쓰는 것은 초보적인 단계예요. 실전에서는 contextdockerfile 옵션을 명확하게 구분해서 사용해야 해요.

💡 알아두기
context는 빌드에 필요한 파일들이 있는 ‘기준점’이고, dockerfile은 그 기준점으로부터 ‘Dockerfile이 어디 있는지’ 알려주는 경로예요. 이 둘을 정확히 분리해야 경로 오류를 막을 수 있어요.

위에서 설계한 구조를 바탕으로 한 설정 예시는 다음과 같아요:

services:
  web-app:
    build:
      context: ./app
      dockerfile: ../docker/Dockerfile
      args:
        NODE_ENV: production
    ports:
      - "3000:3000"

위 설정에서 context./app으로 잡았기 때문에, Dockerfile 내부의 COPY 명령은 app 폴더 내부를 기준으로 작동해요. dockerfile 경로를 통해 별도의 폴더에 있는 설정 파일을 불러오는 방식은 프로젝트를 아주 깔끔하게 유지해 줘요.

STEP 4. .dockerignore를 통한 빌드 컨텍스트 다이어트

빌드 속도를 결정짓는 숨은 공신은 바로 .dockerignore 파일이에요. Git에서 사용하는 .gitignore와 역할이 비슷하지만, 대상은 도커 빌드 과정이에요. 이 파일에 등록된 항목은 빌드 컨텍스트로 전송되지 않아요.

반드시 포함해야 할 항목들은 다음과 같아요:

  • node_modules/: 로컬 환경의 의존성은 이미지 빌드 시 새로 설치해야 해요.
  • .git/: 버전 관리 기록은 이미지 용량만 키울 뿐 필요 없어요.
  • *.log: 각종 로그 파일은 보안상 위험하고 용량만 차지해요.
  • dist/ 또는 build/: 이미 빌드된 결과물이 컨텍스트에 포함되면 혼란을 줄 수 있어요.

주의하세요! 만약 .dockerignore를 설정하지 않으면, 로컬에 있는 수백 메가바이트의 데이터를 도커 데몬으로 보내느라 빌드 시작 전부터 몇 분을 허비하게 될 거예요.

STEP 5. 빌드 인자(args)를 활용한 환경별 맞춤 구축

운영 환경과 개발 환경은 설정이 다를 수밖에 없어요. 매번 Dockerfile을 새로 만드는 대신, build 옵션의 args를 활용하면 하나의 Dockerfile로 여러 환경을 커버할 수 있어요. 예를 들어 개발 시에는 디버그 모드를 켜고, 운영 시에는 최적화된 모드로 빌드하도록 설정할 수 있죠.

컴포즈 파일에서 args를 정의하고 Dockerfile에서 ARG 명령어로 이를 받아서 사용하면, 매우 유연한 컨테이너 운영이 가능해져요. 이는 자동화된 배포 파이프라인(CI/CD)을 구축할 때도 핵심적인 기술이 됩니다.

✅ 실전 구축 시나리오 요약

  • 1. 프로젝트 폴더 구조를 코드와 설정으로 분리한다.
  • 2. Dockerfile 작성 시 의존성 설치 단계를 코드 복사보다 먼저 배치한다.
  • 3. docker-compose.yml에서 context와 dockerfile 경로를 명시한다.
  • 4. .dockerignore로 불필요한 파일을 철저히 차단한다.
  • 5. build args를 사용하여 환경별 변수를 주입한다.

자주 하는 실수와 해결법

현장에서 실제로 가장 많이 발생하는 문제들을 모아봤어요. 문제를 마주했을 때 당황하지 말고 아래 체크리스트를 확인해 보세요.

실수: 빌드 컨텍스트 경로를 루트로 잡고 모든 파일을 다 보냄
👉 왜 발생하는가: 설정을 귀찮게 느껴서 단순히 context: .으로 설정하기 때문이에요.
해결법: .dockerignore를 반드시 작성하고, 가능하다면 context를 실제 소스 코드가 있는 하위 폴더로 좁히세요.

실수: Dockerfile 내의 COPY 경로가 작동하지 않음
👉 왜 발생하는가: context로 지정한 폴더가 기준점인데, 그 기준점 밖의 파일을 복사하려고 하기 때문이에요.
해결법: 모든 복사 대상 파일은 반드시 context 경로 안에 있어야 해요. 경로가 꼬였다면 context 설정을 다시 확인하세요.

실수: 코드 수정 후에도 빌드가 이전 결과물을 그대로 사용함
👉 왜 발생하는가: 도커의 레이어 캐싱이 의도치 않게 작동했기 때문이에요.
해결법적으로 docker-compose build --no-cache 명령어를 사용하여 캐시를 완전히 무시하고 새로 빌드하세요.

실수: 빌드 인자(args)를 전달했는데 Dockerfile에서 인식을 못 함
👉 왜 발생하는가: Dockerfile 내부에 ARG 명령어를 선언하지 않았기 때문이에요.
해결법: docker-compose.ymlargs를 적었다면, Dockerfile에서도 반드시 ARG 변수명을 적어줘야 해당 값을 사용할 수 있어요.

자주 묻는 질문

Q. 빌드 컨텍스트를 너무 작게 잡으면 어떤 문제가 생기나요?

A. 빌드에 꼭 필요한 파일(예: 설정 파일, 스크립트 등)이 컨텍스트 범위 밖에 있으면 Dockerfile의 COPY 명령어가 파일을 찾지 못해 빌드가 실패해요. 항상 빌드에 필요한 최소한의 범위를 포함하되, 불필요한 파일은 .dockerignore로 막는 균형이 중요해요.

Q. 개발 서버와 운영 서버의 이미지를 따로 관리해야 하나요?

A. 하나의 Dockerfile을 사용하되, build args를 통해 환경을 구분하는 방식을 가장 추천해요. 이미지 자체를 따로 만드는 것보다 관리 포인트가 줄어들고 실수할 확률도 낮아지거든요.

Q. 빌드 속도가 너무 느린데, 가장 먼저 확인해야 할 것은 무엇인가요?
A. .dockerignore가 제대로 작동하고 있는지 확인하세요. 빌드 명령을 내린 직후 터미널에 뜨는 ‘Sending build context to Docker daemon’ 메시지의 용량이 너무 크다면 100% 이 문제입니다.

Q. Dockerfile에서 ADD와 COPY 중 무엇을 써야 하나요?
A. 대부분의 경우 COPY를 쓰는 것이 안전해요. ADD는 URL에서 파일을 다운로드하거나 압축을 자동으로 푸는 기능이 있지만, 예측하지 못한 동작을 일으킬 수 있어 꼭 필요한 경우가 아니면 COPY 사용을 권장해요.

지속 가능한 컨테이너 운영을 위한 마무리

지금까지 컴포즈 build 옵션을 활용해 효율적인 빌드 환경을 구축하는 방법을 상세히 살펴봤어요. 처음에는 설정할 것이 많아 번거롭게 느껴질 수 있지만, 한 번 제대로 잡아두면 서버 운영이 놀라울 정도로 쾌적해져요. 빌드 시간이 줄어드는 만큼 여러분의 소중한 개발 시간도 확보할 수 있으니까요.

✅ 핵심 요약

  • 빌드 컨텍스트는 필요한 파일만 포함하도록 좁게 설정하세요.
  • .dockerignore를 활용해 불필요한 파일 전송을 차단하세요.
  • Dockerfile 작성 시 의존성 설치 단계를 먼저 배치하여 캐시를 활용하세요.
  • contextdockerfile 옵션을 명확히 분리하여 관리하세요.
  • build args를 통해 환경별 설정을 유연하게 처리하세요.

이 가이드를 읽으셨다면 이제 다음 단계로 넘어가 보세요. 바로 오늘 하실 일은 현재 운영 중인 프로젝트의 .dockerignore 파일을 점검하고, 빌드 시 전송되는 데이터 크기를 확인하는 것이에요. 만약 용량이 너무 크다면 오늘 알려드린 방법대로 구조를 개선해 보세요.

이번 주 안으로는 build args를 적용해 개발 환경과 운영 환경의 설정을 분리하는 작업까지 마무리해 보시는 걸 추천해요. 이 과정을 문서로 잘 남겨 두시면, 나중에 서버를 이전하거나 팀원이 합류했을 때 훨씬 쉽고 빠르게 환경을 구축할 수 있을 거예요.

도커 컴포즈의 기초가 아직 부족하다면, 도커 컴포즈 기본 개념 완벽 정리 — 개념부터 실무 활용까지 한눈에 보는 가이드를 먼저 읽어보시면 큰 도움이 될 거예요.

댓글 남기기