LabHub

볼륨·네트워크·컴포즈 · 여러 컨테이너 묶기 · 이론

스택을 파일 하나로 선언한다는 것

LabHub 에서 이어서 보기

한 줄 요약

Compose 파일은 여러 컨테이너의 실행 인자를 선언형으로 적어 둔 것입니다.
마법이 아니라, docker run 플래그와 일대일로 대응합니다.

왜 이게 필요했나

컨테이너 셋을 손으로 띄우려면 네트워크를 만들고, 볼륨을 만들고, 각각에
--network, -v, -e, -p 를 정확한 순서로 붙여야 합니다. 한 사람이
한 번 하는 데는 문제가 없지만, 두 번째 사람이 같은 스택을 재현하려는
순간부터 지옥이 됩니다. 어디에도 적혀 있지 않기 때문입니다.

Compose 가 실제로 해결하는 문제가 이것입니다. 스택의 모양이 파일 하나에
적혀 있고, 그 파일이 저장소에 커밋됩니다.

어떻게 동작하나

핵심 대응 관계는 이렇습니다.

| Compose 키 | docker run 대응 |
| --- | --- |
| image | 이미지 인자 |
| command | 이미지 뒤의 명령 |
| ports | -p |
| volumes | -v / --mount |
| environment | -e |
| networks | --network |
| depends_on | (대응 없음 — 기동 순서만) |

여기서 두 가지를 짚어야 합니다.

**첫째, Compose 는 프로젝트마다 사용자 정의 네트워크를 자동으로 만들고
서비스 이름을 별칭으로 등록합니다.** 그래서 "Compose 에서는 잘 되던 것이
docker run 으로 옮기면 안 되는" 일이 생깁니다. 원인은 Compose 의
마법이 아니라, 손으로 옮길 때 네트워크를 안 만들었기 때문입니다.

둘째, depends_on 은 순서만 보장하지 준비 상태를 보장하지 않습니다.
DB 컨테이너가 "시작"된 것과 DB 가 "접속을 받을 준비가 된" 것은 다릅니다.
그래서 헬스체크 조건을 함께 걸거나, 애플리케이션이 재시도하도록 만들어야
합니다. 이 구분을 놓치면 배포할 때마다 첫 몇 초 동안 커넥션 오류가
쏟아집니다.

현장에서 만나는 모습

실전 구성에서 자주 쓰는 패턴은 네트워크를 두 개로 나누는 것입니다.
프론트엔드 네트워크에는 리버스 프록시만, 백엔드 네트워크에는 DB 와 캐시를
두고 앱만 양쪽에 소속시킵니다. 그러면 DB 는 프록시 쪽에서 이름조차 해석되지
않습니다.

그리고 exposeports 와 헷갈리면 안 됩니다. **expose 는 호스트에
포트를 열지 않습니다.** 문서화 용도입니다. 컨테이너끼리만 통신하는
서비스는 아예 ports 를 쓰지 않는 것이 맞습니다.

마지막으로, 선언과 실제가 어긋나는 순간이 사고의 시작입니다. 누군가
손으로 컨테이너를 고치면 파일과 현실이 갈라지고, 그 갈라짐은 다음 배포
때까지 아무도 모릅니다. 선언과 실제를 대조하는 습관이 그래서 중요합니다.

다음 실습에서 할 것

두 서비스로 이루어진 스택을 Compose 파일로 선언하고, 같은 스택을 손으로도
띄운 뒤, 선언한 값과 실제로 도는 값이 일치하는지 직접 대조합니다.