Tóm tắt vấn đề và giải pháp cho lỗi: Docker Network Subnet Exhaustion
Vấn đề
Khi triển khai nhiều instance Odoo trên cùng một server bằng Docker Compose
tôi gặp lỗi:
failed to create network ... all predefined address pools have been fully subnetted.
Nguyên nhân là Docker đã sử dụng hết các subnet mặc định (ví dụ: 172.19.0.0/16, 192.168.240.0/20) do mỗi docker-compose.yml tạo ra một mạng riêng biệt, dẫn đến cạn kiệt khoảng 31 subnet khả dụng trong pool mặc định.
Thường mặc định thì docker sẽ chỉ có khoảng 31 subnet khả dụng trong pool mặc định, cho phép bạn tạo được tầm hơn chục con odoo (mỗi con gồm 1 container odoo và 1 container postgres) là sẽ hết subnet pool, do đó lỗi này khá phổ biến nếu bạn chạy nhiều docker container (không nhất thiết phải là odoo).
Tình trạng ban đầu
- File docker-compose.yml không định nghĩa mạng tùy chỉnh, nên Docker Compose tự tạo mạng _default (ví dụ: tfsd_kyerp_net__default).
- Subnet mặc định: /16 (65,536 IPs) hoặc /20 (4,096 IPs), lãng phí vì mỗi instance chỉ cần 2 IPs (web và db).
- Không có /etc/docker/daemon.json, Docker dùng pool mặc định giới hạn (~31 subnet), không đủ cho 1000 instance.
Giải pháp
Có 2 cách,
Cách 1 là thay đổi file docker compose và điều chỉnh cố định subnet cho mỗi container, cách này khá lằng nhằng vì mỗi file docker compose lại cần sửa lại thủ công để chỉ định subnet
Cách 2 là quy định 1 subnet lớn cho toàn bộ các docker container chạy odoo, cách này có nhược điểm bảo mật do các container cùng 1 subnet sẽ có thể liên lạc với nhau, để đảm bảo môi trường hoàn toàn độc lập cho từng odoo thì phương án này không được.
Cách 3 là mở rộng pool subnet mặc định của docker cho phép có thể chứa nhiều subnet hơn, tôi thấy cách này là tốt nhất:
dưới đây là cách tôi mở rộng pool subnet của docker cho phép chứa được nhiều docker container hơn. Cách mở rộng này cho phép có thể chạy + 1000 docker container trên cùng 1 máy mà không lo hết pool subnet.
1. Tạo /etc/docker/daemon.json:
echo '{"default-address-pools":[{"base":"10.0.0.0/8","size":24}]}' > /etc/docker/daemon.json
- 10.0.0.0/8: 16,777,216 IPs.
- size: 24: Mỗi mạng dùng subnet /24 (256 IPs), đủ cho 65,536 instance.
2. Khởi động lại Docker:
systemctl restart docker
3. Tái tạo instance:
vào từng instance và khởi động lại nó:
cd /home/<instance_directory> docker-compose down
docker-compose up -d
Nếu nhiều docker container đang chạy quá thì làm tự động
#!/bin/bash BASE_DIR="/home" for dir in "$BASE_DIR"/*_d_skyerp_net_*; do if [ -f "$dir/docker-compose.yml" ]; then echo "Recreating $dir..." cd "$dir" docker-compose down docker-compose up -d fi done
Kết quả
- Mỗi instance nhận một subnet /24 mới từ 10.0.0.0/8 (ví dụ: 10.0.1.0/24).
- Containers dùng IPs như 10.0.1.2, 10.0.1.3.
- Hỗ trợ 1000+ instance mà không lo hết subnet.
Lưu ý
- Kiểm tra xung đột với mạng host (dùng ip addr); nếu cần, thay 10.0.0.0/8 bằng 172.16.0.0/12.
- Tái tạo tất cả instance hiện có để áp dụng pool mới.
Xác minh lại xem đúng không
docker network inspect <NETWORK_ID> # Kiểm tra subnet docker info --format '{{.DefaultAddressPools}}' # Xác nhận pool
Tóm tắt vấn đề và giải pháp cho lỗi: Docker Network Subnet Exhaustion