DevFinance
테크·3 min read

Docker 입문 — 개발자 필수 가이드

Docker의 핵심 개념부터 실전 사용법까지, 개발자가 알아야 할 Docker 기초를 정리했습니다.

Docker가 필요한 이유

"내 컴퓨터에서는 되는데..." — Docker는 이 문제를 해결합니다.

  • 개발 환경을 코드로 정의
  • 팀원 모두 동일한 환경에서 작업
  • 로컬과 프로덕션의 차이 최소화

핵심 개념

이미지 (Image)

실행 환경의 스냅샷. Dockerfile로 정의합니다.

컨테이너 (Container)

이미지를 실행한 인스턴스. 격리된 프로세스.

Dockerfile

이미지를 만드는 레시피:

FROM node:20-alpine

WORKDIR /app

COPY package*.json ./
RUN npm ci --only=production

COPY . .

RUN npm run build

EXPOSE 3000
CMD ["npm", "start"]

자주 쓰는 명령어

# 이미지 빌드
docker build -t my-app .

# 컨테이너 실행
docker run -p 3000:3000 my-app

# 백그라운드 실행
docker run -d -p 3000:3000 my-app

# 실행 중인 컨테이너 확인
docker ps

# 컨테이너 중지
docker stop <container-id>

# 로그 확인
docker logs <container-id>

# 컨테이너 진입
docker exec -it <container-id> sh

Docker Compose

여러 서비스를 한 번에 실행:

# docker-compose.yml
services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
    depends_on:
      - db

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: mydb
    volumes:
      - pgdata:/var/lib/postgresql/data
    ports:
      - "5432:5432"

volumes:
  pgdata:
# 전체 시작
docker compose up -d

# 전체 중지
docker compose down

# 로그 확인
docker compose logs -f app

Next.js Dockerfile 최적화

# 빌드 스테이지
FROM node:20-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# 프로덕션 스테이지
FROM node:20-alpine AS runner

WORKDIR /app
ENV NODE_ENV=production

COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static

EXPOSE 3000
CMD ["node", "server.js"]

multi-stage build로 최종 이미지 크기를 크게 줄일 수 있습니다.

.dockerignore

node_modules
.next
.git
*.md
.env*

개발 환경에서의 활용

Hot Reload와 함께 사용

services:
  app:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/app
      - /app/node_modules
    command: npm run dev

volumes로 로컬 파일을 마운트하면 코드 수정 시 즉시 반영됩니다.

실무 팁

  1. Alpine 이미지 사용: node:20 대신 node:20-alpine (900MB → 130MB)
  2. 레이어 캐싱: COPY package*.json 먼저, COPY . . 나중에
  3. non-root 유저: 보안을 위해 root가 아닌 유저로 실행
  4. healthcheck 추가: 컨테이너 상태 모니터링
HEALTHCHECK --interval=30s --timeout=3s \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/ || exit 1
  1. 시크릿 관리: 환경변수에 민감 정보 넣지 말고 Docker Secrets 사용