[Docker] Networking in Compose

Phần này áp dụng cho các file formats version 2 và cao hơn. Chức năng networking không hỗ trợ cho Compose file version 1

Before you begin

Trước tiên tôi tổng kết những hiểu biết ít ỏi của mình về network trong Docker

Mô hình

Cái này tôi không hiểu nên tạm để đọc sau, bạn có thể xem thêm tại đây

Mặc định, Docker hỗ trợ 3 loại card mạng

1
2
3
4
5
C:\Users\Nguyen Van Minh>docker network ls
NETWORK ID NAME DRIVER SCOPE
36b98d0bbbdb bridge bridge local
ed6e03e4775b host host local
5bdac30c1444 none null local
  • None network: Các container thiết lập network này sẽ không được cấu hình mạng. None driver cung cấp cho một container networking stack và không gian mạng riêng của nó nhưng không config các interface bên trong container. Không có config bổ sung, các container hoàn toàn cách ly với networking stack của host.
  • Bridge: Docker sẽ tạo ra một switch ảo. Khi container được tạo ra, interface của container sẽ gắn vào switch ảo này và kết nối với interface của host.
  • Host: Containers sẽ dùng mạng trực tiếp của máy host. Network configuration bên trong container đồng nhất với host.

Default network của Docker

  • Mặc định các container của service sẽ tham gia vào mạng mặc định do Docker tạo ra. Tên mạng sẽ là PROJECTNAME_default, có card là bridge. Mạng này bị Docker quản lý (đúng rồi mà, tạo switch ảo từ Docker ra:D).

“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. Tuy nhiên, các container được cấp ip động nên nó có thể thay đổi, dẫn đến nhiều khó khăn. Vì vậy, thay vì dùng địa chỉ ip, ta có thể dùng name của các container để “liên lạc” giữa các container với nhau.”

  • Cơ bản các container đã nói chuyện được với nhau rồi, nhưng để tránh bị IP thay đổi, bạn có thể dùng link để alias lại tên giữa các container với nhau.
    Ví dụ container A + B cùng tham gia mạng mặc định khi up, tuy nhiên mỗi lần up A lại được cấp IP khác nhau 10.0.2.1 lúc lại là 10.0.2.3.
    => gán cho 1 cái tên và alias (link A:Annie) để IP thay đổi cùng kệ, trong mạng default B sẽ gọi A là Annie =))
    Bản thân tôi thấy không cần link vẫn được, có thể sử dụng luôn tên service. Như vậy link trong docker compose chỉ có đúng 1 tác dụng như vậy :D.

Thay vì phải tham gia vào 1 mạng default và bị Docker quản lý, cấp phát IP như vậy, các container không muốn, muốn tự lập vùng mạng riêng, tham gia vào đó. Nơi này các container tự tìm (discoverable) được nhau qua tên và có thể custom card mạng nếu muốn. Đặc biệt, tạo mạng riêng cho 1 vài container kết nối (ví dụ mạng front-end và mạng back-end sẽ được đề cập trong ví dụ sau).
Cách này là Specify custom networks, bạn nên sử dụng nó và nó được khuyến khích sử dụng thay links

The --link flag is a legacy feature of Docker. It may eventually be removed. Unless you absolutely need to continue using it, we recommend that you use user-defined networks to facilitate communication between two containers instead of using --link.

Let’s start

Mặc định Compose set up 1 mạng đơn cho ứng dụng. Mỗi container cho 1 dịch vụ tham gia default network và cả 2 có thể reachable bởi containers khác trên mạng đó và cũng có thể discoverable trên hostname tới tên container.

Ví dụ, ứng dụng của bạn có đường dẫn myapp, và file docker-compose.yml của bạn sẽ như sau:

1
2
3
4
5
6
7
8
9
10
version: "3"
services:
web:
build: .
ports:
- "8000:8000"
db:
image: postgres
ports:
- "8001:5432"

Khi bạn chạy docker-compose up, những điều sau sẽ xảy ra:

  • Một mạng với tên gọi myapp_default sẽ được tạo.
  • Một container được tạo sử dụng cấu hình của web. Nó tham gia vào mạng myapp_default dưới tên web.
  • Một container được tạo sử dụng cấu hình của db. Nó tham gia vào mạng myapp_default dưới tên db.

Mỗi container bây giờ có thể tra cứu hostname web hoặc db và lấy lại địa chỉ IP của container. Ví dụ, code của ứng dụng web có thể kết nối tới URL postgres://db:5432 và bắt đầu sử dụng Postgres database.

Có 1 điều quan trọng cần chú ý phân biệt giữa HOST_POSTCONTAINER_PORT. Trong ví dụ trên, đối với db, HOST_PORT là 8001 và container port là 5432 (cổng mặc định của postgres). Mạng service-to-service kết nối sử dụng CONTAINER_POST. Khi mà HOST_PORT được định nghĩa, dịch vụ có thể truy cập bên ngoài the swarm

Trong web container, kết nối của bạn tới db sẽ như sau postgres://db:5432 và từ host machine, kết nối sẽ như sau postgres://{DOCKER_IP}:8001

Update containers

Nếu bạn muốn tạo cấu hình thay đổi 1 dịch vụ và chạy docker-compose up để cập nhật nó, các container cũ sẽ bị xóa và 1 cái mới sẽ tham gia mạng dưới 1 địa chỉ IP khác nhưng tên giống như vậy. Container đang chạy có thể tra cứu tên đó và kết nối đến địa chỉ mới, nhưng địa chỉ cũ đã dừng hoạt động.

Nếu 1 vài containers có mở kết nối đến các container cũ, chúng sẽ bị đóng lại. Trách nhiệm của 1 conatainer là phải phát hiện tình trạng này, tra cứu lại tên và kết nối lại.

Links cho phép bạn định nghĩa thêm aliases (bí danh) của 1 service có thể kết nối đến từ service khác. Chúng không yêu cầu phải kích hoạt các services để kết nối - mặc định, 1 vài service có thể đi đến 1 vài service khác với tên của service. Như ví dụ dưới đây, db có thể kết nối từ web với hostname dbdatabase:

1
2
3
4
5
6
7
8
9
version: "3"
services:

web:
build: .
links:
- "db:database"
db:
image: postgres

Multi-host networking

Phần này nói về Docker swarm, sẽ bổ sung sau …

Specify custom networks

Thay vì sử dụng các default app network, bạn có thể chỉ định network riêng của mình với từ khóa networks. Điều này làm cho bạn tạo nhiều hơn cấu trúc phức tạp và chỉ định các options và drives trong các mạng của mình. Bạn cũng có thể sử dụng nó để kết nối các dịch vụ tới mạng externally-created (được tạo từ bên ngoài), cái mà không bị quản lý bởi Compose.

Mỗi service có thể chỉ định mạng để kết nối với service-level networks key, cái mà liệt kê ra danh sách tên tham chiếu sử dụng từ top-level networks key

Dưới đây là ví dụ Compose file định nghĩa 2 custom mạng. proxy service bị cô lập từ db service vì chúng không chia sẻ trong 1 mạng chung - chỉ app có thể nói chuyện với cả 2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
version: "3"
services:

proxy:
build: ./proxy

# service-level networks
networks:
- frontend
app:
build: ./app
networks:
- frontend
- backend
db:
image: postgres
networks:
- backend
# top-level networks
networks:
frontend:
# Use a custom driver
driver: custom-driver-1
backend:
# Use a custom driver which takes special options
driver: custom-driver-2
driver_opts:
foo: "1"
bar: "2"

Networks có thể được cấu hình với địa chỉ static IP bằng cách setting ipv4_address and/or ipv6_address cho mỗi mạng được đính kèm

Networks cũng có thể nhận 1 custom name:

1
2
3
4
5
version: "3.5"
networks:
frontend:
name: custom_frontend
driver: custom-driver-1

Configure the default network

Bạn cũng hoàn toàn có thể cấu hình lại networks mặc định trong Compose bằng cách sử dụng tên default trong networks:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
version: "3"
services:

web:
build: .
ports:
- "8000:8000"
db:
image: postgres

networks:
default:
# Use a custom driver
driver: custom-driver-1

Use a pre-existing network

Nếu bạn muốn container của bạn tham gia 1 pre-existing networks (network đã tồn tại trước đó), sử dụng tùy chọn external:

1
2
3
4
networks:
default:
external:
name: my-pre-existing-network

Thay vì tham gia vào mạng tên là projectname]_default, Compose tìm kiếm mạng tới tên là my-pre-existing-network và kết nối ứng container của bạn tới nó

So sánh link với networks

Như đã đề cập rất nhiều ở trên, bạn nên dùng networks để thay thế link. Link chỉ là bí danh và các container vẫn tham gia chung 1 mạng default cho Docker quản lý.

Đây là 2 cách giúp container có thể kết nối với container khác thông qua tên hoặc bí danh mà không cần địa chỉ IP (ta hiểu là các container tự phân giải được nhau).

Về cơ bản, links không còn cần thiết vì mục đích chính của nó là làm cho container có thể chạm tới nhau bằng cách thêm biến môi trường. Khi containers được thay thế bởi mạng giống nhau, chúng có thể chạm tới các container khác qua tên hoặc bí danh như host


Before the Docker network feature, you could use the Docker link feature to allow containers to discover each other. With the introduction of Docker networks, containers can be discovered by its name automatically.

Tài liệu tham khảo

Author

Ming

Posted on

2020-04-21

Updated on

2021-04-10

Licensed under

Comments