Docker Network에 대해
1. Docker Network 란?
docker container로써 실행된 spring boot
에서 마찬가지로 contatiner로써 실행중인 mysql server
에 접근하기 위해서는, container 실행시 --link
옵션을 이용해 컨테이너간의 연결이 필요했습니다.
간단히 말해, 같은 Docker Host내에서 실행중인 Container간 연결할 수 있도록 돕는 논리적 네트워크같은 개념입니다.
2. --link vs network
docker 공식문서를 살펴보면 --link
는 곧 사라질 예정이며, 해당 기능 대신 network
를 사용하도록 권장하고 있습니다. 따라서, 이번 포스팅에서는 network를 생성한뒤, 이를 이용해 docker container간 통신을 해보는 방법을 알아보도록 하겠습니다.
3. Docker Network 종류
Default Bridge Network
Docker에서 제공하는 network로 실제 프로덕션 환경에 적합하다고 볼수는 없습니다. 간단히 개발환경에서 테스트를 위해 사용할 수 있을 것 같습니다.
User-Defined Bridge Networks
같은 Docker Host내에서 실행중인 Container간 연결할 수 있는, 사용자 정의 브릿지 네트워크이며, 실제 프로덕션 환경에 적합합니다.
Overlay Networks
보통 docker swarm에서 사용되며, 이 포스팅에서 다루지는 않겠습니다.
Docker Network 예제
1. 예제 환경 셋팅
기본 이미지 다운
우선 docker가 설치되어있다는 가정하에 진행하도록 하겠습니다.
xxxxxxxxxx
➜ docker_study docker search alpine
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
alpine A minimal Docker image based on Alpine Linux… 6359 [OK]
...
➜ docker_study docker pull alpine
우선 docker search alpine
를 통해 기본이미지를 찾습니다. Alpine linux 기본이미지가 보입니다.
docker pull alpine
을 입력해 이미지를 받습니다.
xxxxxxxxxx
➜ docker_study docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest a187dde48cd2 3 weeks ago 5.6MB
...
이미지가 받아진것을 확인할 수 있습니다.
2. Default Bridge Network 예제
2.1 연결 테스트를 위한 두개의 컨테이너 띄우기
xxxxxxxxxx
➜ docker_study docker run -dit --name a1 alpine ash
03cd577fb6a7ce81020d5471b20e9a497b6d880b6b35611ca445741ac9b12a5b
➜ docker_study docker run -dit --name a2 alpine ash
b305326dc6ee19573142ab0562eb6237b500d589ede03a0cff2fa189bb82bd09
docker run
명령어를 이용해 앞서 다운받은 기본이미지를 이용해 두개의 container("a1", "a2")를 띄웁니다. 네트워크를 설정하지 않은것에 주목하시길 바랍니다.
-d
옵션은 container를 백그라운드에서 실행하도록 하는 옵션입니다.
-i
옵션은 docker container가 dettach 된 상태일지라도 표준 입력을 유지하도록 하는 옵션입니다.
-t
옵션은 가상 너미널을 연결하는 옵션입니다.
--name
옵션은 컨테이너에 이름을 부여하는 옵션입니다.
마지막 ash는 알파인 리눅스의 기본 쉘을 의미합니다.
xxxxxxxxxx
➜ docker_study docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b305326dc6ee alpine "ash" 25 minutes ago Up 2 seconds a2
03cd577fb6a7 alpine "ash" 25 minutes ago Up 2 seconds a1
docker ps
명령어를 이용해 실행중인 컨테이너 목록을 확인합니다.
2.2 Default Bridge Network 확인
앞서 실행한 두개의 컨테이너에는 별도의 네트워크를 부여하지 않았습니다. 그렇다면 이들은 서로 통신이 불가능할까요 ??
x
➜ docker_study docker network ls
NETWORK ID NAME DRIVER SCOPE
0d99124a7cc8 bridge bridge local
5f3ea3ca8ff4 host host local
813a7781f2aa none null local
우선 docker network ls
명령어를 이용해 현재 HOST docker에 존재하는 network 목록을 보도록합니다.
x
➜ docker_study docker network inspect bridge
[
{
"Name": "bridge",
"Id": "0d99124a7cc84f82aebf7f185fb80549859472a8e465af59d779bfccfd515800",
"Created": "2020-04-16T23:33:01.37400833Z",
"Scope": "local",
"Driver": "bridge",
...
"Containers": { // 연결된 컨테이너 정보 !!!!
"03cd577fb6a7ce81020d5471b20e9a497b6d880b6b35611ca445741ac9b12a5b": {
"Name": "a1",
"EndpointID": "f331d9b5034ac577caa082a77fecd9ac489e548e2337f1d305b58d8b7f01e8bc",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16", // IP !!!!!
"IPv6Address": ""
},
"b305326dc6ee19573142ab0562eb6237b500d589ede03a0cff2fa189bb82bd09": {
"Name": "a2",
"EndpointID": "5a1becdae4fc28638401405dee83ba4ec6002fa326e00c060e169b97c3b0162f",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16", // IP !!!!!
"IPv6Address": ""
}
},
...
]
docker network inspect bridge
를 이용해 bridge 네트워크의 자세한 내용을 확인합니다. 중간의 Containers
를 확인하면, 현재 연결된 container를 확인할 수 있는데요, 방금 실행한 두개의 컨테이너 a1, a2가 보임을 알 수 있습니다.
또한 이들 컨테이너에는 172.17.x.x 대역의 사설 IP가 부여되어 있음을 알 수 있습니다.
2.3 연결 테스트
그렇다면 위에서 찾아낸 IP를 이용해 각각의 컨테이너간 통신을 테스트 해보겠습니다.
x
➜ docker_study docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS ..
b305326dc6ee alpine "ash" 25 minutes ago Up 25 ..
03cd577fb6a7 alpine "ash" 25 minutes ago Up 2 sec ..
➜ docker_study docker attach 03cd577fb6a7
/ #
➜ docker_study docker attach a1
/ #
ps를 이용해 attach할 컨테이너의 id를 찾습니다. docker attach CONTAINER_ID
를 이용해 attach하면 ash이 화면에 나타납니다. (또는 우리가 부여한 name을 이용하여 attach 할수도 있습니다. ctrl + p + q
를 눌러 container를 종료하지 않고 detach 합니다. docker attach a1
을 이용해 attach 합니다.)
xxxxxxxxxx
/ # ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.376 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.098 ms
64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.091 ms
64 bytes from 172.17.0.3: seq=3 ttl=64 time=0.102 ms
a1 컨테이너
의 쉘에서 아까 알아낸 a2 컨테이너
의 IP로 ping 테스트를 실시합니다. 성공적으로 연결되었음을 알 수 있습니다. 이처럼 docker container에 별도의 network 설정을 하지 않더라도, 기본 Bridge에 연결되어있어 컨테이너간 연결을 할 수 있습니다.
2.4 문제점
xxxxxxxxxx
/ # ping a2
ping: bad address 'a2'
이번에는 Container의 이름으로 ping 테스트를 해봅니다. a2
의 주소를 찾지 못합니다.
Production 환경에 부적합
이름으로 연결을 하지 못하는게 어떤 문제가 있을까요 ? 단지 주소를 알아내야하는 불편함 때문일까요? 아닙니다. 예를 들어, Server
를 도커 컨테이너를 이용해 띄웠고, Database
역시 도커 컨테이너를 이용해 띄웠다고 생각을 해봅시다. 이때, HOST docker의 Container가 Server
와 Database
만 존재하는 것이 아니라면, Server측에서 Database에 연결하기위한 address를 예측하기가 어려울 것입니다. 따라서, 이름을 통해 network 통신이 이루어져야 편리한 환경구축이 가능할 것입니다.
3. User-Defined Bridge Networks 예제
3.1 이전 환경 정리
x
➜ docker_study docker stop a1
➜ docker_study docker rm a1
➜ docker_study docker stop a2
➜ docker_study docker rm a2
우선 이전 예제를 위해 사용된 컨테이너를 정리합니다. (컨테이너는 stop후 rm을 이용해 정리합니다.)
3.2 Network 생성
x
➜ docker_study docker network create test-network
58305fc86cbda64c9d4dc5148d6ed98295456af03ff1b87416a9c3e94b05cc6f
➜ docker_study docker network ls
NETWORK ID NAME DRIVER SCOPE
...
9d7f5f440192 test-network bridge local
docker network create NAME
명령어를 이용해 새로운 user defined network를 생성하고, 확인합니다.
3.3 Network를 연결하여 Container 실행
x
➜ docker_study docker run -dit --name a1 --network test-network alpine ash
➜ docker_study docker run -dit --name a2 --network test-network alpine ash
➜ docker_study docker run -dit --name a3 alpine ash
이전 예제에서 컨테이너를 실행하는 명령어에 추가적으로 --network NETWORK_NAME
옵션을 부여하여 컨테이너를 실행합니다. 총 3개의 컨테이너를 실행합니다. 마지막 a3 컨테이너의 경우 컨테이너를 실행한뒤 네트워크를 연결하는 방법을 알아보기위해 네트워크 부여 옵션을 사용하지 않습니다.
3.4 이미 동작중인 Container에 Network 연결하기
x
➜ docker_study docker network inspect test-network
...
"Containers": {
"04e95bdc8b8cf3826e703f26320eba2472e4006e1bd766783f1f4bd94bbdd804": {
"Name": "a1",
"EndpointID": "e494234a92ad21277da0fac2ff865710bc3a22104a3a00864b744ff08f4451fa",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"a63c4606d95a1a8bff9c2ed90046d16bff02b4e687f77a74615f4ba5f6364a63": {
"Name": "a2",
"EndpointID": "733e6f5eae4d353556231b1918d70a91faa274a71360f17e3d4ef210b9f419ff",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
},
inspect 명령어를 이용해 test-network에 연결된 container를 확인합니다. 앞서 생성한 a1, a2
의 컨테이너만이 연결되어 있습니다.
xxxxxxxxxx
➜ docker_study docker network connect test-network a3
동작중인 container에 network를 연결하기 위해서는 network connect NETOWKR_NAME CONTAINER_NAME
명령어를 이용하면 됩니다.
x➜ docker_study docker network inspect test-network
...
"Containers": {
"Name": "a1",
"Name": "a2",
"Name": "a3"
...
},
...
위와같이 세개의 컨테이너가 연결되어 있음을 볼 수 있습니다.
*run 명령어를 통해 컨테이너를 생성하는 경우에는 단하나의 네트워크만을 설정할 수 있습니다. 따라서, 여러 네트워크를 연결하고 싶은 경우에도, 이 명령어를 이용합니다.
3.5 연결 테스트
ip를 이용해서는 당연히 통신이 가능하니, 이번에는 container의 name을 이용해 통신을 시도합니다.
x➜ docker_study docker attach a1
/ # ping a2
PING a2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.129 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.117 ms
64 bytes from 172.18.0.3: seq=2 ttl=64 time=0.104 ms
/ # ping a3
PING a3 (172.18.0.4): 56 data bytes
64 bytes from 172.18.0.4: seq=0 ttl=64 time=0.130 ms
64 bytes from 172.18.0.4: seq=1 ttl=64 time=0.105 ms
위와 같이 user-defined bridge network는 container의 name으로도 통신이 가능함을 알 수 있습니다.
'Infra > Docker' 카테고리의 다른 글
Docker - Spring Boot Application Docker로 배포하기 및 Mysql 연동 (3) | 2020.05.07 |
---|---|
Docker - container volume 사용 (0) | 2019.02.15 |
Docker - Docker의 데이터 저장방법 (0) | 2019.02.15 |
Docker - Forbidden path outside the build context 에러 (4) | 2019.01.30 |
Docker - Certification is Expired or not yet valid 에러 (0) | 2019.01.30 |