콘텐츠로 이동

Docker 완전정복 가이드 🐳


📚 목차

  1. Docker가 뭐야?
  2. Docker 설치하기
  3. Docker 시작하고 끄기
  4. 기본 사용법 배우기
  5. 실습으로 배우는 명령어
  6. 현업에서 이렇게 써요

1. Docker가 뭐야? 🤔

쉽게 말하면 뭘까?

Docker프로그램을 상자(컨테이너)에 넣어서 어디든 옮겨 실행할 수 있게 해주는 도구입니다.

graph TD
    A[내 컴퓨터에서 만든 프로그램] --> B[Docker 컨테이너에 포장]
    B --> C[다른 컴퓨터]
    B --> D[서버]
    B --> E[클라우드]

    F["내 컴퓨터에서는 되는데...😭<br/>다른 곳에서는 안돼"] --> G[Docker로 해결!✨]

    style A fill:#ffeb3b
    style B fill:#4caf50
    style C fill:#2196f3
    style D fill:#2196f3
    style E fill:#2196f3
    style G fill:#4caf50

붕어빵으로 이해하기

graph LR
    subgraph "전통적인 방식 (문제많음)"
        A1[프로그램 코드] --> A2[각자 다른 컴퓨터에 설치]
        A2 --> A3[❌ 환경 차이로 오류 발생]
    end

    subgraph "Docker 방식 (문제해결)"
        B1[이미지<br/>🍯 붕어빵 틀<br/>프로그램 설계도] --> B2[컨테이너<br/>🧁 붕어빵<br/>실행되는 프로그램]
        B1 --> B3[컨테이너<br/>🧁 또 다른 붕어빵]
        B1 --> B4[컨테이너<br/>🧁 세 번째 붕어빵]

        B2 --> B5[✅ 어디서든 똑같이 동작]
        B3 --> B5
        B4 --> B5
    end

핵심 개념: - 이미지(Image): 붕어빵 틀 → 프로그램을 만들기 위한 설계도 - 컨테이너(Container): 붕어빵 → 실제로 실행되는 프로그램

Docker vs 가상머신 (쉬운 비교)

graph TB
    subgraph "가상머신 방식 🐌"
        direction TB
        VM1[💻 물리 컴퓨터]
        VM2[📦 가상화 프로그램 : VMware 등]
        VM3[🖥️ 가상 컴퓨터 1 · Windows 전체 2GB]
        VM4[🖥️ 가상 컴퓨터 2 · Linux 전체 2GB]
        VM5[📱 내 프로그램 1 · 웹사이트]
        VM6[🎮 내 프로그램 2 · 게임]

        VM1 --> VM2
        VM2 --> VM3
        VM2 --> VM4
        VM3 --> VM5
        VM4 --> VM6
    end

    subgraph "Docker 방식 🚀"
        direction TB
        D1[💻 물리 컴퓨터]
        D2[🖥️ 운영체제 : Windows/Mac/Linux]
        D3[🐳 Docker : 컨테이너 관리자]
        D4[📦 컨테이너 1 · 웹사이트만 50MB]
        D5[📦 컨테이너 2 · 게임만 100MB]

        D1 --> D2
        D2 --> D3
        D3 --> D4
        D3 --> D5
    end
구분 Docker 가상머신
크기 가벼움 (MB 단위) 무거움 (GB 단위)
속도 빠름 (몇 초) 느림 (몇 분)
비유 도시락 🍱 집 통째로 이사 🏠

Docker가 왜 좋을까?

mindmap
  root((Docker 장점))
    개발자에게 좋은점
      팀 전체가 같은 환경
      새로운 버전 쉽게 테스트
      배포할 때 실수 줄어듦
    회사에게 좋은점
      서버 비용 절약
      관리하기 쉬워짐
      서비스 확장 편리
    사용자에게 좋은점
      서비스 더 안정적
      새 기능 빨리 만나볼 수 있음

2. Docker 설치하기 ⚙️

Docker는 어떻게 생겼을까?

graph TB
    subgraph "Docker의 구조"
        A[👤 사용자<br/>개발자]
        B[💻 Docker 명령어<br/>docker run, docker stop 등]
        C[🔧 Docker 엔진<br/>실제 일하는 프로그램]
        D[📦 컨테이너들<br/>실행되는 프로그램들]
    end

    A --> |명령어 입력| B
    B --> |명령 전달| C
    C --> |관리| D

    style A fill:#e3f2fd
    style B fill:#fff3e0
    style C fill:#e8f5e8
    style D fill:#f3e5f5

컴퓨터별 설치 방법

Windows에서 설치하기 🪟

# 내 컴퓨터가 Docker를 쓸 수 있는지 확인하기

# 1. Windows 버전 확인 (설정 > 시스템 > 정보)
# - Windows 10 Pro/Enterprise/Education (Build 16299 이상)
# - Windows 10 Home (Build 2004 이상, WSL2 필요)
# - Windows 11 (모든 버전 OK)

# 2. 컴퓨터 성능 확인
# - 64비트 컴퓨터인지 확인
# - 메모리 4GB 이상
# - CPU가 가상화를 지원하는지 확인

# 3. Docker Desktop 다운로드 및 설치
# https://www.docker.com/products/docker-desktop
# 다운로드 → 설치 → 재부팅 → 완료!

Mac에서 설치하기 🍎

# Mac 확인사항

# 1. macOS 버전 확인 (왼쪽 위 🍎 > 이 Mac에 관하여)
# - macOS 10.13 (High Sierra) 이상
# - 2010년 이후 출시된 Mac

# 2. 메모리 확인
# - 4GB 이상 필요

# 3. Docker Desktop 설치
# https://www.docker.com/products/docker-desktop
# Mac용 다운로드 → 설치 → 완료!

Linux에서 설치하기 🐧

# Ubuntu에서 Docker 설치하기 (가장 많이 사용)

# 1. 시스템 업데이트
sudo apt update
# 설명: 우분투의 패키지 목록을 최신으로 업데이트

# 2. 필요한 도구들 설치
sudo apt install curl
# 설명: 인터넷에서 파일을 다운로드하는 도구

# 3. Docker 설치 스크립트 실행
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# 설명: Docker 공식 설치 스크립트를 다운로드하고 실행

# 4. 사용자를 docker 그룹에 추가 (sudo 없이 사용하기 위해)
sudo usermod -aG docker $USER
# 설명: 현재 사용자($USER)를 docker 그룹에 추가
# 로그아웃 후 다시 로그인해야 적용됨

# 5. Docker 버전 확인
docker --version
# 출력 예시: Docker version 24.0.6, build ed223bc

3. Docker 시작하고 끄기 🚀

Windows에서 Docker 조작하기 🪟

# === 마우스로 하기 (GUI) ===

# Docker 시작하기:
# 바탕화면에서 "Docker Desktop" 아이콘 더블클릭
# 또는 시작메뉴에서 "Docker Desktop" 검색해서 실행

# Docker 끄기:
# 화면 오른쪽 아래 작업표시줄에서 고래🐋 모양 아이콘 찾기
# 고래 아이콘 오른쪽 클릭 → "Quit Docker Desktop" 선택

# === 명령어로 하기 (CLI) ===
# Win + R 키 → cmd 입력 → 엔터

# Docker가 실행중인지 확인
docker --version
# 정상 출력: Docker version 24.0.6, build ed223bc
# 오류 발생: Docker Desktop이 실행되지 않음

# Docker 상태 확인
docker info
# Docker가 실행중이면 상세 정보가 나옴
# 실행중이 아니면 오류 메시지

# 간단한 테스트
docker run hello-world
# Docker가 정상이면 환영 메시지가 나옴

Mac에서 Docker 조작하기 🍎

# === 마우스로 하기 (GUI) ===

# Docker 시작하기:
# Finder → 응용 프로그램 → Docker Desktop 더블클릭
# 또는 Spotlight(Cmd + Space) → "Docker" 검색 → 실행

# Docker 끄기:
# 화면 위쪽 메뉴바에서 고래🐋 아이콘 찾기
# 고래 아이콘 클릭 → "Quit Docker Desktop" 선택

# === 터미널로 하기 (CLI) ===
# Cmd + Space → "Terminal" 검색 → 실행

# Docker 버전 확인
docker --version

# Docker 상태 확인  
docker info

# Docker Desktop이 실행중인지 확인
ps aux | grep Docker
# Docker 관련 프로세스가 보이면 실행중

Linux에서 Docker 조작하기 🐧

# === Docker 서비스 시작/중지 ===

# Docker 시작하기
sudo systemctl start docker
# 설명: Docker 데몬(백그라운드 프로그램)을 시작

# Docker 상태 확인
sudo systemctl status docker
# 출력에서 "active (running)" 이면 실행중
# "inactive (dead)" 이면 중지상태

# Docker 중지하기
sudo systemctl stop docker
# 설명: Docker 데몬을 안전하게 중지

# Docker 재시작하기
sudo systemctl restart docker
# 설명: Docker를 완전히 중지했다가 다시 시작

# === 자동 실행 설정 ===

# 컴퓨터 켜질 때 Docker 자동 시작
sudo systemctl enable docker
# 설명: 부팅할 때마다 Docker가 자동으로 시작됨

# 자동 시작 해제
sudo systemctl disable docker
# 설명: 부팅 때 Docker가 자동 시작되지 않음

# === sudo 없이 사용하기 (권장) ===

# 현재 사용자를 docker 그룹에 추가
sudo usermod -aG docker $USER
# 설명: $USER는 현재 로그인한 사용자 이름

# 그룹 변경사항 즉시 적용 (임시)
newgrp docker

# 또는 완전한 적용을 위해 로그아웃 후 다시 로그인

# 권한이 제대로 설정됐는지 확인
docker run hello-world
# sudo 없이 실행되면 성공!

4. 기본 사용법 배우기 📝

Docker 명령어 구조 이해하기

graph LR
    A[docker] --> B[무엇을<br/>container<br/>image<br/>volume<br/>network]
    B --> C[어떻게<br/>run<br/>stop<br/>start<br/>rm]
    C --> D[대상<br/>nginx<br/>ubuntu<br/>mysql<br/>my-app]

    E[옵션들<br/>-d -p --name -v] --> A
    F[추가 명령어<br/>bash<br/>python<br/>ls] --> D

    style A fill:#4caf50
    style B fill:#2196f3  
    style C fill:#ff9800
    style D fill:#9c27b0
    style E fill:#f44336
    style F fill:#607d8b

실제 예시로 이해하기:

docker container run --name my-web -d -p 8080:80 nginx
#  ↑       ↑      ↑      ↑       ↑  ↑     ↑     ↑
#  명령어   무엇을   어떻게   이름지정  백그라운드 포트연결 대상
#         (컨테이너)(실행)   (my-web)  실행     설정   (웹서버)

# 풀어서 설명하면:
# "nginx라는 웹서버 이미지로 컨테이너를 만들어서 실행하는데,
#  이름을 my-web으로 짓고, 백그라운드에서 돌리면서,
#  내 컴퓨터의 8080포트와 컨테이너의 80포트를 연결해줘"

자주 쓰는 옵션들 완전 정리

옵션 의미 예시 언제 써요?
-d 뒤에서 실행 docker run -d nginx 웹서버처럼 계속 돌려야 할 때
--name 이름 짓기 --name my-web 나중에 찾기 쉽게 하려고
-p 포트 연결 -p 8080:80 웹사이트에 접속하려고
-v 폴더 공유 -v /내폴더:/컨테이너폴더 파일을 주고받으려고
-e 환경변수 -e PASSWORD=123 프로그램 설정 바꾸려고
-it 터미널 접속 -it ubuntu bash 컨테이너 안에서 직접 작업하려고
--rm 끝나면 삭제 --rm ubuntu 일회용으로 쓸 때

Docker 명령어 카테고리

mindmap
  root((Docker 명령어))
    컨테이너 다루기
      run: 만들고 실행
      start: 다시 시작
      stop: 멈추기
      rm: 삭제하기
      ps: 목록 보기
      exec: 안에서 명령 실행
      logs: 로그 보기
    이미지 다루기
      pull: 다운로드
      build: 만들기
      push: 업로드
      ls: 목록 보기
      rm: 삭제하기
      tag: 태그 달기
    정리하기
      system prune: 안쓰는 것들 삭제
      container prune: 컨테이너 정리
      image prune: 이미지 정리
    정보 보기
      version: 버전 확인
      info: 상세 정보
      inspect: 자세히 보기

5. 실습으로 배우는 명령어 💻

첫 번째 실습: Hello World 🌟

# === Docker 첫 실행 ===

# 1. Docker가 제대로 설치됐는지 확인
docker --version
# 출력 예시: Docker version 24.0.6, build ed223bc
# 설명: 버전이 나오면 정상 설치됨

# 2. 첫 번째 컨테이너 실행하기  
docker run hello-world
# 설명: 
# - Docker Hub에서 hello-world 이미지를 자동으로 다운로드
# - 컨테이너를 만들어서 실행
# - 환영 메시지를 출력하고 자동으로 종료

# 출력 결과:
# Hello from Docker!
# This message shows that your installation appears to be working correctly.

실행 과정 시각화:

sequenceDiagram
    participant 사용자
    participant Docker엔진
    participant DockerHub
    participant 컨테이너

    사용자->>Docker엔진: docker run hello-world
    Docker엔진->>Docker엔진: 로컬에 hello-world 이미지 있나?
    Docker엔진->>DockerHub: 없으니까 다운로드 해줘
    DockerHub->>Docker엔진: hello-world 이미지 전송
    Docker엔진->>컨테이너: 이미지로 컨테이너 생성 및 실행
    컨테이너->>사용자: Hello from Docker! 메시지 출력
    컨테이너->>Docker엔진: 작업 완료, 자동 종료

두 번째 실습: 웹서버 만들기 🌐

# === Apache 웹서버 컨테이너 만들기 ===

# 1. Apache 웹서버 컨테이너 생성 및 실행
docker run --name my-apache -d -p 8080:80 httpd
# 상세 설명:
# --name my-apache: 컨테이너 이름을 'my-apache'로 지정
# -d: 백그라운드에서 실행 (터미널이 블로킹되지 않음)
# -p 8080:80: 내 컴퓨터의 8080포트를 컨테이너의 80포트와 연결
# httpd: Apache HTTP Server 이미지 사용

# 2. 컨테이너가 잘 실행되는지 확인
docker ps
# 출력 예시:
# CONTAINER ID   IMAGE   COMMAND              CREATED         STATUS         PORTS                  NAMES
# a1b2c3d4e5f6   httpd   "httpd-foreground"   30 seconds ago  Up 30 seconds  0.0.0.0:8080->80/tcp   my-apache

# 3. 웹브라우저에서 확인하기
# 주소창에 입력: http://localhost:8080
# "It works!" 메시지가 나오면 성공! 🎉

# 4. 컨테이너 로그 확인 (웹서버 접속 기록 보기)
docker logs my-apache
# 설명: 웹서버의 접속 로그와 오류 로그를 볼 수 있음

# 5. 컨테이너 안에서 직접 작업하기
docker exec -it my-apache bash
# 설명: 실행 중인 컨테이너 안으로 들어가서 명령어 실행 가능
# 나가려면: exit 입력

# 6. 컨테이너 정리하기
docker stop my-apache     # 컨테이너 중지 (데이터는 보존됨)
docker start my-apache    # 다시 시작하기
docker rm my-apache       # 완전히 삭제 (먼저 stop 해야 함)

세 번째 실습: 리눅스 컨테이너 접속하기 🐧

# === Ubuntu Linux 컨테이너로 놀아보기 ===

# 1. Ubuntu 컨테이너를 터미널 모드로 실행
docker run -it --name my-ubuntu ubuntu bash
# 상세 설명:
# -i: 키보드 입력을 컨테이너로 전달
# -t: 터미널 환경 제공 (색깔, 특수키 등)
# --name my-ubuntu: 컨테이너 이름 지정
# ubuntu: Ubuntu Linux 이미지 사용
# bash: 컨테이너 시작할 때 bash 쉘 실행

# 2. 컨테이너 안에서 Linux 명령어 사용해보기
# (프롬프트가 root@컨테이너ID:/# 로 바뀜)

ls                        # 폴더 목록 보기
pwd                       # 현재 위치 확인 (/가 나올 거임)
whoami                    # 현재 사용자 확인 (root)
cat /etc/os-release      # Ubuntu 버전 정보 보기

# 3. 패키지 설치해보기
apt update               # 패키지 목록 업데이트
apt install -y curl     # curl 프로그램 설치 (-y는 모든 질문에 yes)
curl --version          # curl이 잘 설치됐는지 확인

# 4. 컨테이너에서 나가기
exit
# 설명: 컨테이너를 빠져나오면서 컨테이너도 자동으로 종료됨

# 5. 새 터미널에서 컨테이너 상태 확인
docker ps -a
# STATUS가 "Exited (0)"이면 정상 종료됨

네 번째 실습: 이미지 다운로드와 관리 📦

# === 이미지 관리 실습 ===

# 1. 이미지 검색하기 (Docker Hub에서)
docker search python
# 설명: Docker Hub에서 'python'이 포함된 이미지들을 검색
# OFFICIAL 컬럼이 OK인 것이 공식 이미지

# 2. 특정 버전의 이미지 다운로드
docker pull python:3.11
# 설명: Python 3.11 버전 이미지를 미리 다운로드
# 태그(:3.11)를 지정하지 않으면 자동으로 :latest가 붙음

# 3. 다운로드된 이미지 목록 확인
docker images
# 또는
docker image ls
# 출력 예시:
# REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
# python       3.11      a1b2c3d4e5f6   2 weeks ago    998MB
# ubuntu       latest    b2c3d4e5f6a7   3 weeks ago    77.8MB

# 4. Python 컨테이너로 간단한 프로그래밍
docker run -it --rm python:3.11
# 설명: --rm 옵션으로 종료할 때 자동 삭제
# Python 인터프리터가 실행됨

# Python에서 실행해보기:
print("Hello, Docker!")
2 + 3
exit()  # Python에서 나가기 (컨테이너도 자동 종료)

# 5. 안 쓰는 이미지 삭제하기
docker image rm python:3.11
# 또는 짧게
docker rmi python:3.11
# 주의: 해당 이미지를 사용하는 컨테이너가 있으면 삭제 안됨

다섯 번째 실습: 나만의 이미지 만들기 🛠️

# === 커스텀 이미지 만들기 ===

# 1. Ubuntu 컨테이너에서 작업하기
docker run -it --name work-ubuntu ubuntu bash

# 컨테이너 안에서:
apt update                    # 패키지 목록 업데이트
apt install -y curl vim      # 유용한 도구들 설치
echo "Hello Docker!" > /hello.txt    # 파일 생성
exit                         # 컨테이너 종료

# 2. 수정된 컨테이너를 새로운 이미지로 저장
docker commit work-ubuntu my-custom-ubuntu:v1.0
# 설명: work-ubuntu 컨테이너의 현재 상태를 my-custom-ubuntu:v1.0 이미지로 저장

# 3. 새로 만든 이미지 확인
docker images
# my-custom-ubuntu 이미지가 목록에 나타남

# 4. 새 이미지로 컨테이너 실행해보기
docker run -it --rm my-custom-ubuntu:v1.0
# curl, vim이 이미 설치되어 있고, /hello.txt 파일도 존재함!

# 5. 정리하기
docker rm work-ubuntu                    # 작업용 컨테이너 삭제
docker rmi my-custom-ubuntu:v1.0        # 커스텀 이미지 삭제

실습 정리 및 유용한 명령어들 🧹

# === Docker 환경 정리하기 ===

# 1. 실행중인 모든 컨테이너 확인
docker ps

# 2. 모든 컨테이너 확인 (정지된 것 포함)
docker ps -a

# 3. 모든 컨테이너 한번에 정지
docker stop $(docker ps -q)
# 설명: $(docker ps -q)는 실행중인 컨테이너 ID들을 가져옴

# 4. 모든 정지된 컨테이너 삭제
docker container prune
# 주의: 복구 불가능! 정말 필요없는지 확인 후 실행

# 5. 안 쓰는 이미지 정리
docker image prune
# dangling 이미지들(태그가 없는 이미지)만 삭제

# 6. 모든 안쓰는 것들 한번에 정리 (주의!)
docker system prune
# 컨테이너, 네트워크, 이미지, 캐시 등 정리

# 7. 공간 사용량 확인
docker system df
# Docker가 사용하는 디스크 공간 확인

6. 현업에서 이렇게 써요 💼

실제 개발팀에서 Docker 사용 패턴 🏢

1. 개발환경 통일하기

# === 팀 전체가 똑같은 개발환경 만들기 ===

# 문제상황: 
# - A개발자: "내 컴퓨터에서는 되는데?"
# - B개발자: "Node.js 버전이 달라서 안돼요"
# - C개발자: "Python 라이브러리 충돌나요"

# 해결방법: Docker로 표준 개발환경 제공

# Node.js 개발환경 컨테이너
docker run -it --name dev-node \
  -v $(pwd):/workspace \
  -p 3000:3000 \
  node:18 bash
# 설명:
# -v $(pwd):/workspace: 현재 폴더를 컨테이너의 /workspace와 연결
# -p 3000:3000: 개발서버 포트 연결
# 모든 팀원이 동일한 Node.js 18 환경에서 작업

# Python 데이터 분석 환경
docker run -it --name dev-python \
  -v $(pwd):/workspace \
  -p 8888:8888 \
  jupyter/scipy-notebook
# 설명: Jupyter Notebook + 과학계산 라이브러리가 미리 설치된 환경

2. 다양한 데이터베이스 쉽게 테스트하기

# === 여러 데이터베이스를 동시에 띄우기 ===

# MySQL 데이터베이스 실행
docker run --name test-mysql \
  -e MYSQL_ROOT_PASSWORD=password123 \
  -e MYSQL_DATABASE=testdb \
  -p 3306:3306 \
  -d mysql:8.0
# 설명: 
# -e MYSQL_ROOT_PASSWORD: 관리자 비밀번호 설정
# -e MYSQL_DATABASE: 기본 데이터베이스 이름
# MySQL 서버가 백그라운드에서 실행됨

# PostgreSQL 데이터베이스 실행 (다른 포트로)
docker run --name test-postgres \
  -e POSTGRES_PASSWORD=password123 \
  -e POSTGRES_DB=testdb \
  -p 5432:5432 \
  -d postgres:15
# 설명: MySQL과 PostgreSQL을 동시에 테스트 가능

# Redis 캐시 서버 실행
docker run --name test-redis \
  -p 6379:6379 \
  -d redis:7
# 설명: 메모리 기반 캐시 서버

# 데이터베이스 접속 테스트
docker exec -it test-mysql mysql -uroot -ppassword123 testdb
# MySQL 컨테이너 안에서 직접 SQL 실행 가능

3. 웹 개발 스택 구성하기

# === 프론트엔드 + 백엔드 + 데이터베이스 한번에 ===

# 1. React 개발서버 (프론트엔드)
docker run -d --name frontend \
  -v $(pwd)/frontend:/app \
  -w /app \
  -p 3000:3000 \
  node:18 \
  sh -c "npm install && npm start"
# 설명:
# -w /app: 작업 디렉토리 설정
# sh -c "commands": 여러 명령어를 순서대로 실행

# 2. Express API 서버 (백엔드)
docker run -d --name backend \
  -v $(pwd)/backend:/app \
  -w /app \
  -p 8000:8000 \
  node:18 \
  sh -c "npm install && npm start"

# 3. MongoDB 데이터베이스
docker run -d --name database \
  -p 27017:27017 \
  mongo:6
# 설명: 3개 서비스가 각각 다른 컨테이너에서 독립적으로 실행

4. CI/CD 파이프라인에서 활용

# === 자동 테스트 및 배포 ===

# 테스트용 임시 환경 만들기
docker run --rm \
  -v $(pwd):/workspace \
  -w /workspace \
  node:18 \
  npm test
# 설명:
# --rm: 테스트 끝나면 자동으로 컨테이너 삭제
# 깨끗한 환경에서 매번 테스트 실행

# 프로덕션용 이미지 빌드 (Dockerfile 사용)
docker build -t myapp:latest .
# 설명: Dockerfile을 기반으로 배포용 이미지 생성

# 여러 환경에 배포
docker run -d --name myapp-prod -p 80:3000 myapp:latest      # 프로덕션
docker run -d --name myapp-staging -p 8080:3000 myapp:latest # 스테이징
# 설명: 같은 이미지로 여러 환경에 배포 가능

Docker Compose로 여러 서비스 한번에 관리하기 🎼

실제 현업에서는 Docker Compose를 사용해서 여러 컨테이너를 한번에 관리합니다.

# docker-compose.yml 파일 예시
version: '3.8'

services:
  # 웹서버
  web:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html
    depends_on:
      - api

  # API 서버  
  api:
    image: node:18
    working_dir: /app
    volumes:
      - ./backend:/app
    command: npm start
    ports:
      - "3000:3000"
    environment:
      - DB_HOST=database
    depends_on:
      - database

  # 데이터베이스
  database:
    image: postgres:15
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_PASSWORD=secret123
    volumes:
      - db_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

volumes:
  db_data:
# === Docker Compose 사용법 ===

# 모든 서비스 한번에 시작
docker-compose up -d
# 설명: web, api, database 컨테이너가 모두 연결되어 실행됨

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

# 로그 확인
docker-compose logs web
docker-compose logs -f api  # 실시간 로그

# 모든 서비스 종료 및 삭제
docker-compose down

# 볼륨까지 완전 삭제
docker-compose down -v

현업에서 자주 사용하는 Docker 패턴 🔄

1. 마이크로서비스 아키텍처

graph TB
    subgraph "전통적인 모놀리식 방식"
        A1[거대한 하나의 애플리케이션<br/>🏢 모든 기능이 한 덩어리]
    end

    subgraph "Docker 마이크로서비스 방식"
        B1[사용자 서비스<br/>📦 컨테이너]
        B2[주문 서비스<br/>📦 컨테이너]
        B3[결제 서비스<br/>📦 컨테이너]
        B4[배송 서비스<br/>📦 컨테이너]

        B1 <--> B2
        B2 <--> B3
        B3 <--> B4
    end

    C[😰 하나가 문제면<br/>전체가 멈춤] --> A1
    D[😊 독립적 개발<br/>독립적 배포<br/>독립적 확장] --> B1
# 각 서비스별로 독립된 컨테이너 실행
docker run -d --name user-service -p 3001:3000 user-service:latest
docker run -d --name order-service -p 3002:3000 order-service:latest
docker run -d --name payment-service -p 3003:3000 payment-service:latest
# 각 팀이 독립적으로 개발하고 배포 가능

2. 개발/스테이징/프로덕션 환경 분리

# === 환경별 설정 관리 ===

# 개발환경 (로컬)
docker run -d --name myapp-dev \
  -e NODE_ENV=development \
  -e DB_HOST=localhost \
  -p 3000:3000 \
  myapp:dev

# 스테이징환경 (테스트용)  
docker run -d --name myapp-staging \
  -e NODE_ENV=staging \
  -e DB_HOST=staging-db.company.com \
  -p 8080:3000 \
  myapp:staging

# 프로덕션환경 (실제 서비스)
docker run -d --name myapp-prod \
  -e NODE_ENV=production \
  -e DB_HOST=prod-db.company.com \
  --restart=always \
  -p 80:3000 \
  myapp:latest

현업에서 사용하는 고급 Docker 기능 🚀

1. 헬스체크로 서비스 상태 모니터링

# 헬스체크가 포함된 웹서버 실행
docker run -d --name monitored-web \
  --health-cmd="curl -f http://localhost/ || exit 1" \
  --health-interval=30s \
  --health-timeout=10s \
  --health-retries=3 \
  nginx

# 헬스체크 상태 확인
docker ps
# STATUS 컬럼에 'healthy' 또는 'unhealthy' 표시됨

2. 리소스 제한으로 서버 안정성 확보

# CPU와 메모리 사용량 제한
docker run -d --name limited-app \
  --memory=512m \           # 메모리 512MB로 제한
  --cpus=0.5 \             # CPU 사용률 50%로 제한
  --restart=unless-stopped \
  myapp:latest

# 리소스 사용량 실시간 모니터링
docker stats limited-app

3. 로그 관리 및 분석

# 로그 드라이버 설정으로 로그 관리
docker run -d --name logged-app \
  --log-driver=json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  myapp:latest

# 로그 분석
docker logs --since="1h" logged-app        # 최근 1시간 로그
docker logs --tail=100 logged-app          # 마지막 100줄
docker logs -f logged-app                  # 실시간 로그

실무에서 꼭 알아야 할 Docker 보안 🔒

# === 보안 강화된 컨테이너 실행 ===

# 1. 루트 권한으로 실행하지 않기
docker run --user 1000:1000 \    # 일반 사용자로 실행
  --read-only \                   # 파일시스템 읽기전용
  --tmpfs /tmp \                  # 임시 디렉토리만 쓰기 가능
  myapp:latest

# 2. 불필요한 권한 제거
docker run --security-opt=no-new-privileges \  # 새로운 권한 획득 방지
  --cap-drop=ALL \                             # 모든 시스템 권한 제거
  --cap-add=NET_BIND_SERVICE \                 # 네트워크 바인딩만 허용
  myapp:latest

# 3. 네트워크 격리
docker network create --driver bridge isolated-net
docker run --network=isolated-net myapp:latest
# 다른 컨테이너와 네트워크 분리

Docker 트러블슈팅 🔧

# === 자주 발생하는 문제와 해결법 ===

# 1. 포트가 이미 사용중일 때
docker run -p 8080:80 nginx
# Error: Port 8080 is already in use

# 해결: 다른 포트 사용하거나 기존 프로세스 종료
sudo netstat -tlnp | grep 8080    # 포트 사용 프로세스 찾기
docker run -p 8081:80 nginx       # 다른 포트 사용

# 2. 컨테이너가 바로 종료될 때
docker run ubuntu
# 컨테이너가 바로 Exited 상태가 됨

# 해결: 계속 실행될 명령어 지정
docker run -it ubuntu bash        # 터미널 모드
docker run -d ubuntu sleep infinity  # 무한 대기

# 3. 이미지 다운로드 실패
docker pull some-image:tag
# Error: pull access denied

# 해결: 올바른 이미지 이름 확인
docker search nginx               # 공식 이미지 검색
docker pull nginx:latest         # 공식 이미지 사용

# 4. 컨테이너 내부 파일 접근
docker run -d --name web nginx
# 웹서버 설정 파일을 수정하고 싶음

# 해결: 볼륨 마운트나 exec 사용
docker exec -it web bash         # 컨테이너 안으로 들어가기
docker cp ./nginx.conf web:/etc/nginx/  # 파일 복사

# 5. Docker 데몬 연결 오류
docker ps
# Error: Cannot connect to the Docker daemon

# 해결: Docker 서비스 시작
sudo systemctl start docker      # Linux
# 또는 Docker Desktop 실행        # Windows/Mac

성능 최적화 팁 ⚡

# === Docker 성능 향상 꿀팁 ===

# 1. 이미지 크기 줄이기
# 나쁜 예: 큰 베이스 이미지
FROM ubuntu:latest                # 78MB
RUN apt-get update && apt-get install -y python3

# 좋은 예: 최소한의 베이스 이미지
FROM python:3.11-alpine          # 45MB (Alpine Linux 사용)

# 2. 멀티 스테이지 빌드로 최종 이미지 크기 최소화
# Dockerfile 예시
FROM node:18 AS builder           # 빌드 전용 스테이지
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:alpine                 # 실행 전용 스테이지 (훨씬 작음)
COPY --from=builder /app/build /usr/share/nginx/html

# 3. 빌드 캐시 활용
# 자주 바뀌지 않는 파일을 먼저 복사
COPY package*.json ./             # package.json 먼저
RUN npm install                   # 의존성 설치 (캐시됨)
COPY . .                         # 소스코드는 나중에

현업 Docker 워크플로우 🔄

graph TD
    A[개발자가 코드 작성] --> B[Dockerfile 작성]
    B --> C[로컬에서 이미지 빌드<br/>docker build -t myapp:dev .]
    C --> D[로컬에서 테스트<br/>docker run myapp:dev]
    D --> E{테스트 통과?}

    E -->|No| A
    E -->|Yes| F[Git에 코드 푸시]

    F --> G[CI/CD 파이프라인 실행]
    G --> H[자동으로 이미지 빌드<br/>docker build -t myapp:latest .]
    H --> I[Docker Registry에 푸시<br/>docker push myapp:latest]
    I --> J[스테이징 서버에 배포<br/>docker run myapp:latest]
    J --> K{QA 테스트 통과?}

    K -->|No| A
    K -->|Yes| L[프로덕션 서버에 배포<br/>docker run myapp:latest]

    style A fill:#e3f2fd
    style L fill:#4caf50

이렇게 Docker를 현업에서 활용하면: - 🚀 배포 속도 향상: 몇 분 만에 새 버전 배포 - 🔄 롤백 쉬움: 문제 시 이전 버전으로 즉시 되돌리기
- 📈 확장성: 트래픽 증가 시 컨테이너 개수만 늘리면 됨 - 🛡️ 안정성: 각 서비스가 독립적이라 장애 전파 방지 - 💰 비용 절약: 서버 리소스 효율적 사용

Docker는 단순한 도구가 아니라 현대적인 소프트웨어 개발과 운영의 필수 요소가 되었어요! 🎉