Docker Compose는 여러 개의 컨테이너(container)로 구성된 애플리케이션을 관리하기 위한 간단한 오케스트레이션(Orchestration) 도구입니다. 여러 개의 컨테이너로 구성된 Docker Compose 애플리케이션 내에서 컨테이너 간의 통신에 대해 알아봅니다.
디폴트 네트워크
기본적으로 Docker Compose는 하나의 디폴트 네트워크에 모든 컨테이너를 연결합니다. 디폴트 네트워크의 이름은 docker-compose.yml가 위치한 디렉토리 이름 뒤에 _default가 붙습니다. 예를 들어, 디렉토리 이름이 our_app라면 디폴트 네트워크 이름은 our_app_default가 됩니다.
디폴트 네트워크의 이름은 Docker Compose로 애플리케이션을 올릴 때 어렵지 않게 확인할 수 있습니다. 왜냐하면 Compose는 먼저 네트워크를 생성해놓고 각 컨테이너를 구동한 후 네트워크에 연결시키기 때문입니다.
$ cd our_app
$ docker-compose up -d
Creating network "our_app_default" with the default driver
Creating our_app_db_1 ... done
Creating our_app_web_1 ... done
Docker Compose로 애플리케이션을 내릴 때는 반대 순서로 컨테이너를 종료/제거한 후 마지막에 네트워크를 제거합니다.
$ docker-compose down
Stopping our_app_web_1 ... done
Stopping our_app_db_1 ... done
Removing our_app_web_1 ... done
Removing our_app_db_1 ... done
Removing network our_app_default
애플리케이션이 돌아가고 있는 중에도 Docker 네트워크 목록을 조회하면 디폴트 네트워크가 확인됩니다.
➜ docker network ls
NETWORK ID NAME DRIVER SCOPE
f1859120a0c3 bridge bridge local
95b00551745b host host local
1f7202baa40a none null local
2539640ca106 our_app_default bridge local
컨테이너 간 통신
디폴트 네트워크 안에서 컨테이너 간의 통신에서는 서비스의 이름이 호스트명으로 사용됩니다.
예를 들어, web 서비스의 컨테이너에서 db 서비스의 컨테이너를 대상으로 ping 명령어를 날릴 수 있습니다. 디폴트 네트워크 상에서 db 서비스 컨테이너의 IP가 192.168.48.2인 것으로 확인이되네요.
$ docker-compose exec web ping db
PING db (192.168.48.2) 56(84) bytes of data.
64 bytes from our_app_db_1.our_app_default (192.168.48.2): icmp_seq=1 ttl=64 time=0.094 ms
64 bytes from our_app_db_1.our_app_default (192.168.48.2): icmp_seq=2 ttl=64 time=0.162 ms
64 bytes from our_app_db_1.our_app_default (192.168.48.2): icmp_seq=3 ttl=64 time=0.080 ms
64 bytes from our_app_db_1.our_app_default (192.168.48.2): icmp_seq=4 ttl=64 time=0.348 ms
64 bytes from our_app_db_1.our_app_default (192.168.48.2): icmp_seq=5 ttl=64 time=0.195 ms
64 bytes from our_app_db_1.our_app_default (192.168.48.2): icmp_seq=6 ttl=64 time=0.187 ms
컨테이넌 간 통신에서 주의할 점은 접속하는 위치가 디폴트 네트워크 내부냐 외부냐에 따라서 포트(port)가 달라질 수 있다는 것입니다.
예를 들어, docker-compose.yml에 web 서비스의 ports 설정이 아래와 같다면,
services:
web:
build: .
ports:
- "8001:8000"
호스트 컴퓨터에서 접속할 때는 8001 포트를 사용해야 하고, 같은 디폴트 네트워크 내의 다른 컨테이너에서 접속할 때는 포트 8000을 사용해야 합니다.
- 호스트 컴퓨터에서 web 서비스 컨테이너 접속
$ curl -I localhost:8001
HTTP/1.1 200 OK
Date: Fri, 05 Jun 2020 02:05:10 GMT
Server: WSGIServer/0.2 CPython/3.8.2
Content-Type: text/html
X-Frame-Options: DENY
Content-Length: 16351
X-Content-Type-Options: nosniff
- 같은 네트워크 내의 다른 컨테이너에서 web 서비스 컨테이너 접속
$ docker-compose exec alpine curl -I web:8000
HTTP/1.1 200 OK
Date: Fri, 05 Jun 2020 02:13:46 GMT
Server: WSGIServer/0.2 CPython/3.8.2
Content-Type: text/html
X-Frame-Options: DENY
Content-Length: 16351
X-Content-Type-Options: nosniff
커스텀 네트워크 추가
Docker Compose는 디플트 네트워크 뿐만 아니라 다른 네트워크도 필요에 따라 추가해줄 수 있습니다.
docker-compose.yml의 networks 항목 아래에 our_net이라는 네트워크를 추가하고, web 서비스의 networks 항목 아래에 our_net 네트워크를 추가하겠습니다. 이렇게 설정을 하게되면 db 서비스는 디폴트 네트워크에만 연결되지만, web 서비스는 디폴트 네트워크 뿐만 아니라 our_net 네트워크에도 연결되게 됩니다.
services:
web:
build: .
ports:
- "8000:8000"
networks:
- default
- our_net
db:
image: postgres
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
networks:
our_net:
driver: bridge
Docker Compose로 애플리케이션을 올려보면 두 개의 네트워크가 생성되는 것을 알 수 있습니다.
$ docker-compose up -d
Creating network "our_app_default" with the default driver
Creating network "our_app_our_net" with driver "bridge"
Creating our_app_db_1 ... done
Creating our_app_web_1 ... done
$ our_app docker network ls
NETWORK ID NAME DRIVER SCOPE
f1859120a0c3 bridge bridge local
95b00551745b host host local
1f7202baa40a none null local
2682634e6535 our_app_default bridge local
525403b38bbe our_app_our_net bridge local
our_net은 Docker Compose 내부에서 정의된 네트워크 이므로 애플리케이션을 내릴 때 디폴트 네트워크와 함께 삭제됩니다.
$ docker-compose down
Stopping our_app_web_1 ... done
Stopping our_app_db_1 ... done
Removing our_app_web_1 ... done
Removing our_app_db_1 ... done
Removing network our_app_default
Removing network our_app_our_net
외부 네트워크 사용
Docker Compose가 제공하는 디폴트 네트워크 대신에 외부에서 미리 생성해놓은 다른 네트워크를 사용할 수도 있습니다.
먼저 our_net이라는 네트워크를 별도로 생성하겠습니다.
$ docker network create our_net
6d791b927c8c151c45a10ac13c62f3571ecf38a90756fd2ca1c62b7d3de804e8
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
f1859120a0c3 bridge bridge local
95b00551745b host host local
1f7202baa40a none null local
6d791b927c8c our_net bridge local
그 다음, docker-compose.yml에서 default 네트워크의 external 옵션에 our_net을 설정합니다.
networks:
default:
external:
name: our_net
이제 Docker Compose로 애프리케이션을 올리고, our_net 네트워크의 상세 정보를 확인해보면 Containers 항목에 두 개의 컨테이너가 연결된 것을 볼 수 있습니다.
$ docker-compose up -d
Creating our_app_db_1 ... done
Creating our_app_web_1 ... done
$ docker network inspect our_net
[
{
"Name": "our_net",
"Id": "6d791b927c8c151c45a10ac13c62f3571ecf38a90756fd2ca1c62b7d3de804e8",
"Created": "2020-06-06T15:55:05.3384403Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.208.0/20",
"Gateway": "192.168.208.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"7bcc8194e4018fa48328c6a1aa95a47829c77b850091bebaf1dd6661f5c79df9": {
"Name": "our_app_db_1",
"EndpointID": "4f3ffce8c6afc8d3de543859c1671bfe38b897c6e492a1be891de56ec2dfbf90",
"MacAddress": "02:42:c0:a8:d0:02",
"IPv4Address": "192.168.208.2/20",
"IPv6Address": ""
},
"dda9d355041adc8f90063e8876fe20a2c804b84b55ece3b6860e3dfb139099c7": {
"Name": "our_app_web_1",
"EndpointID": "b0f93bbb39c9eb83d4f286250b90239632667c6b89954d57c9593f32a44c3033",
"MacAddress": "02:42:c0:a8:d0:03",
"IPv4Address": "192.168.208.3/20",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
외부에서 생성된 네트워크이므로 Docker Compose 애플리케이션을 내릴 때 해당 네트워크가 함께 삭제되지 않습니다.
$ docker-compose down
Stopping our_app_web_1 ... done
Stopping our_app_db_1 ... done
Removing our_app_web_1 ... done
Removing our_app_db_1 ... done
Network our_net is external, skipping
외부 네트워크를 잘 활용하면 서로 다른 Docker Compose에서 돌아가고 있는 컨테이너 간에도 연결도 가능하게 됩니다. 예를 들어, 첫 번째 Docker Compose의 디폴트 네트워크를 두 번째 Docker Compose의 커스텀 네트워크로 추가해주면, 두 번째 Docker Compose 내의 컨테이너도 첫 번째 Docker Compose의 디폴트 네트워크에 연결될 수 있습니다.
'Docker' 카테고리의 다른 글
docker install on debian (0) | 2022.05.30 |
---|---|
도커 - web was 구성 (0) | 2022.04.21 |
Docker - 네트워크 (0) | 2022.04.21 |
Docker - 파일 저장 위치 (0) | 2022.04.19 |
Install Docker Engine on CentOS (0) | 2022.04.18 |