Docker는 애플리케이션과 의존성을 컨테이너로 패키징해 어느 서버에서든 동일하게 실행할 수 있게 합니다. 서버 환경을 깔끔하게 분리하고 관리하는 데 매우 유용합니다.

Docker 설치

# 의존성 설치
sudo apt update
sudo apt install -y ca-certificates curl gnupg

# Docker 공식 GPG 키 추가
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
    sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 저장소 추가
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
    https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
    sudo tee /etc/apt/sources.list.d/docker.list

# 설치
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# 현재 사용자를 docker 그룹에 추가 (sudo 없이 사용)
sudo usermod -aG docker $USER
newgrp docker

기본 명령어

# 이미지 검색 및 다운로드
docker search nginx
docker pull nginx:latest

# 컨테이너 실행
docker run -d \
    --name my-nginx \
    -p 8080:80 \
    nginx:latest

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

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

# 컨테이너 로그 확인
docker logs -f my-nginx

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

# 컨테이너 중지 및 삭제
docker stop my-nginx
docker rm my-nginx

볼륨으로 데이터 영구 보존

컨테이너를 삭제하면 내부 데이터도 함께 사라집니다. 볼륨을 사용해 데이터를 호스트에 보존합니다:

# 호스트 디렉터리를 컨테이너에 마운트
docker run -d \
    --name mysql-db \
    -e MYSQL_ROOT_PASSWORD=비밀번호 \
    -e MYSQL_DATABASE=myapp \
    -v /opt/mysql-data:/var/lib/mysql \
    -p 3306:3306 \
    mysql:8.0

# Docker 관리 볼륨 사용
docker volume create mydata
docker run -d -v mydata:/data alpine

# 볼륨 목록 확인
docker volume ls

네트워크 설정

# 사용자 정의 네트워크 생성 (컨테이너 간 통신)
docker network create myapp-network

# 같은 네트워크에 컨테이너 연결
docker run -d --name app --network myapp-network my-app-image
docker run -d --name db --network myapp-network mysql:8.0

# app 컨테이너에서 db 컨테이너 이름으로 접속 가능
# mysql -h db -u root -p

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

여러 컨테이너를 한 파일로 정의하고 관리합니다:

# docker-compose.yml
version: '3.8'

services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./html:/usr/share/nginx/html:ro
    depends_on:
      - app
    networks:
      - myapp

  app:
    image: node:20-alpine
    working_dir: /app
    volumes:
      - ./app:/app
    command: node server.js
    environment:
      - DB_HOST=db
      - DB_PASSWORD=${DB_PASSWORD}
    networks:
      - myapp
    depends_on:
      - db

  db:
    image: mysql:8.0
    volumes:
      - db-data:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
      - MYSQL_DATABASE=myapp
    networks:
      - myapp

volumes:
  db-data:

networks:
  myapp:
    driver: bridge
# 실행 (.env 파일에 환경변수 정의)
docker compose up -d

# 상태 확인
docker compose ps
docker compose logs -f

# 중지 및 삭제 (볼륨 보존)
docker compose down

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

이미지 빌드 (Dockerfile)

# Dockerfile
FROM ubuntu:22.04

# 패키지 설치
RUN apt update && apt install -y \
    nginx \
    && rm -rf /var/lib/apt/lists/*

# 설정 파일 복사
COPY nginx.conf /etc/nginx/nginx.conf

# 포트 노출
EXPOSE 80

# 실행 명령
CMD ["nginx", "-g", "daemon off;"]
# 이미지 빌드
docker build -t my-nginx:1.0 .

# 이미지 목록
docker images

리소스 제한 및 모니터링

# CPU/메모리 제한
docker run -d \
    --name limited-app \
    --memory="512m" \
    --cpus="1.0" \
    my-app-image

# 실시간 리소스 사용량 확인
docker stats

# 사용하지 않는 리소스 정리
docker system prune -a

보안 고려사항

# 루트가 아닌 사용자로 실행
docker run --user 1000:1000 my-app-image

# 읽기 전용 루트 파일시스템
docker run --read-only my-app-image

# 컨테이너가 새 권한 획득 방지
docker run --security-opt no-new-privileges my-app-image

Docker를 활용하면 서버에 여러 서비스를 깔끔하게 분리해 운영할 수 있습니다. 특히 개발 환경과 프로덕션 환경의 일관성을 유지하는 데 매우 효과적입니다.