Container
Container는 애플리케이션과 그 실행 의존성을 하나의 격리된 실행 단위로 묶는 방식입니다. 겉으로는 작은 가상 머신처럼 보이지만, 실제로는 호스트 커널을 공유하면서 프로세스, 파일시스템, 네트워크를 분리해 실행합니다.
▶아키텍처 다이어그램
🔍 구조 다이어그램점선 애니메이션은 데이터 또는 요청의 흐름 방향을 나타냅니다
같은 애플리케이션도 개발자 노트북과 서버의 OS 패키지, 라이브러리 버전, 환경 변수 차이 때문에 실행 결과가 달라지곤 합니다. 수동으로 서버마다 환경을 맞추는 방식은 반복될수록 오차가 쌓이고, 장애가 나면 '어느 서버만 왜 다른가'를 추적하는 비용이 커집니다. 배포 속도를 높이려 할수록 환경 불일치가 가장 먼저 발목을 잡습니다.
초기의 서버 배포는 운영체제 위에 패키지를 직접 설치해 상태를 맞추는 식이었습니다. 이후 가상 머신이 등장해 환경 재현성은 좋아졌지만, 게스트 OS까지 포함하니 이미지가 무겁고 시작 속도도 느렸습니다. 컨테이너는 운영체제 전체를 복제하지 않고도 애플리케이션 경계를 나누고 싶다는 압력에서 자리잡았습니다.
컨테이너는 이미지에서 읽기 전용 레이어를 가져오고, 실행 시점에는 그 위에 얇은 쓰기 레이어를 얹습니다. 프로세스는 namespace로 서로의 PID와 네트워크를 보지 못하고, cgroup은 CPU와 메모리 사용량을 제한합니다. 그래서 컨테이너는 독립된 서버처럼 보이지만 실제로는 같은 커널 위에 놓인 격리된 프로세스 묶음입니다.
컨테이너와 Linux namespace·cgroup은 자주 함께 언급되지만 역할이 다릅니다. 컨테이너는 개발자와 운영자가 다루는 실행 단위이고, namespace·cgroup은 그 격리를 가능하게 하는 커널 메커니즘입니다. 컨테이너를 이해하려면 '무엇을 얻는가'와 '그게 커널에서 어떻게 만들어지는가'를 구분해서 보는 편이 정확합니다.
실무에서 컨테이너는 웹 API, 비동기 워커, 배치 잡처럼 배포 단위가 분명한 프로세스를 감싸는 데 가장 자주 쓰입니다. 이때 로그나 일시적인 캐시는 컨테이너 안에서 소모해도 되지만, 업로드 파일이나 데이터베이스 파일처럼 교체 후에도 남아야 하는 상태는 볼륨이나 외부 저장소로 빼 두어야 합니다. 결국 컨테이너를 잘 쓰는 핵심은 무엇을 이미지로 다시 만들 수 있고 무엇을 컨테이너 밖에 남겨야 하는지 배포 시점마다 구분하는 데 있습니다.