도커(Docker)

  • 애플리케이션과 실행에 필요한 모든 요소
    하나의 표준 단위(컨테이너)로 묶는 플랫폼

  • 컨테이너 = 코드 + 런타임 + 라이브러리 + 시스템 도구 + 설정

  • 리눅스 커널의 네임스페이스/cgroup 기술로
    프로세스를 격리해 가볍고 빠르게 실행

  • 핵심 이점
    환경 일관성, 빠른 기동 시간, 높은 이식성, 대규모 운영의 자동화

도커의 필요성

  • 개발 노트북, 테스트/운영 서버의 OS 버전, 의존성이 서로 다름
  • 라이브러리 버전 충돌, 운영체제 의존 도구 누락, 시스템 환경변수 차이
  • 도커는 애플리케이션 전체를 이미지로 고정
    어디에서 실행해도 동일 환경 보장

가상 머신(VM) vs 컨테이너

VM

  • 게스트 OS 전체를 가상화 → 무겁고(GB), 부팅에 분 단위 소요

컨테이너

  • 호스트 커널을 공유, 앱과 라이브러리만 격리 → 수십 MB, 수 초 내 기동

  • 동일 하드웨어에서 VM은 10대 수준, 컨테이너는 수백 개 까지 실행 가능
  • 개발 속도, 자원 효율, 배포 빈도 등 모든 면에서 컨테이너가 유리

도커 아키텍처의 3대 요소

이미지(image): 앱과 환경을 고려한 읽기 전용 템플릿 - 붕어빵 틀

컨테이너(container): 이미지를 실행 상태로 인스턴스화한 실제 프로세스 - 붕어빵

레지스트리(Registry): 이미지를 저장, 공유하는 원격 창고 (ex) 도커 허브)

흐름: Dockerfile → build → 이미지 → push
→ 레지스트리 → pull → run → 컨테이너

실습: Node.js 예제 어플리케이션

index.js/package.json - 두 파일을 같은 폴더에 준비

// index.js — 3000번 포트에서 응답하는 최소 웹 서버
const http = require('http');
const server = http.createServer((req, res) => {
  res.end('Hello Docker World!');
});
server.listen(3000, () => console.log('3000번 포트 가동 중!'));

// package.json — 시작 스크립트 정의
{
  "name": "docker-node-app",
  "scripts": { "start": "node index.js" }
}

도커파일(Dockerfile)

  • 이미지를 어떻게 만들지 단계별로 기술한 평문 스크립트 - 이미지의 설계도

  • 한 줄 한 줄이 하나의 레이어(Layer)로 쌓여 최종 이미지 구성

  • 변경이 없는 레이어는 캐시 재사용 → 빌드 시간이 극적으로 단축

  • 공식 베이스 이미지(node, python, nginx 등) 위에 내 앱을 얹는 방식이 일반적

Dockerfile 상세 분석

# 1. 기반 이미지 설정 - Node.js 18이 설치된 리눅스 환경을 상속
FROM node:18
# 2. 작업 디렉토리 지정 - 컨테이너 내부 /app 폴더를 만들고 그리로 이동
WORKDIR /app
# 3. 소스 코드 복사 - 현재 폴더의 모든 파일을 /app 안으로 복사
COPY . .
# 4. 실행 명령어 정의 - 컨테이너 기동 시 자동으로 실행
CMD ["npm", "start"]

주요 명령어 정리

이미지 빌드 - docker build로 붕어빵 틀 만들기

  • 명령: docker build -t yourid/node-app .

  • -t 옵션: 이미지에 [사용자/이미지이름: 태그] 형태의 이름표 부착

  • .: 빌드 컨텍스트 = Dockerfile이 위치한 현재 폴더

  • 확인: docker images로 방금 만든 이미지가 목록에 표시되는지 점검

도커 허브를 통한 전 세계 배포 워크플로우

도커 컴포즈(Docker Compose)

  • 여러 개의 컨테이너를 하나의 설정으로 정의/실행하는
    다중 컨테이너 오케스트레이션 도구

  • 설정 파일: docker-compose.yaml (YAML 형식)

  • 한 줄 명령 docker-compose up으로 모든 서비스와 네트워크를 일괄 기동

  • 각 서비스 간 의존 순서, 네트워크, 볼륨, 환경변수를 선언적으로 기술

도커 컴포즈가 필요한 이유

  • 도커 단독 사용 시, 컨테이너마다 docker run을 반복하고
    포트, 네트워크, 옵션을 매번 기억해야 함

  • 수 개 ~ 수십 개 서비스가 얽힌 환경에서 수동 실행은 실수와 누락의 온상

  • 컴포즈: 전체 토폴로지를 YAML로 버전 관리
    → 팀원 모두 동일한 구성으로 재현

  • 개발/테스트용 로컬 환경을 한 명령(up)으로 초기화하고
    한 명령(down)으로 정리

실습: docker-compose.yaml 작성

웹 서버 + 레디스 구성 예시

version: '3.8'               # 1. 컴포즈 파일 규격 버전
services:                    # 2. 실행할 서비스들의 묶음
  web-app:                   # 3. 웹 서버 서비스 정의
    build: .                 # 4. 현재 폴더의 Dockerfile 로 빌드
    ports:                   # 5. 포트 연결 설정
      - "8080:3000"
    depends_on:              # 6. 실행 의존성 정의
      - redis-db             # 7. redis-db가 먼저 켜져야 함
  redis-db:                  # 8. 레디스 서비스 정의
    image: "redis:alpine"    # 9. 공식 경량 이미지 사용

라인별 해석

depends-on 실행 순서의 유무 비교

  • depends-on컨테이너 기동 순서를 보장하는 가이드라인
  • 레디스 컨테이너가 먼저 올라온 뒤에야 웹 서비스가 실행됨
  • 내부 애플리케이션이 완전히 준비(ready) 된 상태까지는 보장하지 않음
    헬스체크 병행 권장

컴포즈는 서비스 이름만으로 통신함

// web-app 컨테이너 내부의 Node.js 코드
const redis = require('redis');
// 과거방식 컨테이너 IP를 직접 적어야 했던 시대
// const client = redis.createClient({ host: '172.18.0.3' });

// 컴포즈방식 yml에 적은 서비스 이름을 그대로 주소로
const client = redis.createClient({ host: 'redis-db' });
// 도커 내부 DNS가 'redis-db'를 자동으로 해석해 연결

도커 컴포즈 핵심 명령어

docker-compose up-d: 설계도대로 모든 서비스를 백그라운드로 기동

docker-compose down: 컨테이너, 네트워크, 볼륨을 한 번에 정리

docker-compose ps: 현재 실행 중인 서비스 상태 조회

docker-compose logs -f [서비스명]: 실시간 로그 스트리밍으로 디버깅

docker-compose build: 코드 변경 후 이미지만 다시 빌드

마무리

  • 도커는 앱과 환경을 이미지로 고정해 어디서나 동일하게를 보장함

  • 도커파일의 네 줄 레시피만으로 나만의 실행 환경을 재현 가능하게 만듦

  • 빌드 → 푸시 → 풀 → 런 4단계로 전 세계 어디든 배포 가능

  • 도커 컴포즈는 YAML 한 장으로 다중 컨테이너 시스템을 한 번에 지휘함

  • 서비스 이름과 depedns-on 만으로 컨테이너 간 통신/실행 순서를 해결

0개의 댓글