← 전체 글로 돌아가기

Docker

Dockerfile 빌드가 로컬에선 되는데 배포에서 실패할 때

도커 이미지는 빌드 환경에 따라 다르게 나온다. 캐시, 네트워크, 권한 문제가 숨어있을 수 있다.

Dockerfile로 로컬에선 docker builddocker run이 잘 되는데, 배포 파이프라인에서 실패한다. 이럴 땐 보통 빌드 컨텍스트, 캐시, 또는 시스템 환경 차이다.

먼저 빌드 캐시를 의심한다

# 캐시 없이 빌드해보기
docker build --no-cache -t my-app:latest .

# 빌드 과정을 자세히 보기
docker build --progress=plain -t my-app:latest .

CI/CD에서 여러 번 빌드하면 캐시가 쌓인다. 어떤 레이어의 캐시가 오래된 패키지를 써서 문제가 생길 수 있다. --no-cache 플래그로 캐시를 무시하고 빌드해보자.

두 번째: 빌드 중 네트워크 의존성 확인

# 문제 있을 수 있는 패턴
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci  # 네트워크가 필요함

# 더 안전한 패턴
RUN npm ci --prefer-offline --no-audit && npm cache clean --force

배포 환경의 네트워크가 제한적이면 npm install이 시간초과될 수 있다. npm ci를 쓰고, 필요하면 타임아웃을 늘린다.

세 번째: 빌드 단계의 환경변수 확인

# 빌드 시에만 필요한 변수
ARG NODE_ENV=production
ARG API_URL

FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN NODE_ENV=${NODE_ENV} npm ci

COPY . .
RUN npm run build

빌드 시점에 필요한 환경변수(API URL, 빌드 플래그 등)가 제대로 전달되지 않으면 빌드가 실패한다. CI/CD 설정에서 --build-arg 옵션을 확인하자.

네 번째: 파일 권한 문제

# 로컬에서 빌드할 때 실행 파일 권한이 있는지 확인
ls -la scripts/

# Dockerfile에서 명시적으로 권한 설정
COPY scripts/entrypoint.sh /app/
RUN chmod +x /app/entrypoint.sh

특히 스크립트 파일이 실행 권한 없이 복사되면 런타임에 실패한다.

다섯 번째: 베이스 이미지 버전 확인

# 위험: 항상 최신 버전을 쓴다
FROM node:latest  # 이미지가 매번 달라질 수 있음

# 안전: 구체적인 버전
FROM node:18.17.1-alpine3.18

latest 태그는 언제든 이미지가 바뀐다. 특정 버전을 명시해야 예측 가능한 빌드를 할 수 있다.

배포 환경에서 확인하는 체크리스트

  1. docker build --no-cache로 캐시 영향을 제거한다
  2. 빌드 로그에서 실패 지점을 본다
  3. --build-arg로 필요한 환경변수를 모두 전달하는지 확인한다
  4. 베이스 이미지 버전을 고정한다
  5. 실제로 docker run해서 이미지가 동작하는지 테스트한다

Docker 빌드 문제는 환경 차이에서 생기는 경우가 많다. 로컬과 배포 환경의 Dockerfile을 동일하게 유지하고, 빌드 스크립트에서 자주 변하는 값들을 명시적으로 제어하자.