← 전체 글로 돌아가기

Docker

Dockerfile을 배포 전에 점검하는 방법

Docker 이미지 빌드가 실패하거나 실행 중에 문제가 생기는 것을 미리 방지하는 체크리스트.

Dockerfile을 작성했는데 실제로 빌드하면 실패하거나, 빌드는 되는데 컨테이너가 정상 작동하지 않는 일이 생긴다. 배포 전에 미리 확인할 수 있는 것들이 있다.

문법부터 확인한다

Dockerfile의 문법이 맞는지 먼저 본다. 간단한 검사는 실제 빌드로만 가능하다.

docker build -t my-app:test .

Build 중에 에러가 나면 메시지를 읽고 수정한다. 보통은 명확한 에러 메시지가 나온다.

베이스 이미지를 확인한다

FROM node:18-alpine

이 이미지가 정말 존재하는지, 최신 버전인지 확인한다.

docker pull node:18-alpine

또한 이 이미지에 필요한 도구가 있는지도 본다. Alpine은 최소한 설치만 되어있으므로, 추가 패키지가 필요할 수 있다.

작업 디렉토리를 명확히 정한다

WORKDIR /app

모든 명령이 이 디렉토리에서 실행된다. WORKDIR를 명시하지 않으면 루트에서 실행되므로 좋지 않다.

파일 복사 순서를 생각한다

COPY package*.json ./
RUN npm ci
COPY . .

변경 가능성이 높은 파일(소스 코드)을 마지막에 복사한다. 그래야 Docker 레이어 캐시가 효율적이다.

npm ci를 쓴다

RUN npm ci  # npm install 대신

npm ci는 정확한 버전을 설치하므로, npm install보다 결정론적이다.

환경변수를 설정한다

ENV NODE_ENV=production
ENV PORT=3000

필요한 환경변수를 미리 정의한다. 런타임에 재정의할 수도 있지만, 빌드 시점에 필요한 것들은 여기서 설정한다.

불필요한 파일을 제외한다

.dockerignore 파일을 만든다:

node_modules
.git
.next
dist
*.log
README.md

Dockerfile에 위 파일들을 복사하면 이미지 크기가 커진다.

빌드 결과를 테스트한다

이미지가 빌드되면 실제로 실행해본다.

docker run --rm my-app:test node -v

프로그램이 정상 실행되는지 확인한다. Next.js면:

docker run --rm -p 3000:3000 my-app:test npm start

실제로 서버가 뜨는지 본다.

멀티스테이지 빌드를 고려한다

빌드 단계와 런타임 단계를 분리하면 이미지 크기를 줄일 수 있다.

FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/server.js"]

builder 스테이지의 빌드 도구들이 최종 이미지에 포함되지 않는다.

포트 설정을 확인한다

EXPOSE 3000

이 포트와 실제 애플리케이션이 listen하는 포트가 같아야 한다.

Docker run 할 때도 맞춰야 한다:

docker run -p 3000:3000 my-app:test

헬스체크를 추가한다

HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

컨테이너가 정상 작동하는지 주기적으로 확인한다.

컨테이너 실행할 때 환경변수를 주입한다

docker run -e DATABASE_URL="..." my-app:test

민감한 정보는 Dockerfile에 하드코딩하지 않는다.

결론

Dockerfile은 작성보다 테스트가 중요하다. 실제로 빌드하고, 실행하고, 필요한 포트에서 접속해보면 대부분의 문제를 미리 발견할 수 있다.