Bạn có chắc chắn muốn xóa bài viết này không ?
Bạn có chắc chắn muốn xóa bình luận này không ?
Cách liên kết các container lại với nhau trong docker
Liên kết các container trên cùng một host
Trên cùng một host, các container chỉ cần dùng bridge network để nói chuyện được với nhau. Nhưng có một trở ngại là IP của các container được cấp động nên nếu sử dụng IP thì không tiện chút nào. Cách duy nhất giải quyết là dùng name, vừa thân thiện lại có thể map động nên khi IP thay đổi cũng không lo mất kết nối giữa các dịch vụ chạy trên các container khác nhau. Phương thức thực hiện của docker lại hơi khác nhau trong hai trường hợp: sử dụng default bridge network và sử dụng user-defined bridge network. MÌnh sẽ đi lần lượt từng trường hợp.
Về bridge network bạn có thể tìm đọc một bài mình từng viết:
http://kipalog.com/posts/Tim-hieu-bridge-network-trong-Docker
Trường hợp sử dụng default bridge network để kết nối các container
Để kết nối được các container trong host qua name thì chỉ có cách dùng dns hoặc /etc/hosts
Trong trường hợp sử dụng default bridge network mặc định sẽ không có một built-in DNS hoạt động. Thử kiểm tra xem
Run alpine image và xem resolv.conf của nó
docker run -it alpine sh
/ # cat /etc/resolv.conf
nameserver 8.8.8.8
Thông tin trong /etc/resolv.conf của container là sao chép từ con host, chỉ sao chép chứ không tham chiếu. Nameserver 8.8.8.8 chắc chắn không thể biết phân giải name của các container được. Bạn có thể sửa đổi nameserver qua docker run --dns
Tìm tiếp trong /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.8 81d8c4cf33ff
Dòng 172.17.0.8 81d8c4cf33ff là cho localhost
Cũng không có thông tin để phân giải name ra IP cho các container khác.
Ở đây hostname khi không được xác định trong docker run -h thì sẽ dùng container id
Cả ba file /etc/hosts, /etc/resolv.conf và /etc/hostname đều được mount từ ngoài vào
/ # mount | grep etc
/dev/md126p3 on /etc/resolv.conf
/dev/md126p3 on /etc/hostname
/dev/md126p3 on /etc/hosts
Vậy nếu giờ muốn liên kết các container qua default bridge network thì làm thế nào ?
Có thể dùng giải pháp link container.
Giả sử có mô hình
web - redis - db
ở đây từ container web phải connect được đến redis và đến db. Đặt tên cho từng container. Sau đó link theo tên, phải đảm bảo container được link phải tồn tại. Do đó phải run theo thư tứ db -> redis -> web
docker run -itd --name=db -e MYSQL_ROOT_PASSWORD=pass mysql:latest
docker run -itd --name=redis redis:latest
docker run -itd --name=web --link=redis --link=db nginx:latest
docker exec -it web sh
# ping redis
PING redis (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: icmp_seq=0 ttl=64 time=0.245 ms
...
# ping db
PING db (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.126 ms
...
Lý do web container liên lạc được db và redis qua name là nhờ docker engine đã tự set thông tin link vào /etc/hosts của web container:
# cat /etc/hosts
172.17.0.3 redis 21cdcee10183
172.17.0.2 db 158aed2b8df9
Link này chỉ link một chiều, từ db và redis bạn không thể ping đến web được. Nói chung dùng link thì rất bất tiện, phải định nghĩa rõ chiều kết nối, phải đảm bảo start container theo đúng thứ tự. Phương thức kết nối qua link đã bị xem là lịch sử. Hiện tại nó chỉ còn được dùng để đảm bảo thứ tự khỏi chạy của các container.
Có lẽ lý do default bridge network không sử dụng một built-in dns sẵn là tránh cho người dùng cấu hình bừa bãi trong network này khiến nó trở thành một mạng quá lớn, các container liên kết với nhau quá dễ dàng dễ gây loạn. Vừa giải quyết vấn đề của link mà không khiến mạng bridge quá phình to thì docker khuyến khích dùng các user-defined bridge network
Trường hợp sử dụng user-defined bridge network để kết nối các container
Như đã nói, trường hợp này docker sẽ có sẵn một built-in dns, bạn không cần thực hiện thao tác link qua link lại giữa các container nữa.
Mỗi một user-defined network này sẽ có một built-in dns riêng.
docker network create my-net
docker network ls
NETWORK ID NAME DRIVER
716f591e185a bridge bridge
4b0041303d6d host host
7239bb9e0255 my-net bridge
016cf6ec1791 none null
docker run -itd --name=web1 --net my-net nginx:latest
docker run -itd --net my-net --name=redis1 redis:latest
docker run -itd --name=db1 --net my-net -e MYSQL_ROOT_PASSWORD=pass mysql:latest
docker exec -it web1 sh
# ping db1
PING db1 (172.18.0.4): 56 data bytes
64 bytes from 172.18.0.4: icmp_seq=0 ttl=64 time=0.161 ms
# ping redis1
PING redis1 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: icmp_seq=0 ttl=64 time=0.168 ms
Và do không dùng link mà qua một dns built-in nên các container có thể kết nối lẫn nhau, từ db1 bạn có thể ping được redis1 và web1
cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0
Nếu trong default bridge network, cố tính set nameserver 127.0.0.11 cũng không active được built-in dns này.
Hiện tại docker chưa cung cấp công cụ để xem thông tin các record của built-in dns này.
Tham khảo:
https://docs.docker.com/engine/userguide/networking/default_network/configure-dns/
https://docs.docker.com/engine/userguide/networking/configure-dns/
manhdung 22-07-2016






