본문 바로가기
클라우드 Cloud/Docker

도커 리눅스 비교 (Docker 컨테이너 네트워크 격리의 원리)

by 비타민찌 2025. 9. 17.
728x90

도커란, 결국 하나의 리눅스 커널 위에서

여러 개의 격리된 실행 환경을 제공하는 기술입니다.

 

docker run 한 줄로 띄우는 컨테이너도 사실

리눅스 내부에서 이미 존재하던 기능들이 자동으로 설정된 결과물인 것이죠.

 

이번 글에서는 이러한 과정을

직접 리눅스 명령어로 따라 해보며,

Docker가 컨테이너를 띄울 때

어떤 네트워크 동작을 수행하는지 확인해 보겠습니다.

 

리눅스 네임스페이스(Network Namespace), 브리지(Bridge), NAT 기능들을 수동으로 설정하면서,

컨테이너 네트워크의 원리를 이해해 봅니다. 🏋🏻‍♀️

 

 

 

1. 리눅스로 컨테이너 네트워크 알아보기

리눅스 네임스페이스 + 브리지 + NAT 실습 목차

 

  1. 한 대의 리눅스에서 2개의 네트워크 네임스페이스(ns1, ns2)를 생성
    • 네임스페이스: 컨테이너처럼 보이는 격리된 네트워크 스택
  2. 각각을 별도 브리지(bridge1, bridge2)에 연결하고, 두 개의 독립 서브넷 구성
    • 브리지: 같은 세그먼트를 구성하는 가상 스위치/게이트웨이
  3. 호스트를 라우터 + NAT 게이트웨이로 삼아 ns1 ↔ ns2 통신 가능하게 만들기
    • 호스트(라우터 역할): ip_forward + NAT로 서브넷 간 패킷 전달

 

 

1. 네임스페이스 생성 및 확인

 

먼저 네임스페이스를 2개 생성합니다.

이름은 ns1, ns2로 하고요.

 

# 네임스페이스 확인
ip netns list

# 네임스페이스 생성
ip netns add ns1
ip netns add ns2

 

 

네임스페이스란 리눅스 커널 기능으로,

프로세스마다 독립적인 네트워크 스택/파일시스템/프로세스 ID 등을 가질 수 있게 해줍니다. (Docker는 컨테이너 실행 시 자동으로 net, pid, mnt, uts, ipc, user 네임스페이스를 생성합니다.)

 

이렇게 네트워크 스택을 격리해서

다음과 같이 독립적인 네트워크 환경을 구성합니다.

 

네임스페이스 생성 및 확인

 

 

생성 후 ip netns list 명령어로

ns1, ns2 네임스페이스 생성 확인해 주세요.

 

 

2. 가상 bridge 생성

bridge 2개(bridge1, bridge2)를 생성합니다.

 

ip link add bridge1 type bridge
ip link add bridge2 type bridge

 

그럼 이렇게 되죠.

 

가상 bridge 생성

 

apt install -y bridge-utils
brctl show

 

brctl show 명령어로

브리지 생성 잘 되었는지 확인해 주고요.

 

 

3. 가상 링크(veth pair) 생성

네임스페이스와 브리지를 잇는 가상 케이블(veth pair)을 생성합니다.

 

ip link add ns1-veth type veth peer name ns1-veth-br
ip link add ns2-veth type veth peer name ns2-veth-br

 

여기까지 다음과 같은 상황입니다.

 

 

ns1-veth가 그림에서 위의 초록색,

ns1-veth-br이 아래 초록색에 해당합니다.

(참고로 그림에서 위아래는 상관없습니다)

 

 

4. 네임스페이스와 브리지 연결

아래 명령어로 veth의 한쪽 끝은 네임스페이스(ns1, ns2)로, 다른 한쪽 끝은 브리지로 이동하게 합니다.

 

ip link set ns1-veth netns ns1
ip link set ns2-veth netns ns2

ip link set ns1-veth-br master bridge1
ip link set ns2-veth-br master bridge2

 

 

여기까지 다음과 같은 상황입니다.

 

        ns1                            ns2
     ┌─────────┐                   ┌─────────┐
     │ ns1-veth│                   │ ns2-veth│
     └────┬────┘                   └────┬────┘
          │                            │
          │                            │
   ns1-veth-br                    ns2-veth-br
          │                            │
     ┌────┴────┐                   ┌────┴────┐
     │ bridge1 │                   │ bridge2 │
     └─────────┘                   └─────────┘

 

 

5. IP 주소 설정 및 인터페이스 활성화

아래 명령어로 네임스페이스와 브리지 각각에 IP를 할당해 줍니다.

 

ip netns exec ns1 ip addr add 10.10.10.10/24 dev ns1-veth
ip netns exec ns2 ip addr add 20.20.20.20/24 dev ns2-veth
ip addr add 10.10.10.1/24 dev bridge1
ip addr add 20.20.20.1/24 dev bridge2

ip link set bridge1 up
ip link set bridge2 up
ip link set ns1-veth-br up
ip link set ns2-veth-br up
ip netns exec ns1 ip link set ns1-veth up
ip netns exec ns2 ip link set ns2-veth up

 

현재 네트워크 구성은 아래와 같습니다.

 

 ns1(netns)                       ns2(netns)
 ┌───────────────┐               ┌───────────────┐
 │ ns1-veth      │               │ ns2-veth      │
 │ 10.10.10.10/24│               │ 20.20.20.20/24│
 └──────┬────────┘               └──────┬────────┘
        │                                │
   ns1-veth-br                      ns2-veth-br
        │                                │
 ┌──────┴────────┐               ┌──────┴────────┐
 │ bridge1       │               │ bridge2       │
 │ 10.10.10.1/24 │               │ 20.20.20.1/24 │
 └───────────────┘               └───────────────┘

 

 

6. 통신 확인

ip netns exec ns1 ping 10.10.10.1 -c 5   # OK
ip netns exec ns2 ping 20.20.20.1 -c 5   # OK
ip netns exec ns1 ping 20.20.20.20 -c 5  # X
ip netns exec ns2 ping 10.10.10.10 -c 5  # X

 

 

위 명령어로 통신 확인을 해봅니다.

 

  • ns1 → bridge1(10.10.10.1) 통신 가능
  • ns2 → bridge2(20.20.20.1) 통신 가능
  • ns1 ↔ ns2 간 직접 통신은 불가능 (서브넷이 다르고 라우팅이 없기 때문)

 

게이트웨이까지는 되는데,

ns1 ↔ ns2 간에는 안되는 상황임을 알 수 있습니다.

 

 

7. 라우팅 테이블 추가

ns1, ns2에서 게이트웨이를 추가합니다.

 

ip netns exec ns1 ip route add default via 10.10.10.1
ip netns exec ns2 ip route add default via 20.20.20.1

 

 

위 명령어로 ns1, ns2가 게이트웨이(bridge1/bridge2)를 통해 다른 네트워크로 나가도록 설정합니다.

 

  • ns1의 기본 경로: default → 10.10.10.1
  • ns2의 기본 경로: default → 20.20.20.1

 

이제 ns1과 ns2는 자신이 모르는 목적지 패킷을 각각의 브리지(게이트웨이)로 전달하게 됩니다.

 

 

8. IP 포워딩 허용

아래 명령어로 리눅스 커널의 IP 포워딩 기능(리눅스가 패킷을 받았을 때 원래 목적지가 자기 자신이 아니라 다른 네트워크에 있는 경우, 그 패킷을 그냥 버리지 않고 다른 인터페이스로 포워딩 해주는 기능)을 켜는 설정을 합니다.

 

sysctl -w net.ipv4.ip_forward=1

 

 

본인에게 온 IP가 아니어도

패킷을 버리지 않도록 설정이죠.

 

 

9. NAT 설정

호스트에서 NAT을 설정해 두 서브넷이 서로 통신할 수 있도록 합니다.

 

iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 20.20.20.0/24 -j MASQUERADE

 

 

10.10.10.0/24 네트워크에서 나가는 모든 패킷의 소스 IP를 호스트 IP로 바꿔주는 NAT 규칙을 추가합니다.

집에서 여러 기기가 사설 IP(192.168.x.x)를 쓰지만,

공유기를 통해 나갈 때는 공인 IP 하나로 보이는 것과 같은 원리죠.

 

iptables -t nat -L -n -v 명령어로 결과를 확인합니다.

 

 

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source          destination
    0     0 MASQUERADE all  --  *      *       10.10.10.0/24   0.0.0.0/0
    0     0 MASQUERADE all  --  *      *       20.20.20.0/24   0.0.0.0/0

 

 

최종 결과로, ns1 ↔ ns2 통신이 가능해지고

호스트가 라우터 + NAT 게이트웨이 역할을 하게 되었습니다.

 

 

리눅스, Docker 비교

리눅스
Docker 내부
ns1, ns2
(netns 네임스페이스)
컨테이너 네트워크 네임스페이스
veth pair
컨테이너 NIC ↔ docker0 연결선
bridge1/bridge2
docker0 브리지
ip_forward, NAT
Docker 데몬이 자동 설정하는 iptables 규칙.


컨테이너 간, 외부와 통신이 가능하게 되는 원리.

 

 

이번 포스팅에서는 '리눅스 한 대'에서

네트워크 격리와 연결을 직접 다뤄보며

컨테이너 네트워크가 어떻게 구현되는지를 확인했습니다.

 

Docker나 Kubernetes가 자동으로 해주는

네트워크 세팅을 직접 눈으로 확인할 수 있었죠.

 

다음 포스팅에서는 실제로 도커를 설치해서

이번 포스팅처럼 수동으로 설정했을 때와 비슷하게 네트워크가 격리가 되어있는지 확인해 보겠습니다.

 

 

 

참고

https://blog.naver.com/ghdalswl77/224002500768

728x90

댓글