"내 컴퓨터에서는 되는데요?" — 개발자라면 한 번쯤 들어봤거나 해본 말일 겁니다. 환경 차이로 인한 버그는 매우 흔하고 해결하기도 어렵습니다. Docker는 애플리케이션과 그 실행 환경을 하나의 컨테이너로 패키징해 어디서든 동일하게 실행할 수 있게 해줍니다.

핵심 개념

  • 이미지(Image): 컨테이너를 만들기 위한 읽기 전용 템플릿. 레이어 구조로 효율적으로 관리됩니다.
  • 컨테이너(Container): 이미지를 실행한 인스턴스. 격리된 환경에서 동작합니다.
  • Dockerfile: 이미지를 만드는 설계도(명령어 모음).
  • 레지스트리(Registry): Docker Hub처럼 이미지를 저장하고 공유하는 저장소.

기본 명령어

# 이미지 다운로드
docker pull nginx

# 컨테이너 실행 (-d: 백그라운드, -p: 포트 매핑)
docker run -d -p 8080:80 --name my-nginx nginx

# 실행 중인 컨테이너 목록
docker ps

# 모든 컨테이너 (중지 포함)
docker ps -a

# 컨테이너 중지 / 시작 / 삭제
docker stop my-nginx
docker start my-nginx
docker rm my-nginx

# 로그 확인
docker logs -f my-nginx

# 컨테이너 내부 접속
docker exec -it my-nginx bash

Dockerfile 작성하기

# Node.js 앱 Dockerfile
FROM node:20-alpine          # 베이스 이미지 (경량 Alpine Linux)

WORKDIR /app                  # 작업 디렉토리 설정

# 의존성 먼저 복사 (캐시 최적화)
COPY package*.json ./
RUN npm install --production

# 소스 코드 복사
COPY . .

# 포트 노출 (문서용, 실제 바인딩은 docker run -p에서)
EXPOSE 3000

# 컨테이너 시작 명령
CMD ["node", "app.js"]
# 이미지 빌드
docker build -t my-app:1.0 .

# 실행
docker run -d -p 3000:3000 --name my-app my-app:1.0

.dockerignore

node_modules
.git
.env
*.log
README.md

docker-compose로 멀티 컨테이너 관리

# docker-compose.yml
version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DB_URL=mongodb://db:27017/mydb
    depends_on:
      - db
    volumes:
      - ./logs:/app/logs  # 로그 파일 호스트와 공유

  db:
    image: mongo:7
    ports:
      - "27017:27017"
    volumes:
      - mongo_data:/data/db  # 데이터 영속성

volumes:
  mongo_data:
# 모든 서비스 시작
docker-compose up -d

# 로그 확인
docker-compose logs -f app

# 특정 서비스 재시작
docker-compose restart app

# 전체 종료 및 볼륨 삭제
docker-compose down -v

멀티 스테이지 빌드 (최적화)

# 빌드 스테이지
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# 실행 스테이지 (빌드 결과물만 복사)
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
RUN npm install --production
CMD ["node", "dist/app.js"]
핵심 정리
Docker는 "환경 차이" 문제를 컨테이너로 해결합니다. Dockerfile로 이미지를 정의하고, docker-compose로 여러 서비스를 함께 관리하세요. 멀티 스테이지 빌드로 최종 이미지 크기를 최소화하는 것이 좋습니다.