Docker

[Docker] 도커 볼륨 / 도커 네트워크 구조

sian han 2023. 2. 5. 19:44

▶ 도커 볼륨

도커 이미지로 컨테이너를 생성하면 이미지는 읽기 전용이 된다. 이미 생성된 이미지는 어떤 경우로도 변경되지 않으며, 컨테이너 계층에 원래 이미지에서 변경된 파일시스템 등을 저장한다. 컨테이너를 삭제하면 ? 컨테이너 계층에 저장되어있는 DB 정보도 삭제된다. 도커 볼륨은 이를 방지하기 위해 컨테이너의 데이터를 영속적 데이터로 활용할 수 있는 방안 중 하나이다.

 

▶ 도커 볼륨 활용 방안

1. 호스트와 볼륨을 공유한다.

2. 볼륨 컨테이너를 사용한다.

3. 도커과 관리하는 볼륨을 생성한다.

 

이처럼 컨테이너가 아닌 외부에 데이터를 저장하고 컨테이너는 그 데이터로 동작하도록 설계하는 것을 stateless 하다고 말한다. 컨테이너 자체는 상태가 없고 상태를 결정하는 데이터는 외부로부터 제공받는다. 컨테이너가 삭제되도 데이터는 보존되므로 stateless 한 컨테이너 설계는 바람직하다.

 

 

▷  1. 호스트 볼륨 공유

mysql 데이터베이스 컨테이너와 워드프레스 웹 서버 컨테이너를 생성한다

//mysql DB 컨테이너
# docker run -d  \
--name wordpredssdb_hostvolume\
-v : /home/wordpress_db:/var/lib/mysql
mysql:5.7
//워드프레스 컨테이너
# docker run -d \
--name wordpress_hostvolume \
--link wordpress_db_hostvolume:mysql \
-p 80 \
wordpress

 

워드 프레스 컨테이너에 -p 옵션으로 컨테이너의 80 포트를 외부에 노출했다.

따라서 docker ps 명령어에서 확인한 wordpress_hostvolume 컨테이너의 호스트 포트로 워드프레스 컨테이너에 접속할 수 있다. 

 

-v : 호스트의 /home/wordpress_db 디렉터리와 컨테이너의 /var/lib/mysql 디렉터리를 공유한다는 뜻이다.

[호스트의 공유 디렉터리]:[컨테이너의 공유 디렉터리]

두 디렉터리는 동기화되는 것이 아니라 완전히 같은 디렉터리이다.

컨테이너의 /var/lib/mysql 디렉터리는 MYSQL 이 DB데이터를 저장하는 기본 디렉터리이다.

 

미리 호스트에 /home/wordpress_db 디렉터리를 생성하지 않았어도 도커가 자동으로 이것을 생성한다. 

파일단위의 공유도 가능하며, 동시에 여러개의 -v 옵션을 사용하는 것이 가능하다.

 

이미지에 원래 존재하던 디렉터리에 호스트의 볼륨을 공유하면 컨테이너의 디렉터리 자체가 덮어씌워진다. 

-v 옵션을 통한 호스트 볼륨 공유는 호스트의 디렉터리를 컨테이너의 디렉터리에 마운트 한다.

 

 

 

 

▷ 2. 볼륨 컨테이너

--volumes-from

컨테이너 생성 시 아래 옵션을 설정하면 -v 또는 --volume 옵션을 적용한 컨테이너의 볼륨 디렉터리를 공유할 수 있다. 

볼륨을 사용하려는 컨테이너에 -v 대신 --volumes-from 옵션을 사용함으로써 볼륨 컨테이너에 연결해 데이터를 간접적으로 공유받는 방식이다.

 

볼륨 직접공유(X)

-v 옵션을 적용한 컨테이너를 통한 공유(O)

 

ex)

# docker run -i -t \
--name volumes_from_container \
--volumes-from volume_overide \

volumes_overide 컨테이너는 호스트와 특정 디렉터리를 공유하고 있으며, 

이 컨테이너를 볼륨 컨테이너로서 volumes_from_container 컨테이너에 다시 공유하는 것이다.

 

여러개의 컨테이너가 동일한 컨테이너에 --volumes-from 옵션을 사용함으로써 볼륨을 공유해 사용할 수 있고,

이런 구조를 활용하면 호스트에서 볼륨만 공유하고 별도의 역할을 담당하지 않는 '볼륨 컨테이너' 로서 활용하는 것이 가능하다.

 

 

 

▷ 3. 도커 볼륨

docker volume

위 명령어를 통해 도커 자체에서 제공하는 볼륨 기능을 활용해 데이터를 보존하는 방법이다.

 

볼륨 생성

docker volume create --name myvolume

 

생성된 볼륨 확인

docker volume ls

 

생성한 볼륨을 사용하는 컨테이너 생성

docker run -i -t --name --name myvolume_container \
-v myvolume:/root/ \
[볼륨의 이름]:[컨테이너의 공유 디렉터리]

호스트와 볼륨을 공유할때 사용한 -v 옵션의 입력 형식과는 다르게 입력해야 한다. 

이 예시에서 생성되는 myvolume_container 컨테이너는 볼륨을 컨테이너의 /root/ 디렉터리에 마운트 하므로 /root 디렉터리에 파일을 쓰면 해당 파일이 볼륨에 저장된다. 

 

# /root/volume

이렇게 /root 디렉터리에 volume 이라는 파일을 생성하고 다른 컨테이너에서 myvolume 볼륨을 사용하면

볼륨을 활용한 디렉터리에 volume 파일이 존재할 것이다.

# docer run -i -t --name myvolume_container2 \
-v myvolume:/root/ \

cat /root/volume

 

 

 


▶ 도커 네트워크

도커는 컨테이너에 내부 IP를 순차적으로 할당하며, 이것은 컨테이너를 재시작할 때마다 변경될 수 있다. 이 과정은 컨테이너를 시작할 때 마다 veth 라는 네트워크 인터페이스를 생성함으로써 이뤄진다. 이렇게 할당된 IP 는 도커가 설치된 호스트 내에서만 쓸 수 있는 IP이기에 외부와 연결되어야한다. 도커는 각 컨테이너에 외부와의 네트워크를 제공하기 위해 컨테이너마다 가상 네트워크 인터페이스를 호스트에 생성하며 이 인터페이스의 이름은 veth 로 시작한다 (virtual eth)

 

▷ veth 로 시작하는 인터페이스

  • veth~ 인터페이스는 컨테이너가 생성될 때 도커 엔진이 자동으로 생성한다.
  • ifconfig 명령어를 통해 현재 실행중인 컨테이너 수 만큼 veth~ 인터페이스가 생성된 것을 확인할 수 있다.
  • veth~ 인터페이스들은 각 컨테이너의 eth0 과 연결되어있다.

▷ docker0 브리지

docker0 브리지는 각 veth~ 인터페이스와 바인딩되어 호스트의 eth0 인터페이스와 이어주는 역할을 한다.

그림설명 :

컨테이너의 eth0 인터페이스는 호스트의 veth~ 인터페이스와 연결. 

veth~ 인터페이스는 docker0 브리지와 바인딩 되어 외부와 통신할 수 있게 된다.

 

▷ 도커 네트워크 기능

따라서 컨테이너를 생성하면 기본적으로 docker0 브리지를 통해 외부와 통신할 수 있는 환경을 사용할 수 있다.

외에 도커에서 기본적으로 쓸 수 있는 네트워크는 어떤 것이 있을까 ?

 

 

도커 네트워크 목록확인

docker network ls

bridge, host, none 네트워크를 확인할 수 있다.

 

 

 

 

▷ bridge 네트워크

  • bridge 네트워크는 172.17.0.x IP 대역을 컨테이너에 순차적으로 할당한다.
  • docker0 브리지와 비슷하게 bridge 네트워크는 docker0 이 아닌 사용자 정의 브리지를 새로 생성해 각 컨테이너에 연결하는 네크워크 구조이다.

 

브리지 네트워크 정보 확인

docker network inspect bridge
"Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },

Config 항목의 subnet 과 gateway 가 다음과 같이 설정되어있다.

 

"Containers": {
            "3ff": {
                "Name": "mysql-container",
                "EndpointID": "",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },

브리지 네트워크를 사용중인 컨테이너 목록을 Containers 에서 확인할 수 있다.

 

 

 

▷ 호스트 네트워크

  • 네트워트를 호스트로 설정하면 호스트의 네트워크 환경을 그대로 쓸 수 있다.
  • 호스트 드라이버의 너트워크는 별도로 생성할 필요 없이 기존의 host 라는 이름의 네트워크를 사용한다.
  • 컨테이너 내부의 애플리케이션을 별도의 포트포워딩 없이 바로 서비스 할 수 있다. 
docker run -i -t --name network_host \
--net host \

--net : 호스트 설정

이렇게 생성된 컨테이너의 내부에서 네트워크 환경을 확인하면 호스트와 같은 것을 확인할 수 있다.

호스트의 이름을 컨테이너가 물려받기 때문에 컨테이너의 호스트 이름도 무작위 16진수가 아닌 호스트 머신의 호스트 이름으로 설정된다.

 

 

▷ 논 네트워크

  • 아무런 네트워크를 쓰지 않는 것을 뜻한다.
docker run -i -t --name network_none \
--net none \

다음과 같이 컨테이너를 생성하면 외부와의 연결이 단절된다.

 

 

▷ 컨테이너 네트워크

  • 다른 컨테이너와 네트워크 환경을 공유할 수 있다.
  • 공유 속성 : 내부 IP, 네트워크 인터페이스의 MAC 주소 등
docker run -i -t -d name network_container_1 ubuntu:14.04
docker run -i -t -d --name network_container_2 \
--net container:network_container_1 \

network_container_2 컨테이너의 네트워크와 관련된 사항은 전부 network_container_1 과 같게 설정된다.