같은 compose 파일 안의 서비스는 자동으로 한 네트워크에 묶이고 서비스 이름으로 서로를 찾는다. 대부분은 이것으로 충분하고, IP 를 고정할 이유는 별로 없다. 다만 외부 장비가 특정 IP 로 접근해야 하거나 설정 파일에 IP 를 박아야 하는 레거시 애플리케이션에서는 고정이 필요하다.
고정 IP 를 주려면 그 네트워크에 ipam.config.subnet 이 있어야 한다. 서브넷 없이 ipv4_address 만 적으면 "user specified IP address is supported only when connecting to networks with user configured subnets" 오류가 난다.
services:
app1:
image: nginx:latest
networks:
mynet:
ipv4_address: 172.28.0.10
app2:
image: httpd:latest
networks:
mynet:
ipv4_address: 172.28.0.11
networks:
mynet:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/24
gateway: 172.28.0.1
/16 을 통째로 잡으면 다른 네트워크가 쓸 대역을 먹으므로 필요한 만큼만 /24 로 잡는 편이 낫다.
internal: true 를 주면 그 네트워크에는 게이트웨이가 만들어지지 않아 바깥으로 나가지 못한다. 데이터베이스처럼 밖에 노출할 이유가 없는 서비스를 여기에 둔다. 앞단 서비스만 공개 네트워크에 함께 붙인다.
services:
backend:
image: redis:latest
networks: [internal_net]
frontend:
image: nginx:latest
ports: ["8080:80"]
networks: [public_net, internal_net]
networks:
public_net:
driver: bridge
internal_net:
driver: bridge
internal: true
컨테이너가 사내망의 독립 장비처럼 보여야 한다면 macvlan 을 쓴다. 컨테이너마다 MAC 을 받아 물리 네트워크에 직접 참여한다.
networks:
lan:
driver: macvlan
driver_opts:
parent: eth0
ipam:
config:
- subnet: 192.168.1.0/24
gateway: 192.168.1.1
macvlan 에는 제약이 둘 있다. 호스트와 그 컨테이너는 서로 통신하지 못한다 — 같은 물리 인터페이스에서 나간 프레임이 호스트로 되돌아오지 않기 때문이다. 필요하면 호스트에 macvlan 서브 인터페이스를 따로 만들어 우회한다. 그리고 스위치가 포트당 MAC 을 제한하거나 무선 인터페이스를 부모로 쓰면 동작하지 않는다.
단순히 호스트 IP 를 그대로 쓰면 되는 경우라면 network_mode: host 가 훨씬 간단하다. 대신 포트 매핑이 없어 호스트 포트와 충돌할 수 있다.
failed to create network xxx_default: could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network 는 Docker 가 기본 풀에서 비어 있는 대역을 찾지 못했다는 뜻이다. 네트워크를 많이 만들어 뒀거나, VPN·사내망이 172.17.0.0/12 대역과 겹칠 때 난다.
docker network ls
docker network prune # 쓰지 않는 네트워크 정리
ip route # 이미 쓰는 대역 확인
해결은 셋 중 하나다. 쓰지 않는 네트워크를 지우거나, 해당 네트워크에 서브넷을 명시하거나, 데몬의 기본 풀 자체를 사내망과 겹치지 않는 대역으로 바꾼다. 마지막 방법은 Docker network 대역 변경 에 있다.