0466

인프라

[Docker] Docker란?

| 서론

안녕하세요, 팡일입니다.

이번 포스팅에서는 Docker가 무엇인지부터 시작해서, 실제로 개발하면서 자주 사용하는 기본 명령어까지 한 번에 정리해보려고 합니다.

처음 Docker를 접하면 개념이 조금 추상적으로 느껴질 수 있는데, 이 글에서는 최대한 직관적인 비유와 함께 이해할 수 있도록 설명해보겠습니다.

| Docker란?

: Docker는 애플리케이션과 그 실행에 필요한 모든 환경(라이브러리, 설정 파일, 런타임 등)을 하나의 컨테이너로 패키징하는 기술입니다. 이 컨테이너는 어떤 환경에서도 동일하게 동작하기 때문에, 개발·테스트·프로덕션 환경 간의 차이로 발생하는 문제를 근본적으로 줄일 수 있습니다.

1) 가상머신 (VM)과 Docker 컨테이너의 차이

Docker를 이해하려면 기존 방식인 가상머신(VM)과의 차이를 먼저 알아두는 것이 좋습니다. 둘 다 “격리된 환경을 만든다”는 점은 같지만, 동작 방식과 효율성에서 큰 차이가 있습니다.

구분

가상머신 (VM)

Docker 컨테이너

구조

하이퍼바이저 + 게스트 OS

Docker Engine (커널 공유)

크기

GB 단위

MB 단위

시작 시간

분 단위

초 단위

리소스 사용

무겁다 (OS 전체 로드)

가볍다 (필요한 것만)

이식성

제한적

뛰어남

핵심은 Docker는 OS를 새로 띄우지 않고, 필요한 부분만 격리해서 실행하기 때문에 훨씬 가볍고 빠르다는 점입니다.

2) Docker를 써야 하는 이유

그렇다면 실제로 왜 Docker를 사용할까요?

  • 환경 일관성 — 개발, 테스트, 프로덕션 환경이 완전히 동일하다.

  • 빠른 배포 — 이미지를 빌드해두면 어디서든 몇 초 만에 실행할 수 있다.

  • 리소스 효율 — VM 대비 훨씬 가볍고, 하나의 서버에 더 많은 서비스를 올릴 수 있다.

  • 격리성 — 각 컨테이너는 독립된 환경에서 실행되어 서로 영향을 주지 않는다.

  • 버전 관리 — 이미지에 태그를 달아 쉽게 롤백하거나 특정 버전을 재현할 수 있다.

실무에서는 특히, “배포 안정성 + 환경 통일” 때문에 거의 필수적으로 사용됩니다.

3) Docker 핵심 개념 3가지 - 이미지, 컨테이너, 레지스트리

아래는 Docker를 이해할 때 가장 중요한 3가지 개념입니다.

(1) 이미지 (Image)

: docker 이미지는 컨테이너를 만들기 위한 읽기 전용 템플릿이다.

  • 애플리케이션 코드, 런타임, 라이브러리, 환경 변수, 설정 파일 등 실행에 필요한 모든 것을 포함한다.

  • 비유하면, 이미지는 붕어빵 틀과 같고, 틀 하나로 여러 개의 붕어빵(컨테이너)를 만들 수 있다.

(2) 컨테이너 (Container)

: 컨테이너는 이미지를 실행한 인스턴스이다.

  • 이미지가 설계도라면, 컨테이너는 그 설계도로 지은 실제 건물이다.

  • 각 컨테이너는 독립된 파일시스템, 네트워크, 프로세스를 가지며 서로 격리되어 실행된다.

(3) 레지스트리 (Registry)

: Docker 이미지를 저장하고 배포하는 저장소

  • 가장 대표적인 public registry가 Docker Hub(hub.docker.com)이며, nginx, postgres, node 등 공식 이미지를 무료로 다운로드할 수 있다.

  • 기업 환경에서는 private registry(AWS ECR, Google GCR, Github Container Registry 등)를 사용하여 내부 이미지를 안전하게 관리한다.

| 도커 기본 명령어

이제 실제로 가장 많이 사용하는 명령어들을 살펴보겠습니다.

1) 이미지 관련

code
# 이미지 관련 명령어
docker pull nginx              # 이미지 다운로드
docker images                  # 이미지 목록 확인
docker rmi nginx               # 이미지 삭제
docker image prune             # 사용하지 않는 이미지 정리
  • 이미지는 “설계도”이기 때문에, 먼저 다운로드 받아야 컨테이너를 실행할 수 있습니다.

2) 컨테이너 실행 및 관리

code
# 컨테이너 실행
docker run -d --name my-nginx -p 8080:80 nginx
# -d: 백그라운드 실행
# --name: 컨테이너 이름 지정
# -p 8080:80: 호스트 8080 포트를 컨테이너 80 포트에 연결

# 컨테이너 관리
docker ps                      # 실행 중인 컨테이너 목록
docker ps -a                   # 모든 컨테이너 목록 (중지 포함)
docker stop my-nginx           # 컨테이너 중지
docker start my-nginx          # 컨테이너 시작
docker restart my-nginx        # 컨테이너 재시작
docker rm my-nginx             # 컨테이너 삭제
  • 위 예제에서 docker run -d --name my-nginx -p 8080:80 nginx를 실행하면, Nginx 웹 서버가 백그라운드에서 실행되고, 브라우저에서 http://localhost:8080에 접속하면 Nginx 기본 페이지를 확인할 수 있습니다.

  • docker run은 pull + create + start를 한 번에 실행하며, 이미지가 로컬에 없으면 자동으로 Docker Hub에서 다운로드합니다.

3) 디버깅 명령

code
# 컨테이너 내부 접속
docker exec -it my-nginx bash
# -i: 표준 입력 유지
# -t: 터미널 할당

# 로그 확인
docker logs my-nginx           # 전체 로그
docker logs -f my-nginx        # 실시간 로그 (tail -f와 유사)
  • docker exec -it는 실행 중인 컨테이너 안에 들어가서 직접 명령어를 실행할 수 있는 매우 유용한 명령어이며, 문제 해결이나 설정 확인 시 자주 사용합니다.

| Dockerfile

: Docker 이미지를 만들기 위한 설정 파일입니다. 어떤 베이스 이미지를 사용하고, 어떤 파일을 복사하고, 어떤 명령어를 실행할지를 순서대로 기술합니다.

1) 레이어 구조

: 각 명령어가 하나의 레이어를 생성합니다. 레이어 구조 덕분에 변경되지 않은 단계는 캐시를 활용하여 빌드 속도를 크게 줄일 수 있습니다.

code
# Layer 1 : 베이스 이미지
FROM node:20-alpine

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

# Layer 3 : 의존성 파일 먼저 복사 (캐시 활용)
COPY package*.json ./

# Layer 4 : 패키지 설치
RUN npm install

# Layer 5 : 전체 코드 복사
COPY . .

# Layer 6 : 컨테이너 실행 시 실행할 명령
CMD ["node", "server.js"]

2) 주요 Dockerfile 명령어

명령어

설명

예시

FROM

베이스 이미지 지정

FROM node:20-alpine

WORKDIR

작업 디렉토리 설정

WORKDIR /app

COPY

파일 복사

COPY . .

RUN

빌드 시 명령 실행

RUN npm install

EXPOSE

포트 문서화

EXPOSE 3000

CMD

컨테이너 실행 시 기본 명령

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

ENV

환경 변수 설정

ENV NODE_ENV=production

3) 실전 Dockerfile 예제 (Node.js)

code
# Node.js 애플리케이션 Dockerfile 예제
FROM node:20-alpine

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

# 의존성 파일 먼저 복사 (캐시 활용)
COPY package*.json ./
RUN npm install --production

# 소스 코드 복사
COPY . .

# 포트 노출
EXPOSE 3000

# 실행 명령
CMD ["node", "server.js"]
  • package*.json을 먼저 복사하고 npm install을 실행하는 이유: Docker의 레이어 캐시를 활용하기 위함입니다.

  • 소스 코드만 변경되면 npm install 레이어는 캐시에서 재사용됩니다.

4) 빌드 및 실행

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

# 빌드된 이미지로 컨테이너 실행
docker run -d -p 3000:3000 --name my-app my-node-app

# 브라우저에서 http://localhost:3000 접속하여 확인
  • docker build -t my-node-app .에서 마지막 점(.)은 현재 디렉토리를 빌드 컨텍스트로 사용하겠다는 의미입니다.

  • Dockerfile이 현재 디렉토리에 있어야 합니다.

| 결론

Docker는 단순한 도구가 아니라, 개발 → 테스트 → 배포까지의 전체 흐름을 안정적으로 만들어주는 핵심 기술입니다.

처음에는 개념이 많아 보이지만, 이미지 → 컨테이너 → 실행 흐름만 이해하면 빠르게 익숙해질 수 있습니다.

다음에는 Docker Compose에 대해서 다뤄보겠습니다.