Docker Compose로 멀티 컨테이너 환경 구축하기: 단계별 튜토리얼

Docker Compose로 멀티 컨테이너 환경 구축하기: 단계별 튜토리얼

Docker Compose로 멀티 컨테이너 환경 구축하기: 단계별 튜토리얼 주제 키워드: Docker Compose, 멀티 컨테이너, YAML 구성, 의존성 관리, CI/CD 통합 현대 애플리케이션 개발에서 멀티 컨테이너 아키텍처는 마이크로서비스, 데이터 처리 파이프라인, 개발/운영 환경 통합에 필수적인 요소입니다. Docker Compose는 단일 YAML 파일로 여러 컨테이너의 생명주기, 네트워크, 볼륨, 환경 변수를 관리하는 도구로, 개발부터 프로덕션까지 효율성을 극대화합니다. 이 가이드에서는 DB-웹 애플리케이션 예제부터 고급 설정, 트러블슈팅까지 실제 동작 가능한 예제로 설명합니다. 1. Docker Compose의 핵심 개념과 장점 1.1 멀티 컨테이너 아키텍처의 필요성 단일 컨테이너로 모든 기능을 구현하면 관심사 분리가 어렵고, 확장성이 제한됩니다. 예를 들어, 웹 서버와 데이터베이스를 하나의 컨테이너에 묶으면: ...

2026년 4월 24일 · 4 min · 756 words · Chanyeol

사내 VM IP 관리 시스템 만들기 - React 대시보드 + Docker Compose 배포 (4편)

React 대시보드 대시보드는 탭 2개로 구성된다. VM 목록 — 전체 VM 현황, 상태별 필터, ONLINE/OFFLINE/UNKNOWN 배지 이벤트 로그 — IP 충돌, IP 변경, 오프라인 이벤트 타임라인 WebSocket이 아닌 30초 폴링으로 구현했다. VM 상태가 초 단위로 바뀌지 않고, 운영 대시보드 특성상 약간의 지연은 허용된다. 심플하게 가는 게 낫다고 판단했다. 30초 폴링 훅 // usePolling.js import { useEffect, useRef } from 'react'; export function usePolling(callback, intervalMs = 30_000) { const callbackRef = useRef(callback); useEffect(() => { callbackRef.current = callback; }); useEffect(() => { callbackRef.current(); // 마운트 시 즉시 1회 실행 const id = setInterval(() => callbackRef.current(), intervalMs); return () => clearInterval(id); }, [intervalMs]); } // App.jsx const [vms, setVms] = useState([]); const [loading, setLoading] = useState(true); usePolling(async () => { const data = await fetch('/api/vms').then(r => r.json()); setVms(data); setLoading(false); }, 30_000); callbackRef를 쓰는 이유는 setInterval 클로저가 최초 등록 시점의 callback을 계속 참조하는 문제를 피하기 위해서다. useRef로 항상 최신 콜백을 가리키도록 한다. ...

2026년 4월 15일 · 5 min · 958 words · Chanyeol

사내 인사정보 관리 시스템 만들기 - Docker Compose 멀티 서비스 배포 + 트러블슈팅 (3편)

Docker Compose 멀티 서비스 구성 세 서비스가 올바른 순서로 떠야 한다. db (PostgreSQL) → server (Express + Prisma) → client (React + nginx) server가 DB보다 먼저 뜨면 Prisma 연결이 실패하고, client가 server보다 먼저 뜨면 API 프록시가 동작하지 않는다. docker-compose.yml services: db: image: postgres:16-alpine container_name: insa-db environment: POSTGRES_DB: unipost_insa POSTGRES_USER: insa POSTGRES_PASSWORD: insa1234 volumes: - ./data/postgres:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U insa -d unipost_insa"] interval: 5s timeout: 5s retries: 10 server: build: ./server container_name: insa-server ports: - "4000:4000" env_file: - ./server/.env environment: DATABASE_URL: postgresql://insa:insa1234@db:5432/unipost_insa depends_on: db: condition: service_healthy healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:4000/health', r => process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))"] interval: 5s timeout: 5s retries: 10 restart: unless-stopped client: build: ./client container_name: insa-client ports: - "3002:80" depends_on: server: condition: service_healthy restart: unless-stopped depends_on에 condition: service_healthy를 쓰면 단순히 컨테이너가 “시작됐는지"가 아니라 “준비됐는지"를 확인하고 다음 서비스를 시작한다. ...

2026년 4월 11일 · 5 min · 862 words · Chanyeol
1