개발자를 위한 Docker: 이미지, 컨테이너, Compose
당신은 개발자이고 Docker에 대해 들어봤을 것입니다. 어쩌면 시도해봤지만 이미지, 컨테이너, Compose 개념이 모호하게 느껴질 수 있습니다. 아니면 "내 컴퓨터에서는 작동해"라는 말에 지쳐 일관된 환경을 원할 수도 있습니다. 이 가이드는 잡음을 제거하고 Docker의 핵심 요소와 효과적인 사용법을 실용적으로 이해할 수 있도록 도와줍니다.
개발자에게 Docker가 필요한 이유
Docker는 환경 불일치를 해결합니다. 의존성을 컴퓨터에 직접 설치하는 대신, 앱과 의존성을 컨테이너에 패키징합니다. 컨테이너는 노트북, 동료의 노트북, 프로덕션 등 어디서나 동일하게 실행됩니다. 이는 설정 편차를 제거하고 온보딩을 간단하게 만듭니다.
이미지: 설계도
이미지는 읽기 전용 템플릿입니다. 애플리케이션 코드, 런타임, 라이브러리, 환경 변수를 포함합니다. Dockerfile이라는 지침이 담긴 텍스트 파일로 이미지를 빌드합니다.
다음은 Node.js 앱을 위한 간단한 Dockerfile입니다:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
각 지침은 레이어를 생성합니다. 레이어는 캐시되므로 코드만 변경될 때 재빌드가 빠릅니다. 이미지는 Docker Hub나 프라이빗 레지스트리 같은 레지스트리에 저장됩니다.
컨테이너: 실행 인스턴스
컨테이너는 이미지의 실행 가능한 인스턴스입니다. 격리되어 있지만 호스트 OS 커널을 공유하므로 가볍습니다. docker run으로 컨테이너를 시작합니다.
docker run -p 3000:3000 -d my-app
이 명령은 호스트의 포트 3000을 컨테이너의 포트 3000에 매핑하고 분리 모드로 실행합니다. 컨테이너는 일시적입니다: 볼륨을 사용하지 않으면 제거 시 변경 사항이 손실됩니다.
주요 명령어:
docker ps– 실행 중인 컨테이너 목록docker stop <container>– 컨테이너 중지docker rm <container>– 컨테이너 제거docker images– 이미지 목록docker rmi <image>– 이미지 제거
Docker Compose: 멀티 컨테이너 앱
실제 앱은 종종 웹 서버, 데이터베이스, 캐시 등 여러 서비스가 필요합니다. Docker Compose를 사용하면 단일 YAML 파일로 멀티 컨테이너 애플리케이션을 정의하고 실행할 수 있습니다.
다음은 PostgreSQL과 함께 Node.js 앱을 위한 docker-compose.yml입니다:
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
depends_on:
- db
db:
image: postgres:15
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
docker compose up를 실행하여 두 서비스를 시작합니다. Compose가 네트워킹을 처리하므로 web은 서비스 이름으로 db에 접근할 수 있습니다.
Docker Compose vs. 일반 Docker 사용 시기
| 시나리오 | 사용 |
|---|---|
| 단일 컨테이너 | docker run |
| 여러 서비스 (앱 + DB) | Docker Compose |
| 프로덕션 오케스트레이션 | Kubernetes, Swarm |
개발자를 위한 모범 사례
- .dockerignore 사용하여 node_modules, .git 등을 제외해 빌드 속도를 높입니다.
- 멀티 스테이지 빌드로 최종 이미지를 작게 유지합니다.
- 버전 고정을 FROM 문에 사용하여 재현성을 확보합니다.
- 루트로 실행하지 않기 프로덕션 컨테이너에서.
- 볼륨 사용하여 영구 데이터와 개발 중 라이브 코드 리로딩에 활용합니다.
일반적인 함정
포트 충돌: 포트 3000이 사용 중이면 다른 호스트 포트로 매핑하세요: -p 3001:3000.
데이터 손실: 볼륨 없이는 컨테이너 제거 시 데이터베이스 데이터가 사라집니다.
느린 빌드: Dockerfile 지침을 변경 빈도가 낮은 것부터 높은 것 순으로 정렬하여 캐시를 활용하세요.
FAQ
이미지와 컨테이너의 차이점은 무엇인가요?
이미지는 읽기 전용 템플릿이고, 컨테이너는 해당 이미지의 실행 인스턴스입니다. 동일한 이미지에서 여러 컨테이너를 실행할 수 있습니다.
단일 서비스에도 Docker Compose가 필요한가요?
아니요. Compose는 여러 서비스가 있을 때 빛을 발합니다. 단일 컨테이너에는 docker run이 더 간단합니다.
Docker에서 데이터를 영구적으로 저장하려면 어떻게 하나요?
볼륨을 사용하세요. Compose에서 명명된 볼륨을 정의하거나 docker run에 -v를 사용하여 호스트 디렉터리나 명명된 볼륨을 마운트하세요.
Docker 워크플로우를 간소화할 준비가 되셨나요? JSON Formatter를 확인하여 docker-compose.yml이나 package.json 같은 JSON 구성 파일을 빠르게 검증하고 포맷하세요.