본문으로 건너뛰기
피드

2026년에 Docker Compose를 프로덕션에서 써도 될까? 답은 '가능하지만 운영은 직접 챙겨야 함'

devops 약 15분

Docker Compose는 2026년에도 단일 노드 프로덕션, 고객사 내부망 배포, 엣지 장비 같은 환경에서는 충분히 쓸 수 있음. 다만 Compose 자체에는 스케줄러, 상태 조정기, 자동 복구, 배포 에이전트가 없어서 orphan 컨테이너, 디스크 고갈, healthcheck 무시, latest 태그 드리프트, Docker socket 권한 같은 운영 구멍을 팀이 직접 메워야 함.

  • 1

    Compose는 작은 프로덕션 워크로드에 여전히 유효하지만, Kubernetes처럼 상태를 계속 맞춰주는 컨트롤 플레인이 없음

  • 2

    서비스를 삭제해도 예전 컨테이너가 남을 수 있으니 --remove-orphans를 매번 써야 함

  • 3

    컨테이너 로그와 이미지 레이어를 방치하면 디스크가 차서 Docker 자체가 이상하게 실패할 수 있음

  • 4

    Docker HEALTHCHECK는 상태만 표시하고 자동 재시작은 하지 않음

  • 5

    프로덕션 이미지는 :latest 대신 @sha256 digest로 고정해야 배포 드리프트를 막을 수 있음

  • 6

    /var/run/docker.sock 마운트는 사실상 호스트 root 권한을 주는 것과 비슷함

  • 7

    고객사 여러 대에 Compose를 배포하려면 Watchtower나 SSH 스크립트보다 상태 보고와 롤백이 있는 pull 기반 에이전트가 현실적임

Compose는 아직 죽지 않았지만, 그냥 쓰면 운영 구멍이 그대로 남음

  • 결론부터 말하면 Docker Compose는 2026년에도 프로덕션에서 쓸 수 있음. 단, 'Compose만으로 충분하다'는 뜻은 아님.

    • 글쓴이는 self-managed 환경에 소프트웨어와 AI 앱을 배포하는 Distr 엔지니어고, 실제 고객 호스트에서 Docker Compose와 Docker Swarm 배포를 매일 다룬다고 함.
    • Compose가 잘 맞는 곳은 단일 노드 배포, 고객사 내부망에 넣는 벤더 앱, Kubernetes 클러스터까지는 과한 내부 장기 운영 서비스, 매장이나 엣지 장비 같은 환경임.
  • Compose의 매력은 단순함임. docker-compose.yaml 하나에 서비스, 네트워크, 볼륨, 환경변수, 설정 파일 패턴을 적고 docker compose up으로 호스트 상태를 맞춤.

    • 문제는 docker compose up이 한 번 실행되고 끝난다는 점임.
    • 뒤에서 계속 감시하는 스케줄러도 없고, 상태를 다시 맞추는 reconciler도 없고, 외부에서 업데이트를 밀어 넣는 컨트롤 플레인도 없음.

중요

> Compose의 진짜 질문은 '프로덕션에 써도 되냐'가 아니라 'Compose가 안 해주는 운영 작업을 누가 책임질 거냐'에 가까움.

자주 터지는 사고 1: 지운 서비스가 계속 살아 있음

  • docker-compose.yaml에서 서비스를 지우고 docker compose up -d를 다시 실행해도, 예전 컨테이너가 자동으로 사라지지 않을 수 있음.

    • 이 컨테이너는 프로젝트에서 떨어져 나갔지만 같은 네트워크나 포트를 계속 물고 있을 수 있음.
    • docker compose ps에는 안 보이는데, docker ps --filter label=com.docker.compose.project=로 보면 아직 Docker 라벨이 남아 있는 식임.
    • 6개월 뒤에 '왜 예전 worker가 아직 RAM을 먹고 있지?' 같은 상황이 나오는 이유가 이거임.
  • 해결책은 매번 --remove-orphans를 붙이는 것.

    • 이 플래그는 예전에 프로젝트에 속했지만 현재 Compose 파일에는 없는 컨테이너를 제거하라고 알려줌.
    • Compose가 만든 네트워크도 up 과정에서 비슷하게 정리됨.
    • 단, named volume은 데이터 보호 때문에 기본적으로 남겨 둠. 지운 서비스가 쓰던 볼륨 공간까지 회수하려면 docker volume ls --filter dangling=true로 후보를 보고 직접 지우거나, 프로젝트 전체 볼륨을 날릴 의도일 때만 docker compose down -v를 써야 함.

자주 터지는 사고 2: 디스크가 조용히 다 차버림

  • docker compose pull을 할 때마다 이전 이미지가 디스크에 남고, 기본 json-file 로그 드라이버는 컨테이너 로그를 무제한으로 씀.

    • 로그 경로는 /var/lib/docker/containers//-json.log 형태임.
    • 바쁜 호스트에서는 이게 정말 흔한 장애 원인임. 디스크가 꽉 차면 Docker가 로그, 메타데이터, 이미지 레이어를 못 쓰고 컨테이너 실패도 이상한 형태로 보이기 시작함.
  • 먼저 docker system df -v로 어디서 공간을 먹는지 봐야 함.

    • -v 옵션은 이미지, 컨테이너, 볼륨, 빌드 캐시별 사용량을 나눠 보여줘서 범인을 찾기 좋음.
    • 이미지는 prune 스케줄을 두고, 볼륨은 docker volume prune -f가 강력하지만 데이터 삭제 리스크가 있으니 대충 누르면 안 됨.
  • 로그는 Docker 데몬 레벨에서 한 번에 제한하는 게 좋음.

    • /etc/docker/daemon.json에 json-file 로그 드라이버의 max-size와 max-file을 설정하면 새 컨테이너부터 로그 로테이션이 적용됨.
    • 예시처럼 10MB씩 3개만 유지하면 컨테이너 하나당 로그 상한이 30MB가 됨.
    • 이미 떠 있는 컨테이너는 새 기본값을 먹이려면 재생성해야 함.

⚠️주의

> 로그 제한 없이 Compose를 오래 돌리면 앱 버그가 아니라 디스크 고갈 때문에 Docker 전체가 흔들릴 수 있음. 이건 배포 전에 잡아야 하는 운영 기본값임.

자주 터지는 사고 3: HEALTHCHECK는 자동 복구가 아님

  • Dockerfile의 HEALTHCHECK나 Compose의 healthcheck: 블록을 추가해도, 컨테이너가 unhealthy가 됐다고 Docker Engine이 알아서 재시작하지는 않음.

    • Docker는 상태를 보고할 뿐임.
    • restart: unless-stopped는 컨테이너 프로세스가 종료됐을 때 동작하지, unhealthy 상태 표시에는 반응하지 않음.
    • docker inspect로 보면 실패 streak와 마지막 probe 출력까지 나오지만, 엔진은 그 정보를 보고 액션을 취하지 않음.
  • 선택지는 세 가지 정도임.

    • willfarrell/docker-autoheal 같은 autoheal 사이드카를 띄워 Docker socket을 마운트하고 unhealthy 이벤트를 감시하게 함.
    • Docker Swarm으로 올리면 Swarm이 unhealthy task를 기본적으로 재시작함.
    • Distr처럼 배포 에이전트가 adapted autoheal 서비스를 같이 배포하도록 설계할 수도 있음.
sequenceDiagram
    participant 컨테이너
    participant 도커엔진
    participant 오토힐
    participant 운영자
    컨테이너->>도커엔진: HEALTHCHECK 실패 보고
    도커엔진->>도커엔진: 상태를 unhealthy로 표시
    도커엔진-->>운영자: inspect나 이벤트로 상태 노출
    오토힐->>도커엔진: unhealthy 이벤트 감시
    오토힐->>도커엔진: 문제 컨테이너 재시작 요청
    도커엔진->>컨테이너: 컨테이너 재시작

자주 터지는 사고 4: :latest는 약속이 아니라 포인터임

  • Docker 태그는 바뀔 수 있는 참조임. myapp:1.4도 오늘과 내일이 다를 수 있고, :latest는 특히 위험함.

    • image: nginx처럼 태그를 생략하면 사실상 image: nginx:latest로 처리됨.
    • 두 호스트가 5분 차이로 같은 태그를 pull했는데 서로 다른 레이어를 받아 다른 코드를 실행할 수 있음.
    • 프로덕션에서 이건 재현성 박살 나는 지름길임.
  • 해결책은 digest로 고정하는 것임.

    • image@sha256:... 형태로 이미지 내용을 직접 가리키면 태그 변경과 무관하게 같은 바이트를 받게 됨.
    • registry에 해당 digest가 없으면 pull이 빠르게 실패함. 조용히 다른 코드가 뜨는 것보다 훨씬 낫다.
    • 같은 참조 방식은 docker stack deploy, docker run, Kubernetes manifest에서도 통함.

자주 터지는 사고 5: Docker socket 마운트는 거의 호스트 root임

  • /var/run/docker.sock을 컨테이너에 마운트하면 그 컨테이너는 Docker API를 호출할 수 있음.

    • Docker API는 privileged 컨테이너를 띄우고 호스트 root filesystem을 마운트할 수 있음.
    • 즉 socket을 가진 컨테이너는 사실상 호스트 root 권한을 가진 셈임.
  • 실무 위생은 꽤 명확함.

    • socket을 마운트한 컨테이너를 inventory로 관리하고, 에이전트, CI runner, 모니터링 사이드카, 컨테이너 관리 UI처럼 꼭 필요한 것만 남김.
    • 가능하면 rootless Docker를 써서 socket이 털렸을 때 blast radius를 호스트 전체가 아니라 해당 사용자 계정 수준으로 줄임.
    • docker-socket-proxy 같은 프록시로 monitoring에 필요한 read-only containers/events처럼 API 일부만 노출함.
    • socket을 잡는 이미지는 작고 단순하게 유지해서 공격 표면을 줄임.

고객사 여러 대에 Compose 배포하기는 또 다른 문제임

  • SSH로 들어가서 docker compose pull && docker compose up -d를 치는 건 한 대일 때나 깔끔함.

    • 고객사 self-managed 환경이 수십 개가 되고, 각자 방화벽과 변경 승인 프로세스가 다르면 수동 배포는 바로 한계가 옴.
    • Docker Hub webhook은 이미지 push 시 CI를 깨울 수는 있지만, 고객사 네트워크 안의 Compose 호스트에게 pull하라고 말해주지는 못함.
  • 흔한 우회책마다 비용이 있음.

    • Watchtower는 registry를 주기적으로 polling해서 새 이미지를 받고 컨테이너를 재생성함. 설치는 쉽지만 staged rollout, rollback, 중앙 가시성이 약함.
    • bastion, SSH, Ansible, 스크립트 조합은 고객 10곳까지는 버틸 수 있어도 50곳, air-gapped 3곳, 자체 변경 일정 4곳 같은 상황이 되면 운영자가 공유 키와 점검 시간표에 깔림.
    • pull 기반 agent는 고객 호스트 안에서 주기적으로 중앙 endpoint를 polling하고, 로컬 Compose 상태를 서버가 원하는 상태와 맞춤. Distr는 agent가 5초마다 polling하고, 각 고객이 어느 버전에 있는지 대시보드에 보고한다고 함.
  • 이 패턴은 Kubernetes operator나 GitOps 도구가 이미 쓰는 방식이기도 함.

    • Compose 사용자도 결국 비슷한 걸 만들게 되는데, rollback, 상태 보고, 버전 pinning 없이 만들면 보이지 않는 fleet drift가 생김.
    • agent 자기 자신을 업데이트할 때는 별도 컨테이너를 띄워 교체하게 해야 함. 실행 중인 자기 자신을 바로 바꾸려 하면 꼬이기 쉬움.

Compose 다음 단계는 보통 Kubernetes, 가끔 Swarm

  • 단일 노드 Compose 배포가 커지면 대부분의 팀에게 현실적인 다음 단계는 Kubernetes임.

    • 생태계가 크고, 운영 패턴이 문서화돼 있고, 채용 가능한 인력 풀이 있음.
    • 대신 운영 복잡도는 확실히 올라감.
  • Docker Swarm도 여전히 선택지는 됨.

    • Compose YAML 형식을 재사용하고 Docker에 내장돼 있음.
    • unhealthy task 재시작, update_config 기반 rollout, secrets/configs 같은 기능을 제공함.
    • 다만 넓은 범용 플랫폼이라기보다는 단일 클러스터, 낮은 ceremony 배포에 맞는 좁은 선택지로 보는 게 맞음.
  • 요약하면 Compose는 프로덕션 불가가 아니라 운영 자동화가 없는 도구임.

    • 매번 --remove-orphans를 붙임.
    • 로그 상한을 daemon.json에 설정하고 이미지 prune을 스케줄링함.
    • HEALTHCHECK를 autoheal, Swarm, agent 중 하나와 연결함.
    • :latest 대신 @sha256 digest로 pinning함.
    • Docker socket 마운트를 root 권한처럼 취급함.
    • 여러 고객사 호스트에는 상태 보고와 rollback이 있는 agent를 둠.

기술 맥락

  • Compose는 원래 '한 호스트에서 여러 컨테이너를 쉽게 묶어 띄우는 도구'라서, Kubernetes처럼 계속 상태를 감시하고 복구하는 시스템으로 설계된 게 아니에요. 그래서 단일 노드나 고객사 내부망 배포처럼 작고 명확한 환경에서는 장점이 살아나지만, 운영 자동화는 별도 레이어로 붙여야 해요.

  • --remove-orphans, 로그 로테이션, 이미지 prune 같은 얘기가 중요한 이유는 장애 원인이 앱 코드가 아니라 호스트 상태 누적에서 오는 경우가 많기 때문이에요. Compose는 YAML에서 빠진 컨테이너나 오래된 이미지, 커지는 로그를 적극적으로 정리해주지 않으니 배포 파이프라인이나 에이전트가 그 역할을 맡아야 해요.

  • HEALTHCHECK도 이름 때문에 오해하기 쉬운데, Docker Engine 입장에서는 '상태를 측정하는 기능'이지 '복구 정책'이 아니에요. 그래서 autoheal 사이드카, Swarm의 task 관리, 또는 별도 배포 에이전트처럼 unhealthy 이벤트를 보고 실제 재시작을 수행하는 주체가 필요해요.

  • digest pinning은 재현 가능한 배포를 위한 장치예요. 태그는 사람이 읽기 좋은 이름일 뿐이고 언제든 같은 이름으로 다른 이미지가 올라올 수 있거든요. 운영 환경에서 같은 버전을 배포했다고 말하려면 태그보다 @sha256 digest가 훨씬 강한 기준이 돼요.

  • Docker socket은 관리 자동화에 편하지만 권한 경계가 매우 얇아요. socket을 가진 컨테이너가 Docker API로 호스트를 건드릴 수 있기 때문에, 에이전트 구조를 택할 때도 rootless Docker나 socket proxy처럼 피해 범위를 줄이는 설계가 같이 따라와야 해요.

이 글의 핵심은 'Compose가 장난감이냐'가 아니라 'Compose가 안 해주는 운영 업무를 누가 할 거냐'임. 작은 서비스일수록 Kubernetes를 들이기 부담스러운데, 그렇다고 Compose를 아무 설정 없이 굴리면 장애는 대부분 새벽에 한 번씩 배움 비용으로 찾아옴.

댓글

댓글

댓글을 불러오는 중...

devops

클라우드플레어, AI 에이전트가 계정 만들고 도메인 사고 배포까지 하게 열어줌

클라우드플레어가 Stripe Projects와 함께, 코딩 에이전트가 사용자 대신 클라우드 계정 생성, 유료 구독 시작, 도메인 구매, API 토큰 발급, 프로덕션 배포까지 처리하는 흐름을 공개했어. 핵심은 OAuth, OIDC, 결제 토큰화를 조합해 사람의 대시보드 조작과 카드 입력을 줄이고, 에이전트를 배포 주체로 정식 취급하는 새 프로토콜임.

devops

삼성SDS 토큰증권부터 위버스 AI 상담까지, 국내 클라우드 업계 업데이트 모음

국내 클라우드 업계 소식 네 건을 묶은 기사야. 삼성SDS는 한국예탁결제원 토큰증권 플랫폼 운영 구축을 맡았고, 보난자랩은 OCI 전환으로 비용을 50% 줄였으며, 위버스는 구글 클라우드 기반 대화형 AI로 245개국 팬 문의를 처리했고, 스푼랩스는 일레븐랩스 음성 AI로 오디오 콘텐츠 제작 기간을 수개월에서 수시간으로 줄였어.

devops

보난자랩, OCI로 옮기고 클라우드 비용 50% 줄임

디지털자산 데이터 업체 보난자랩이 오라클 클라우드 인프라스트럭처로 이전한 뒤 클라우드 비용을 약 50% 줄였다고 밝혔어. 실시간 가격, 거래 데이터, 온체인 데이터, 위험 지표를 API와 웹뷰로 제공하는 서비스라서 비용 절감과 확장성 확보가 꽤 직접적인 이슈임.

devops

으뜸정보기술과 다온플레이스, 클라우드·AI 사업 확대 위해 손잡았다

클라우드 전문 기업 으뜸정보기술이 AI 솔루션 기업 다온플레이스와 클라우드 및 AI 기반 사업 확대를 위한 전략적 파트너십을 맺었다. 양사는 AI 솔루션 개발, 클라우드 MSP 서비스, 공동 판매, 신규 사업 발굴을 함께 추진할 계획이다.

devops

소프트스퀘어드, 개발팀도 클라우드처럼 쓰는 ‘B2B WaaS’ 인증 받았다

소프트스퀘어드의 그릿지가 KACI로부터 B2B WaaS 클라우드 서비스 확인서를 받았다. 개발자 매칭이나 외주를 넘어 개발팀 구성, 프로젝트 운영, 품질관리, 정산, 리포팅까지 묶어 제공하는 워크포스 클라우드 모델로 인정받았다는 내용이다. 회사는 여기에 클로드, 커서 같은 AI 개발 도구 운영 관제까지 붙여 개발 AI MSP 시장으로 확장하려 한다.