<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Multi-Container on Chanyeol Dev</title>
    <link>https://chanyeols.com/tags/multi-container/</link>
    <description>Recent content in Multi-Container on Chanyeol Dev</description>
    <generator>Hugo</generator>
    <language>ko-kr</language>
    <lastBuildDate>Fri, 24 Apr 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://chanyeols.com/tags/multi-container/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Docker Compose로 멀티 컨테이너 환경 구축하기: 단계별 튜토리얼</title>
      <link>https://chanyeols.com/posts/docker-compose-multi-container-deployment-guide/</link>
      <pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://chanyeols.com/posts/docker-compose-multi-container-deployment-guide/</guid>
      <description>docker-compose로 멀티 컨테이너 환경을 구성하는 단계별 가이드. 네트워크, 볼륨, 의존성 관리부터 트러블슈팅까지 완벽 정리</description>
      <content:encoded><![CDATA[<h2 id="docker-compose로-멀티-컨테이너-환경-구축하기-단계별-튜토리얼">Docker Compose로 멀티 컨테이너 환경 구축하기: 단계별 튜토리얼</h2>
<blockquote>
<p><strong>주제 키워드</strong>: Docker Compose, 멀티 컨테이너, YAML 구성, 의존성 관리, CI/CD 통합</p>
</blockquote>
<p>현대 애플리케이션 개발에서 <strong>멀티 컨테이너 아키텍처</strong>는 마이크로서비스, 데이터 처리 파이프라인, 개발/운영 환경 통합에 필수적인 요소입니다. <strong>Docker Compose</strong>는 단일 YAML 파일로 여러 컨테이너의 생명주기, 네트워크, 볼륨, 환경 변수를 관리하는 도구로, 개발부터 프로덕션까지 효율성을 극대화합니다. 이 가이드에서는 DB-웹 애플리케이션 예제부터 고급 설정, 트러블슈팅까지 실제 동작 가능한 예제로 설명합니다.</p>
<h2 id="1-docker-compose의-핵심-개념과-장점">1. Docker Compose의 핵심 개념과 장점</h2>
<h3 id="11-멀티-컨테이너-아키텍처의-필요성">1.1 멀티 컨테이너 아키텍처의 필요성</h3>
<p>단일 컨테이너로 모든 기능을 구현하면 <strong>관심사 분리</strong>가 어렵고, <strong>확장성</strong>이 제한됩니다. 예를 들어, 웹 서버와 데이터베이스를 하나의 컨테이너에 묶으면:</p>
<ul>
<li>DB 업데이트 시 전체 애플리케이션 재빌드 필요</li>
<li>각 서비스의 독립적인 확장(Scale-out) 불가</li>
<li>로깅/모니터링의 복잡성 증가</li>
</ul>
<p>Docker Compose는 이런 문제를 해결하며, <strong>서비스 간 의존성</strong>을 명확히 정의하고 <strong>환경별 구성</strong>을 쉽게 전환할 수 있습니다. 공식 문서(<a href="https://docs.docker.com/compose/">Docker Compose Overview</a>)에서도 강조하는 핵심 이점은 다음과 같습니다:</p>
<ul>
<li><strong>선언적 구성</strong>: YAML 파일로 인프라 상태를 코드로 관리</li>
<li><strong>의존성 자동 처리</strong>: <code>depends_on</code>으로 컨테이너 시작 순서 제어</li>
<li><strong>환경 변수 분리</strong>: <code>.env</code> 파일로 민감 정보 관리</li>
</ul>
<h3 id="12-단일-yaml-파일의-효율성">1.2 단일 YAML 파일의 효율성</h3>
<p>예를 들어, 웹 애플리케이션과 PostgreSQL DB를 연결하는 구성은 다음과 같이 단순화됩니다:</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># docker-compose.yml</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">version</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#39;3.8&#39;</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">services</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">webapp</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">image</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">my-webapp:latest</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">ports</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span>- <span style="color:#a5d6ff">&#34;8000:8000&#34;</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">environment</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span>- <span style="color:#a5d6ff">DB_HOST=db</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span>- <span style="color:#a5d6ff">DB_USER=user</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span>- <span style="color:#a5d6ff">DB_PASSWORD=secret</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">depends_on</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span>- <span style="color:#a5d6ff">db</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">db</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">image</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">postgres:15</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">environment</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span><span style="color:#7ee787">POSTGRES_USER</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">user</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span><span style="color:#7ee787">POSTGRES_PASSWORD</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">secret</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">volumes</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span>- <span style="color:#a5d6ff">postgres_data:/var/lib/postgresql/data</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">volumes</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">postgres_data</span>:<span style="color:#6e7681">
</span></span></span></code></pre></div><h2 id="2-사전-준비-개발-환경-설정">2. 사전 준비: 개발 환경 설정</h2>
<h3 id="21-docker-및-docker-compose-설치">2.1 Docker 및 Docker Compose 설치</h3>
<ul>
<li><strong>Linux (Ubuntu 기준)</strong>:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt-get update
</span></span><span style="display:flex;"><span>sudo apt-get install docker.io docker-compose
</span></span></code></pre></div><ul>
<li><strong>macOS</strong>: <a href="https://www.docker.com/products/docker-desktop/">Docker Desktop</a> 설치 후 자동 포함</li>
<li><strong>Windows</strong>: Docker Desktop 설치 시 WSL2와 함께 Compose 활성화</li>
</ul>
<blockquote>
<p><strong>확인 명령</strong>:</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>docker --version
</span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># Docker version 24.0.2, Build cb71016</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>docker-compose version
</span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># docker-compose version 1.29.2, build 5becea4c</span>
</span></span></code></pre></div><h3 id="22-네트워크-및-볼륨-개념">2.2 네트워크 및 볼륨 개념</h3>
<ul>
<li><strong>네트워크</strong>: 컨테이너 간 통신을 위한 가상 네트워크. 기본적으로 Compose는 프로젝트명_default 네트워크를 생성하지만, 커스텀 네트워크도 정의 가능합니다.</li>
<li><strong>볼륨</strong>: 호스트와 컨테이너 간 데이터 영구 저장. 위 예제의 <code>postgres_data</code>는 DB 데이터를 호스트에 보관하여 컨테이너 재생성 시에도 데이터 유지</li>
</ul>
<h2 id="3-단계별-본문-기본-구성-실습">3. 단계별 본문: 기본 구성 실습</h2>
<h3 id="31-간단한-웹-애플리케이션-예제">3.1 간단한 웹 애플리케이션 예제</h3>
<p>Python Flask 애플리케이션과 Redis 캐시를 연동하는 예제를 구현해 보겠습니다.</p>
<h4 id="311-애플리케이션-코드-작성">3.1.1 애플리케이션 코드 작성</h4>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># app.py</span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">from</span> <span style="color:#ff7b72">flask</span> <span style="color:#ff7b72">import</span> Flask
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">import</span> <span style="color:#ff7b72">redis</span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">import</span> <span style="color:#ff7b72">os</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>app <span style="color:#ff7b72;font-weight:bold">=</span> Flask(<span style="color:#79c0ff">__name__</span>)
</span></span><span style="display:flex;"><span>redis_host <span style="color:#ff7b72;font-weight:bold">=</span> os<span style="color:#ff7b72;font-weight:bold">.</span>getenv(<span style="color:#a5d6ff">&#39;REDIS_HOST&#39;</span>, <span style="color:#a5d6ff">&#39;localhost&#39;</span>)
</span></span><span style="display:flex;"><span>redis_client <span style="color:#ff7b72;font-weight:bold">=</span> redis<span style="color:#ff7b72;font-weight:bold">.</span>StrictRedis(host<span style="color:#ff7b72;font-weight:bold">=</span>redis_host, port<span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#a5d6ff">6379</span>, db<span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#a5d6ff">0</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#d2a8ff;font-weight:bold">@app.route</span>(<span style="color:#a5d6ff">&#39;/&#39;</span>)
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">def</span> <span style="color:#d2a8ff;font-weight:bold">hello</span>():
</span></span><span style="display:flex;"><span>    redis_client<span style="color:#ff7b72;font-weight:bold">.</span>incr(<span style="color:#a5d6ff">&#39;hits&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#ff7b72">return</span> <span style="color:#79c0ff">f</span><span style="color:#a5d6ff">&#34;Total hits: </span><span style="color:#a5d6ff">{</span>redis_client<span style="color:#ff7b72;font-weight:bold">.</span>get(<span style="color:#a5d6ff">&#39;hits&#39;</span>)<span style="color:#ff7b72;font-weight:bold">.</span>decode(<span style="color:#a5d6ff">&#39;utf-8&#39;</span>)<span style="color:#a5d6ff">&#34;</span><span style="color:#79c0ff">\n</span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">if</span> <span style="color:#79c0ff">__name__</span> <span style="color:#ff7b72;font-weight:bold">==</span> <span style="color:#a5d6ff">&#34;__main__&#34;</span>:
</span></span><span style="display:flex;"><span>    app<span style="color:#ff7b72;font-weight:bold">.</span>run(host<span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#a5d6ff">&#39;0.0.0.0&#39;</span>, port<span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#a5d6ff">8000</span>)
</span></span></code></pre></div><h4 id="312-docker-이미지-빌드">3.1.2 Docker 이미지 빌드</h4>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-Dockerfile" data-lang="Dockerfile"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># Dockerfile</span><span style="color:#f85149">
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">FROM</span><span style="color:#6e7681"> </span><span style="color:#a5d6ff">python:3.9-slim</span><span style="color:#f85149">
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">WORKDIR</span><span style="color:#6e7681"> </span><span style="color:#a5d6ff">/app</span><span style="color:#f85149">
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">COPY</span> requirements.txt ./<span style="color:#f85149">
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">RUN</span> pip install --no-cache-dir -r requirements.txt<span style="color:#f85149">
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">COPY</span> . ./<span style="color:#f85149">
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">CMD</span> [<span style="color:#a5d6ff">&#34;python&#34;</span>, <span style="color:#a5d6ff">&#34;app.py&#34;</span>]<span style="color:#f85149">
</span></span></span><span style="display:flex;"><span><span style="color:#f85149">
</span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># requirements.txt</span><span style="color:#f85149">
</span></span></span><span style="display:flex;"><span>flask<span style="color:#f85149">
</span></span></span><span style="display:flex;"><span>redis<span style="color:#f85149">
</span></span></span></code></pre></div><h4 id="313-docker-compose-파일-작성">3.1.3 Docker Compose 파일 작성</h4>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># docker-compose.yml</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">version</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#39;3.8&#39;</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">services</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">web</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">build</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">.</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">ports</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span>- <span style="color:#a5d6ff">&#34;8000:8000&#34;</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">environment</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span><span style="color:#7ee787">REDIS_HOST</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">redis</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">depends_on</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span>- <span style="color:#a5d6ff">redis</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">redis</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">image</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">redis:7.0</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">ports</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span>- <span style="color:#a5d6ff">&#34;6379:6379&#34;</span><span style="color:#6e7681">
</span></span></span></code></pre></div><h4 id="314-실행-및-테스트">3.1.4 실행 및 테스트</h4>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># 빌드 및 실행</span>
</span></span><span style="display:flex;"><span>$ docker-compose up --build
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># 별도 터미널에서 테스트</span>
</span></span><span style="display:flex;"><span>$ curl http://localhost:8000
</span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># 출력: Total hits: 1</span>
</span></span></code></pre></div><h3 id="32-의존성-관리의-중요성">3.2 의존성 관리의 중요성</h3>
<p><code>depends_on</code>은 컨테이너 시작 순서만 제어할 뿐, DB 준비 완료 상태를 보장하지 않습니다. 이를 해결하려면 <a href="https://github.com/vishnubob/wait-for-it">wait-for-it.sh</a> 같은 툴을 사용하거나, 애플리케이션 수준에서 재시도 로직을 구현해야 합니다.</p>
<h2 id="4-고급-설정-프로덕션-환경-최적화">4. 고급 설정: 프로덕션 환경 최적화</h2>
<h3 id="41-커스텀-네트워크와-환경-변수-분리">4.1 커스텀 네트워크와 환경 변수 분리</h3>
<h4 id="411-네트워크-정의-예제">4.1.1 네트워크 정의 예제</h4>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># docker-compose.yml</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">version</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#39;3.8&#39;</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">networks</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">app-network</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">driver</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">bridge</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">services</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">web</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">networks</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span>- <span style="color:#a5d6ff">app-network</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">db</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">networks</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span>- <span style="color:#a5d6ff">app-network</span><span style="color:#6e7681">
</span></span></span></code></pre></div><h4 id="412-env-파일-활용">4.1.2 .env 파일 활용</h4>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-env" data-lang="env"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># .env</span>
</span></span><span style="display:flex;"><span><span style="color:#79c0ff">DB_USER</span><span style="color:#ff7b72;font-weight:bold">=</span>admin
</span></span><span style="display:flex;"><span><span style="color:#79c0ff">DB_PASSWORD</span><span style="color:#ff7b72;font-weight:bold">=</span>strong_password
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># docker-compose.yml</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">env_file</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span>- <span style="color:#a5d6ff">.env</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">services</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">web</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">environment</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span><span style="color:#7ee787">DB_USER</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">${DB_USER}</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span><span style="color:#7ee787">DB_PASSWORD</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">${DB_PASSWORD}</span><span style="color:#6e7681">
</span></span></span></code></pre></div><h3 id="42-프로필-기반-구성-devprod">4.2 프로필 기반 구성 (dev/prod)</h3>
<p>Compose 1.27+부터 <code>profiles</code>를 사용해 환경별 서비스를 활성화할 수 있습니다.</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># docker-compose.yml</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">version</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#39;3.8&#39;</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">services</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">web</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">image</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">my-webapp:latest</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">db</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">image</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">postgres:15</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">devtools</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">image</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">node:18</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">command</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">npm run dev</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">profiles</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span>- <span style="color:#a5d6ff">dev</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">monitoring</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">image</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">prom/prometheus</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">profiles</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span>- <span style="color:#a5d6ff">prod</span><span style="color:#6e7681">
</span></span></span></code></pre></div><blockquote>
<p><strong>실행 방법</strong>:</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># 개발 환경</span>
</span></span><span style="display:flex;"><span>$ docker-compose --profile dev up
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># 프로덕션 환경</span>
</span></span><span style="display:flex;"><span>$ docker-compose --profile prod up
</span></span></code></pre></div><h2 id="5-트러블슈팅-흔한-문제와-해결법">5. 트러블슈팅: 흔한 문제와 해결법</h2>
<h3 id="51-컨테이너-간-연결-실패">5.1 컨테이너 간 연결 실패</h3>
<ul>
<li><strong>증상</strong>: <code>Connection refused</code> 오류 발생</li>
<li><strong>원인</strong>: DB가 준비되기 전에 웹 애플리케이션이 연결을 시도</li>
<li><strong>해결</strong>:
<ol>
<li><code>depends_on</code>에 <code>condition</code> 추가</li>
<li><a href="https://github.com/avengerow/dockurize">Dockerize</a> 같은 툴로 헬스 체크</li>
</ol>
</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># 조건 추가 예제</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">depends_on</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span><span style="color:#7ee787">db</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">condition</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">service_healthy</span><span style="color:#6e7681">
</span></span></span></code></pre></div><h3 id="52-볼륨-마운트-권한-문제">5.2 볼륨 마운트 권한 문제</h3>
<ul>
<li><strong>증상</strong>: <code>Permission denied</code> 오류</li>
<li><strong>해결</strong>:
<ol>
<li>호스트 디렉터리 권한 변경</li>
<li>Docker Compose에서 <code>user</code> 지정</li>
</ol>
</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># 권한 문제 해결 예제</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#7ee787">volumes</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span>- <span style="color:#7ee787">type</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">volume</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">source</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">myvol</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">target</span>:<span style="color:#6e7681"> </span><span style="color:#a5d6ff">/app/data</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#7ee787">volume</span>:<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">      </span><span style="color:#7ee787">nocopy</span>:<span style="color:#6e7681"> </span><span style="color:#79c0ff">true</span><span style="color:#6e7681">
</span></span></span></code></pre></div><h3 id="53-로그-분석">5.3 로그 분석</h3>
<ul>
<li><strong>컨테이너 로그 확인</strong>:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ docker-compose logs <span style="color:#ff7b72;font-weight:bold">[</span>서비스명<span style="color:#ff7b72;font-weight:bold">]</span>
</span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"># 예: docker-compose logs web</span>
</span></span></code></pre></div><ul>
<li><strong>실시간 모니터링</strong>:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ docker-compose logs -f web
</span></span></code></pre></div><h2 id="6-마치며-docker-compose의-확장성">6. 마치며: Docker Compose의 확장성</h2>
<ol>
<li><strong>CI/CD 통합</strong>: GitHub Actions, GitLab CI에서 <code>docker-compose</code> 명령어로 테스트 환경 구축 가능</li>
<li><strong>확장성</strong>: Kubernetes로의 전환을 위해 Compose 파일을 Helm 차트로 변환 가능</li>
<li><strong>모니터링</strong>: Prometheus + Grafana와 연동해 컨테이너 메트릭 수집</li>
</ol>
<blockquote>
<p><strong>추가 학습 자료</strong>:</p>
</blockquote>
<ul>
<li><a href="https://docs.docker.com/compose/reference/">Docker Compose 공식 문서</a></li>
<li><a href="https://github.com/veggiemonk/awesome-docker">Awesome Docker</a> 커뮤니티 리소스</li>
</ul>
<p>이 가이드를 통해 멀티 컨테이너 환경의 설계부터 운영까지의 핵심 역량을 습득할 수 있습니다. 실제 프로덕션 환경에서는 보안 강화(예: TLS 암호화)와 리소스 제한(예: <code>--memory</code>, <code>--cpus</code>)을 추가로 적용해야 합니다.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
