[공부정리] Docker의 흥미로운 사실들

jeyong·2024년 11월 3일
0

공부 / 생각 정리  

목록 보기
120/120


이번 게시글에서는 Docker를 공부하며 흥미롭게 접한 내용을 정리하고자 한다. 흔히 볼 수 있는 내용보다는 흥미로운 사실들만 모아 작성했으므로, 다소 가독성이 떨어질 수 있다.

1. 아키텍처

Docker는 생각보다 복잡한 구조로 이루어져 있다. 많은 사람들이 이 사실을 모른다는 것은 그만큼 기술적으로 잘 설계되어 있다는 의미일 것이다. 이제 Docker의 구조에 대해 알아보자.

  • 간단히 말해, docker CLI로 보낸 요청을 docker daemon이 docker.sock을 통해 수신하고, 이를 기반으로 containerd를 활용해 컨테이너를 생성 및 관리한다. 즉, docker daemon이 컨테이너를 직접 생성하는 것이 아니라, containerd가 컨테이너 생성을 담당하는 구조이다.
  • containerd(고수준 런타임)는 컨테이너 런타임을 관리하는 서비스로, Docker는 이 런타임으로 runc를 사용한다. runc(저수준 런타임)는 리눅스의 cgroupnamespace를 이용해 실제로 컨테이너를 생성하는 역할을 한다.
  • containerdrunc가 직접적으로 통신하면 containerd 종료 시 runc도 함께 종료되는 문제가 발생할 수 있으며, 이는 실행 중인 컨테이너에 영향을 미칠 수 있다. 이를 방지하기 위해 shim이 도입되었으며, shimrunc가 독립적으로 작동하도록 지원한다.
  • docker daemon은 노는 건가?

    당연히 아니다. 컨테이너 생성 기능을 제외하고도 container build, security, volume, networking, secrets, orchestration, distributed state와 같은 기능을 담당하고 있다. 이러한 이유로 Kubernetes에서 Docker를 컨테이너 런타임으로 사용하기엔 다소 무거운 선택일 수 있다.

  • cgroup? namespace?

    cgroup은 특정 프로세스가 사용할 수 있는 자원을 제한하고, namespace는 프로세스의 접근 범위를 격리하는 리눅스 커널 기술이다. 이런 기술을 개발하거나 이를 통해 가상화 기술을 발전시킨 사람들은 정말 대단하다고 생각한다.

  • 표준 준수 (OCI)?

    컨테이너 런타임은 OCI(Open Container Initiative) 표준을 준수해 다양한 도구와 호환되도록 설계된다. 이는 컨테이너 이미지가 어디에서 생성되었든 같은 방식으로 실행될 수 있게 보장한다.

  • 왜 이런 복잡한 구조를?

    하나의 프로세스가 다른 프로세스의 영향을 받지 않도록 책임을 분리한 구조이다. 실제로 docker daemon을 재시작해도 containerd와 컨테이너들은 계속 실행되고, containerd를 재시작하더라도 이미 실행 중인 runc 프로세스는 shim을 통해 독립적으로 유지된다. runc는 container 생성을 완료하면 종료되며, shim이 그 후 관리를 이어받기 때문이다.

이 외에도 Kubernetes와 docker-shim에 대한 흥미로운 내용이 많지만, Docker의 내용을 벗어나기 때문에 다음에 다루어 보겠다.

2. 네트워크

Docker 네트워크 구조는 실생활의 네트워크 구조와 비슷하다. 그래서 실생활의 네트워크 구조를 먼저 이해하는 것이 좋다.

간단하게 설명하자면, 사설 IP에서 외부 서버로 접속할 때는 NAT 기술을 이용해 공인 IP로 변환하여 접속한다. 반대로 외부 서버에서 사설 IP로 접속하고 싶을 때는 포트 포워딩 기술을 이용해 공인 IP와 사설 IP를 매핑해 전달한다.

Docker 네트워크는 외부 서버와 컨테이너의 연결을 위해 소프트웨어 기반 라우터를 구현한 것과 비슷하다.

컨테이너를 실행하면 veth라는 가상 네트워크 인터페이스가 생성되고, 이를 컨테이너 내부의 eth0에 연결한다. veth는 게이트웨이 역할을 하는 브리지 네트워크에 연결되며, 만약 브리지 네트워크를 지정하지 않았다면 기본 브리지 네트워크인 docker0에 연결된다. docker0를 실생활의 라우터와 같은 역할로 이해할 수 있다.

  • 포트 포워딩 기술은?

    NAT으로 내부에서 외부로의 연결은 가능하지만, 외부에서 컨테이너로의 접속을 위해서는 포트 포워딩이 필요하다. 이를 위해 docker0와 같은 브리지 네트워크가 iptables에 컨테이너 IP 주소를 기록하고, 외부 요청을 해당 컨테이너로 전달하는 방식으로 작동한다.

  • 컨테이너 이름으로 통신은?

    같은 브리지에 속한 네트워크라면 컨테이너 이름만으로 통신할 수 있다. 이는 Docker가 브리지 내부에 DNS를 띄워 컨테이너 이름과 주소를 기록하기 때문이다. 단, 기본 브리지 네트워크인 docker0는 DNS 기능을 지원하지 않는다.

3. 플랫폼

종종 Docker 이미지가 어디서나 작동할 것이라고 오해할 수 있는데, 이는 사실이 아니다. Docker 컨테이너도 하나의 프로세스이기 때문에 이를 실행하는 하드웨어에 종속적이다.

도커 허브에서는 이미지 아래에 작동 가능한 아키텍처를 명시한다. 개발 환경과 배포 환경의 아키텍처가 다를 경우 빌드 시 --platform 옵션을 지정해야 한다. 다행히도 이미지를 pull 받을 때는 플랫폼 환경에 따라 적절한 이미지를 자동으로 지정해준다.

이런 불편함을 해결하기 위해 Docker는 최근 buildx라는 멀티플랫폼 빌드를 지원하기 시작했다.

Docker buildx는 한 번의 명령어로 여러 플랫폼을 지원하는 이미지를 생성하는 것이다.

4. Off The Record

Docker가 출시되면서 정말 많은 것이 바뀌었다. 도커 첫 시연 영상을 보면 알 수 있듯이, 정말 충격적인 기술이다.

하지만 그렇다고 VM 기술이 나쁜 것은 아니다. 하이퍼바이저 기반의 VM 기술은 가상화에 비해 무겁지만, Docker는 프로세스를 분리하고, VM은 운영체제를 분리하기 때문에 서로 다른 환경을 완벽히 분리한다.

따라서 둘 다 장단이 있는 기술이고, 상황에 맞게 사용할 수 있도록 편협한 시각을 가지지 않는 것이 중요하다고 생각한다.

profile
노를 젓다 보면 언젠가는 물이 들어오겠지.
post-custom-banner

0개의 댓글