부트캠프에서 Docker를 배우다가 의문점이 들어서 작성하게 되었습니다.
작년에 VirtualBox라는 가상머신을 매우 많이 사용했는데, 그래서 Docker의 동작 방식이 더 궁금했던 것 같습니다.
길어서 1편과 2편으로 나눴습니다.
< 질문 1: 커널을 공유한다는 것이 정확히 어떤 의미인가? docker와 기존 OS에서 실행된 각각의 프로세스가 커널에서는 구별되지 않고 취급되는 것인가? >
Docker 컨테이너는 호스트 OS의 커널을 그대로 사용한다. Docker 자체가 커널 레벨에서는 ‘프로세스’이다. 또한 Namespace와 sgroups같은 기술을 이용해서 독립된 OS처럼 “격리된 공간”을 만들어낸다.
여기서 “격리된 공간”이라는 말은 컨테이너 내부의 입장이다.
- 그러면 Docker와 그 안의 프로세스들은 커널 입장에서는 하나의 프로세스인가? 그러면 Docker에서 실행한 프로세스의 스케줄링은 어떻게 되는거지…?
Docker 데몬은 하나의 프로세스이다. 그리고 그 컨테이너 안에서 실행되는 각각의 프로세스도 커널에 각각 개별적으로 등록되어서 관리된다.
그렇기 때문에 Docker 컨테이너 안의 프로세스들은 커널 입장에서 일반 리눅스 프로세스와 완전히 동일하게 취급된다.
→ 모든 리소스 경쟁을 호스트 OS의 프로세스들과 같이 동일한 조건에서 한다. 즉, Docker를 쓸 때 성능상 불이익은 없다. (가상 머신의 경우 하이퍼바이저 위에서 별개의 OS(커널)가 돌아가는 구조이기 때문에 성능상 불이익이 있을 수 있다.) - 그러면 Windows는 WSL2에서 docker를 돌리는 걸로 알고 있는데 스케줄링이 어떻게 되는거지?
WSL2는 Windows Hyper-V 위에서 돌아가는 가상머신이다. 즉, Windows에서 돌아가는 docker는 사실상 Windows와 커널을 공유하는 것이 아니라 가상머신에서 돌아가는 것이다. (하지만 일반적인 가상머신과 다르게, WSL2 기반 Docker는 거의 체감되지 않을 정도로 빠르다고 한다.) - 격리된 공간이 어떻게 만들어지는가?
Docker는 리눅스의 namespace와 cgroups를 통해 “격리된 공간”을 만든다. 현재 커널 위에서 “보이는 범위”와 “사용 가능한 자원”을 제한함으로써 별도의 컴퓨터처럼 보이게 만든다.
namespace로 보이는 범위를 제한하고, sgroups로 사용 가능한 자원을 제한한다.- ”보이는 범위를 제한한다”는 것이 무슨 뜻인가?
컨테이너 내부에서 밖이 안 보이게 하는 것이다.
실제 호스트에서 PID와 별개로 내부에서는 PID가 1번부터 다시 시작한다.
그 외에 네트워크 호스트 이름, 네트워크 인터페이스, 파일시스템 루트 경로 등도 컨테이너 내부에서 완전히 독립적으로 보인다. - ”사용 가능한 자원을 제한한다”는 것이 무슨 뜻인가?
프로세스가 사용하는 리소스의 양을 제한하는 기능을 말한다.
→ 커널이 프로세스의 리소스 사용량을 감시해서 초과 시에 제한한다.
제한은 도커 컨테이너 내부의 프로세스들의 총 사용량에 대해서 제한을 한다.
⇒ 호스트 OS의 프로세스와 동일한 조건에서 리소스 경쟁을 하지만, 제한된 환경에 따른 자연스러운 성능 감소는 존재한다.
- ”보이는 범위를 제한한다”는 것이 무슨 뜻인가?
< 질문 2: docker-compose의 이미지들은 하나의 컨테이너가 되나? 그러면 사용자 영역도 공유하나? >
docker-compose의 여러 이미지들은 각각 서로 다른 컨테이너가 된다.
(docker-compose의 services
블록 수 = 컨테이너 수)
하지만 네트워크로 컨테이너간 연결이 가능하다.
⇒ 즉, 당연히 사용자 영역도 공유하지 않는다.
네트워크로 연결한다는 것이 어떤 의미인가?
docker-compose는 서비스를 실행할 때 자동으로 bridge 네트워크를 하나 생성하고 그 안에 모든 컨테이너를 같은 네트워크에 넣는다.
만약 컨테이너에서 다른 컨테이너로 접근하려고 한다면 서비스 이름과 그 서비스의 내부 포트 번호로 접근할 수 있다.services: mysql: image: mysql:8.0 # restart: always volumes: - ./my.cnf:/etc/mysql/conf.d/my.cnf - ./sql:/docker-entrypoint-initdb.d - ./db/mysql/data:/var/lib/mysql ports: - "4444:3306" environment: - MYSQL_ROOT_PASSWORD=likelion - MYSQL_DATABASE=likelion - MYSQL_USER=likelion - MYSQL_PASSWORD=likelion adminer: image: adminer # restart: always ports: - "3080:8080"
이 상황에서 adminer는 mysql에
mysql:3306
로 접근 가능하다.- 위의 예시에서 adminer가 mysql에 접근할 수 있는 방법은?
mysql:3306
→ 같은 Docker bridge 네트워크로 요청 (따로 설정하지 않는 이상 MySQL은 3306포트로 오는 요청을 받는다.)
→ 내부 DNS(mysql
)와 컨테이너 포트(3306
)으로 직접 연결됨host.docker.internal:4444
→ Docker 컨테이너에서 호스트의 포트로 접속하는 방법.
- bridge 네트워크가 무엇인지?
bridge 네트워크는 docker가 기본적으로 제공하는 가상 네트워크이다. 호스트 시스템과는 분리된 독립된 IP 대역을 가진다. 이를 통해 컨테이너들까지 서로 통신할 수 있게 해준다.
일종의 전용 스위치가 설치된 내부 네트워크라고 볼 수 있다. 컨테이너들이 이 스위치에 연결되어서 독립된 IP 기반으로 서로 패킷을 주고받으며 통신할 수 있다.
docker-compose 실행 시 자동으로 컨테이너들을 같은 bridge 네트워크에 연결시킨다.
그리고 외부와의 통신을 위해ports
설정으로 포트를 여는 것이다.- 근데 bridge 네트워크로 통신할 때도 서비스의 내부 포트 번호를 알아야 하는데, 꼭 외부와의 통신을 위해
ports
설정이 필요한 건 아니지 않나?ports
는 외부(호스트OS)와의 통신을 위해 하는 설정이 맞다.ports
설정이 없어도 mysql이 어떤 포트로 리슨 중인지 안다면 거기로 요청을 보내면 된다.
- 근데 bridge 네트워크로 통신할 때도 서비스의 내부 포트 번호를 알아야 하는데, 꼭 외부와의 통신을 위해
- 위의 예시에서 adminer가 mysql에 접근할 수 있는 방법은?
< 질문 3: docker에서 따로 OS를 설정하지 않아도 서비스가 구동이 되는데, 어떤 OS에서 돌아가는 것인가? (현재 Windows면 Windows 커널을 공유하는 것인가? 아니면 wsl linux를 공유하는 것인가?) >
컨테이너 이미지는 일반적으로 리눅스 기반의 사용자 공간(user space) 을 포함하고 있으며, 리눅스 커널에서 제공하는 기능(namespace, cgroups 등)을 필요로 한다.
예를 들어 MySQL 이미지를 쓴다면, 그 안에는 리눅스 기반의 사용자 공간이 들어 있다.
이러한 컨테이너는 리눅스 커널 위에서만 실행 가능하기 때문에,Windows 환경에서는 리눅스 커널을 대신 제공해 줄 무언가가 필요하다.
→ 그래서 Windows에서는 WSL2를 사용한다.
WSL2는 경량 리눅스 VM이며, Docker Desktop은 이를 자동으로 설치하고 활용한다.
즉, Windows에서는 Docker가 WSL2 위에서 실행되는 리눅스 환경의 커널을 공유하는 구조다.
- 리눅스나 Mac에서 docker를 실행하면?
- 리눅스에서 docker 실행 시
리눅스는 docker의 고향이다. 따라서 리눅스에서는 WSL2나 VM 없이 곧바로 호스트 리눅스 커널 위에서 컨테이너가 실행된다.
즉, 호스트 리눅스 커널을 그대로 공유하며, 거의 모든 자원이 native 수준이다. - Max에서 docker 실행 시
Mac의 커널은 Darwin 기반이다. 또한 Mac은 Windows의 WSL2처럼 리눅스 커널 기능을 직접 제공하지 않는다.
→ 그래서 Docker Desktop for Mac은 내부적으로 경량 리눅스 VM을 실행하고, 그 위에 Docker가 올라간다.
→ Docker를 리눅스에서 실행하는게 아니면, 사실상 가상 머신 위에서 돌리는 것이다.- 그러면 Docker Desktop for Mac이 아니라 CLI로 설치하면 어떻게 되는거지?
CLI로 Docker를 설치하고 쓰려면 VM 기반 환경을 직접 구성해야 한다.
- 그러면 Docker Desktop for Mac이 아니라 CLI로 설치하면 어떻게 되는거지?
- 리눅스에서 docker 실행 시
- 근데 다른 OS 기반은 없나?
Windows 컨테이너도 있다. 하지만 정상적으로 작동하는 Docker 이미지들이 대부분 리눅스 기반이다.
→ 리눅스 컨테이너가 표준임.
'스터디 > 백엔드' 카테고리의 다른 글
도커(Docker) 용어 이해 및 의문점 (0) | 2025.04.07 |
---|---|
[백엔드] 쿠키(Cookie)란? (0) | 2024.12.13 |