이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.
공부 › 아키텍처와 운영 › 배포와 운영
컨테이너와 가상 머신
컨테이너는 왜 가볍고 빨리 뜨나
같은 애플리케이션을 여러 개 띄울 때, 가상 머신은 인스턴스마다 운영체제를 통째로 올리고 컨테이너는 호스트의 커널을 함께 씁니다. 방식과 개수를 바꿔 가며 올라가는 것들과 메모리 사용을 비교하고, 컨테이너에 메모리 제한을 걸었을 때 무슨 일이 생기는지도 보세요.
문서·표준 대조 · Docker와 리눅스 커널 문서
이 실습에 나오는 개념
- 컨테이너와 이미지
- 컨테이너는 애플리케이션과 그 실행에 필요한 것들을 묶어, 호스트 운영체제의 커널을 공유하면서 다른 프로세스와 격리된 환경에서 실행하는 기술이다. 이미지는 컨테이너를 만드는 데 쓰는 읽기 전용 템플릿으로 애플리케이션과 라이브러리, 설정이 들어 있다. 같은 이미지로 실행하면 실행 환경의 차이로 생기는 문제를 크게 줄인다.
- 컨테이너와 가상 머신의 차이
- 가상 머신은 하드웨어를 가상화해 그 위에 운영체제 전체를 따로 설치해 실행한다. 컨테이너는 호스트의 운영체제 커널을 공유하고 프로세스만 격리한다. 그래서 컨테이너는 가상 머신보다 가볍고 빨리 시작되지만 격리 수준은 가상 머신이 더 높다.
- 네임스페이스와 cgroups
- 컨테이너를 구현하는 리눅스 커널의 기능이다. 네임스페이스는 프로세스가 볼 수 있는 범위(프로세스 목록, 네트워크, 파일 시스템 등)를 분리해 서로 독립된 환경처럼 보이게 한다. cgroups는 프로세스 그룹이 사용할 수 있는 CPU와 메모리 같은 자원의 양을 제한한다.
이렇게 바꿔 보세요
- 처음 설정으로 — 컨테이너 3개. 호스트의 커널을 함께 씁니다.
- 같은 것을 가상 머신으로 — 인스턴스마다 운영체제가 하나씩 더 올라갑니다.
- 6개로 늘리면 — 가상 머신마다 운영체제(게스트 커널)가 하나씩 더 뜹니다.
- 컨테이너 6개 — 애플리케이션이 쓰는 만큼만 늘어납니다.
- 메모리 제한을 256MB로 — 애플리케이션이 400MB를 쓰려다 강제 종료됩니다.
처음 설정으로 실행하면
- 물리 서버 한 대에 호스트 운영체제가 떠 있습니다. 여기에 애플리케이션 인스턴스 3개를 서로 격리해서 띄우려 합니다.
- 컨테이너 런타임은 가상 하드웨어를 만들지 않습니다. 호스트 커널의 기능으로 프로세스를 격리해서 실행할 뿐입니다.
- 컨테이너 1: 이미지(애플리케이션과 실행에 필요한 파일 묶음)를 읽기 전용으로 깔고, 그 위에서 프로세스를 시작합니다. 운영체제를 부팅하지 않으므로 프로세스 하나를 띄우는 시간이면 됩니다. 같은 이미지는 컨테이너끼리 공유합니다.
- 컨테이너 1: 실행 중입니다. 네임스페이스 덕분에 이 프로세스는 자기만의 파일 시스템, 네트워크, 프로세스 목록을 가진 것처럼 보이지만, 실제로는 호스트 커널 위의 평범한 프로세스입니다.
- 컨테이너 2: 이미지(애플리케이션과 실행에 필요한 파일 묶음)를 읽기 전용으로 깔고, 그 위에서 프로세스를 시작합니다. 운영체제를 부팅하지 않으므로 프로세스 하나를 띄우는 시간이면 됩니다. 같은 이미지는 컨테이너끼리 공유합니다.
- 컨테이너 2: 실행 중입니다. 네임스페이스 덕분에 이 프로세스는 자기만의 파일 시스템, 네트워크, 프로세스 목록을 가진 것처럼 보이지만, 실제로는 호스트 커널 위의 평범한 프로세스입니다.
- 컨테이너 3: 이미지(애플리케이션과 실행에 필요한 파일 묶음)를 읽기 전용으로 깔고, 그 위에서 프로세스를 시작합니다. 운영체제를 부팅하지 않으므로 프로세스 하나를 띄우는 시간이면 됩니다. 같은 이미지는 컨테이너끼리 공유합니다.
- 컨테이너 3: 실행 중입니다. 네임스페이스 덕분에 이 프로세스는 자기만의 파일 시스템, 네트워크, 프로세스 목록을 가진 것처럼 보이지만, 실제로는 호스트 커널 위의 평범한 프로세스입니다.
실행 결과
- 컨테이너는 커널을 공유하므로 가볍고 빨리 뜹니다. 대신 격리는 가상 머신보다 약하고, 호스트와 같은 종류의 커널에서만 동작합니다. "보이는 범위"는 네임스페이스가, "쓸 수 있는 자원량"은 cgroups가 나눕니다.
코드
# Dockerfile
FROM eclipse-temurin:21-jre # JRE가 들어 있는 기본 이미지
COPY build/libs/app.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
# 실행 (컨테이너 3개)
$ docker run -d --memory=1024m my-app:1.0
이 모형의 전제
메모리 수치(게스트 운영체제 약 1GB, 애플리케이션 약 400MB)와 부팅 시간은 차이의 방향을 보이기 위한 대략적인 예시이며 실제 값은 구성에 따라 크게 다릅니다. 컨테이너가 호스트 커널을 공유하고 네임스페이스와 cgroups로 격리된다는 점, 제한을 넘으면 커널이 프로세스를 종료한다는 점은 Docker와 리눅스 커널 문서의 설명을 따랐습니다. 윈도우나 맥의 Docker Desktop은 내부에 리눅스 가상 머신을 하나 두고 그 안에서 컨테이너를 돌립니다.
앞 실습: 배포 전략 · 다음 실습: 쿠버네티스 자가 치유