| IT

Docker 완전 가이드

Docker란?

🐳 Docker 컨테이너는 앱과 실행 환경을 통째로 패키징합니다.

📦 이미지는 읽기 전용 레이어의 스택입니다. 각 Dockerfile 명령이 하나의 레이어를 만들고, 같은 레이어는 여러 이미지에서 재사용됩니다.

▶️ 컨테이너를 실행하면 맨 위에 쓰기 가능 레이어가 추가됩니다. 원본 이미지는 변경되지 않아요!

아래로 스크롤하여 더 알아보기

Docker & Image: "내 컴퓨터에선 되는데 왜 네 컴퓨터에선 안 돼?"

1. 문제점: 환경의 차이

개발자가 프로그램을 만들 때, 내 컴퓨터에는 A, B, C 프로그램이 깔려있어서 잘 돌아갔습니다. 하지만 친구 컴퓨터에는 B가 없고, C 버전이 달라서 에러가 납니다. "이 프로그램 돌리려면 뭐뭐 깔아야 해?" → 설명하기도, 맞추기도 너무 힘듭니다.

2. 해결책: 컨테이너 (Container) - "도시락"

그래서 프로그램을 실행에 필요한 모든 것(코드, 라이브러리, 설정)과 함께 하나의 상자(도시락)에 담아서 포장해버립니다. 이 상자를 컨테이너라고 부릅니다. 이제 친구에게 "이 상자만 받아서 열어봐"라고 하면, 친구 컴퓨터에 뭐가 깔려있든 상관없이 똑같이 돌아갑니다.

가상머신(VM)과 차이점

3. 이미지 (Image) - "도시락 레시피 & 레이어"

컨테이너를 찍어내는 원본 틀(설계도)이미지라고 합니다. 이미지는 효율성을 위해 레이어(Layer)라는 겹겹이 쌓인 구조로 되어 있습니다.

레이어 구조 (시각화 목표)

마치 투명 필름(OHP 필름)을 여러 장 겹친 것과 같습니다.

  1. Base Layer: 윈도우/리눅스 같은 기초 바닥.
  2. Add Python: 그 위에 파이썬을 설치한 투명 필름을 얹음.
  3. Add Code: 그 위에 내 코드를 쓴 투명 필름을 얹음.

= 최종 결과물: 위에서 내려다보면 하나의 합쳐진 그림처럼 보임!

왜 이렇게 할까? 파이썬까지 똑같고 코드만 다른 프로그램이 있다면, 1, 2번 필름은 재사용하고 3번 필름만 바꾸면 되니까요! (용량 절약)

4. Dockerfile: 레시피 작성법

Dockerfile은 이미지를 만드는 레시피(설계도)입니다. 텍스트 파일로, 어떤 순서로 필름을 쌓을지 적어놓습니다.

기본 명령어

FROM: 기초 바닥 깔기

FROM ubuntu:20.04

RUN: 명령어 실행 (설치, 설정)

RUN apt-get update && apt-get install -y python3

COPY: 파일 넣기

COPY . /app

CMD: 실행 명령어 (컨테이너가 시작될 때)

CMD ["python3", "app.py"]

전체 예시

# 1. 우분투 깔기
FROM ubuntu:20.04

# 2. 파이썬 설치
RUN apt-get update && apt-get install -y python3

# 3. 내 코드 복사
COPY . /app

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

# 5. 실행 명령어
CMD ["python3", "app.py"]

5. Docker Compose: 여러 컨테이너 한번에 관리하기

문제점: 웹 서버 + 데이터베이스 + 캐시 서버... 여러 컨테이너를 하나씩 실행하기 귀찮아요!

Docker Compose오케스트라 지휘자처럼 여러 컨테이너를 한 번에 관리합니다.

비유: 오케스트라

docker-compose.yml 예시

version: '3'
services:
  web:
    image: nginx
    ports:
      - "80:80"

  database:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret

  cache:
    image: redis

실행 방법

# 모든 컨테이너 한 번에 시작
docker-compose up

# 모든 컨테이너 한 번에 종료
docker-compose down

6. 볼륨(Volume): 데이터를 안전하게 보관하기

문제점: 컨테이너를 삭제하면, 안에 있던 데이터도 같이 사라집니다!

볼륨은 데이터를 컨테이너 밖에 저장하는 USB처럼 동작합니다.

비유: USB 메모리

사용 방법

# 볼륨 생성
docker volume create my_data

# 컨테이너 실행 시 볼륨 연결
docker run -v my_data:/data my_image

활용 사례


7. Docker 네트워크: 컨테이너끼리 대화하기

기본적으로 각 컨테이너는 격리되어 있습니다. 하지만 웹 서버가 데이터베이스에 접속하려면 연결이 필요합니다.

비유: 아파트 단지

네트워크 생성 및 연결

# 네트워크 생성
docker network create my_network

# 컨테이너를 네트워크에 연결
docker run --network my_network --name web nginx
docker run --network my_network --name db mysql

결과: web 컨테이너에서 db라는 이름으로 데이터베이스에 접속 가능!

Docker Compose에서 자동 네트워크

version: '3'
services:
  web:
    image: nginx
  db:
    image: mysql
# → 자동으로 같은 네트워크에 연결됨!

8. Nginx: Docker에서 가장 많이 쓰는 컨테이너

위 시뮬레이션의 Compose 탭에서 보듯이, 실무에서는 Nginx 컨테이너가 맨 앞에서 모든 요청을 받아 처리합니다. 왜 굳이 Nginx를 앞에 두는 걸까요?

비유: 건물 안내 데스크

8-1. 리버스 프록시 (Reverse Proxy)

외부 요청을 받아서 내부 컨테이너로 전달하는 역할입니다.

# nginx.conf 예시
server {
    listen 80;

    # "/" 요청 → 프론트엔드 컨테이너로 전달
    location / {
        proxy_pass http://frontend:3000;
    }

    # "/api" 요청 → 백엔드 컨테이너로 전달
    location /api {
        proxy_pass http://backend:8080;
    }
}

요청 흐름:

  1. 외부 사용자 → https://mysite.com/api/users 요청
  2. Nginx가 /api 경로를 확인 → 백엔드 컨테이너로 전달
  3. 백엔드가 처리 → Nginx가 응답을 사용자에게 반환
왜 직접 연결하지 않나요? 프론트엔드(3000번 포트)와 백엔드(8080번 포트)를 외부에 직접 노출하면 보안 위험이 커집니다. Nginx 하나만 80/443 포트로 노출하고, 내부 서비스는 Docker 네트워크 안에서만 통신합니다.

8-2. SSL/TLS 종료 (HTTPS 처리)

HTTPS 암호화/복호화를 Nginx가 대신 처리합니다. 내부 컨테이너들은 HTTP로만 통신하면 되어 간단합니다.

server {
    listen 443 ssl;
    ssl_certificate     /etc/ssl/cert.pem;
    ssl_certificate_key /etc/ssl/key.pem;

    location / {
        proxy_pass http://frontend:3000;  # 내부는 HTTP
    }
}
구간 프로토콜 설명
외부 → Nginx HTTPS (암호화) 인터넷 구간, 도청 방지
Nginx → 내부 컨테이너 HTTP (평문) Docker 네트워크 내부, 안전한 구간
비유: 건물 입구에서 보안 검색(SSL)을 통과하면, 건물 내부에서는 자유롭게 이동할 수 있는 것과 같습니다. 각 사무실마다 보안 검색을 반복할 필요가 없습니다.

8-3. 접근 제어 (Access Control)

Nginx에서 특정 IP만 허용하거나, 요청 속도를 제한할 수 있습니다.

# IP 기반 접근 제어
location /admin {
    allow 192.168.1.0/24;   # 내부 네트워크만 허용
    deny all;                # 나머지 차단
    proxy_pass http://backend:8080;
}

# 요청 속도 제한 (Rate Limiting)
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

location /api {
    limit_req zone=api burst=20;  # 초당 10회, 순간 20회까지 허용
    proxy_pass http://backend:8080;
}
기능 설정 용도
IP 허용/차단 allow / deny 관리자 페이지를 내부망에서만 접근
Rate Limiting limit_req_zone API 남용/DDoS 방어
CORS 헤더 add_header 프론트엔드 도메인에서만 API 호출 허용
파일 크기 제한 client_max_body_size 업로드 용량 초과 차단

8-4. Docker Compose에서 Nginx 설정

실제 프로젝트에서는 이렇게 구성합니다:

version: '3'
services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - ./ssl:/etc/ssl
    depends_on:
      - frontend
      - backend

  frontend:
    build: ./frontend
    # 포트를 외부에 노출하지 않음 (Nginx만 접근)

  backend:
    build: ./backend
    # 포트를 외부에 노출하지 않음 (Nginx만 접근)
핵심 포인트: frontendbackend에는 ports를 설정하지 않습니다. Docker 네트워크 내부에서 Nginx만 접근하고, 외부에서는 Nginx의 80/443 포트만 열려 있습니다. 이것이 리버스 프록시의 보안 이점입니다.

9. 자주 쓰는 명령어 정리

명령어 설명 비유
docker build -t my_image . Dockerfile로 이미지 만들기 레시피대로 도시락 제작
docker run my_image 이미지로 컨테이너 실행 도시락 뚜껑 열기
docker ps 실행 중인 컨테이너 목록 오픈된 도시락 확인
docker stop <ID> 컨테이너 중지 도시락 뚜껑 닫기
docker rm <ID> 컨테이너 삭제 도시락 버리기
docker images 이미지 목록 보기 레시피북 펼치기
docker rmi <이미지> 이미지 삭제 레시피 찢어버리기
docker exec -it <ID> bash 실행 중인 컨테이너 내부 접속 도시락 안 들여다보기
docker logs <ID> 컨테이너 로그 확인 도시락에서 나는 냄새 맡기
docker pull <이미지> Docker Hub에서 이미지 다운로드 레시피 사이트에서 다운
docker-compose up 여러 컨테이너 한 번에 시작 오케스트라 시작
docker-compose down 여러 컨테이너 한 번에 종료 오케스트라 종료

유용한 옵션


정리

개념 핵심 비유
Dockerfile 이미지 만드는 레시피 요리 레시피
Docker Compose 여러 컨테이너 관리 오케스트라 지휘자
Volume 데이터 영구 보관 USB 메모리
Network 컨테이너 간 통신 아파트 복도
Nginx 리버스 프록시, SSL, 접근 제어 건물 안내 데스크

핵심 워크플로우:

  1. Dockerfile 작성 (레시피)
  2. docker build (이미지 제작)
  3. docker-compose.yml 작성 (여러 서비스 설정)
  4. docker-compose up (한 번에 실행!)
  5. Volume으로 데이터 보호, Network로 연결!