Đây chỉ là một ghi chú nhanh do việc này cũng rất đơn giản, mình ngộ ra từ một project thực tế nên ghi lại cho nhớ.
Vấn đề
Có lẽ thường thì chúng ta chỉ hay làm việc với những app độc lập khi dùng Docker. Ví dụ mỗi app dùng riêng một docker-compose.yml với các containers độc lập chẳng hạn, app nào biết app đó. Nhưng có trường hợp thế này: bạn đang phát triển một project bao gồm phần API và phần Admin tách riêng, nhưng lại dùng chung database. Nếu như bạn tự build trên máy local thì quá đơn giản, ở mỗi app chỉ cần trỏ chung đến cùng một database là xong. Nhưng khi dùng docker thì sao?
Nếu như ở phần Admin bạn điền DATABASE HOST cho giống với API thì sẽ không thể nào chạy được, vì đơn giản là mỗi khi bạn build từ docker-compose, nó sẽ tự tạo cho mỗi project một network mặc định khác nhau, khác network thì không thể liên lạc với nhau được.
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
e186de001b4b my-demo-api_default bridge local
7dc9746e3ad0 my-demo-admin_default bridge local
Ví dụ như trên khi mình list ra các networks đang có, mỗi bên app của mình có một network riêng với suffix _default
Network dùng chung
Vấn đề sẽ được giải quyết khi ta chỉ cần tạo 1 network thôi, và ở đâu muốn dùng thì ta khai báo là được. Cụ thể, ta sẽ khai báo network dùng chung ở bên API chẳng hạn, sau đó bên Admin sẽ dùng lại network đó.
Cài đặt trong docker-compose.yml
Bên API
Trong docker-compose.yml, thêm phần khai báo network:
# services declarations...
networks:
my-network:
driver: bridge
Nếu bạn docker-compose up
với config này, nó sẽ báo:
WARNING: Some networks were defined but are not used by any service: my-network
Nghĩa là các services trong docker-compose.yml
chưa khai báo để sử dụng network này, cho nên docker sẽ chỉ tạo network mặc định như đầu bài viết có nói. Ta phải định nghĩa thêm cho các services:
version: '2'
services:
my_api:
build: .
working_dir: /app
ports:
- '3000:3000'
networks:
- my-network
my_db:
image: mysql:5.7
ports:
- 33066:3306
networks:
- my-network
# other servies...
networks:
my-network:
driver: bridge
Khi up
với nội dung config này, docker sẽ tạo ra network có tên theo định dạng <directory_name>_<network_name>
, với <directory_name>
là tên của folder đang chứa app hiện tại, <network_name>
là tên chúng ta vừa khai báo. Cụ thể, network sẽ có tên là my-demo-api_my-network
. Đây chính là tên sẽ khai báo ở bên Admin.
Bên Admin
Không giống như bên "chủ nhà" tạo ra network, ở bên sử dụng, chỉ cần khai báo networks là xong, không cần khai báo đến từng service:
# admin services...
networks:
default:
external:
name: my-demo-api_my-network
Chỉ cần như vậy, khi up
project Admin lên, nó sẽ kết nối tới network của bên API, và khi đó bạn có thể dùng chung các thứ khác, ví dụ database.
Chỉ có một lưu ý nho nhỏ là để các app chạy được, bạn phải bật app "chủ nhà" tạo network trước, rồi mới đến các app khác.
Chúc Mừng Năm Mới 2020!