Khắc phục truy cập DNS/internet ra ngoài trong Rootless Docker (HiTechCloud)
Triệu chứng
Các container chạy trong context rootless Docker riêng của từng người dùng (qua vpnkit) không truy cập được internet ra bên ngoài. Việc phân giải DNS thất bại với mọi hostname bên ngoài, dù:
- Máy chủ host có truy cập internet đầy đủ.
- Các container Docker cấp hệ thống (ví dụ container reverse proxy) phân giải DNS bình thường.
- Sự cố chỉ ảnh hưởng tới các container rootless của từng người dùng.
Ví dụ lỗi:
docker --context <user> exec apache wget -q --spider --timeout=5 https://example.com/feed.xml
# wget: bad address 'example.com'
docker --context <user> exec apache nslookup example.com 8.8.8.8
# ;; connection timed out; no servers could be reached
Ảnh hưởng thực tế: Với các ứng dụng tải nội dung từ xa (ví dụ mô-đun RSS/feed trong CMS), mỗi host bên ngoài không phân giải được có thể làm mỗi lần tải trang chậm đi đáng kể — vì PHP/Apache phải chờ hết thời gian chờ DNS cho từng host không phân giải được. Điều này có thể biến một lần tải trang bình thường vài giây thành hơn một phút.
Nguyên nhân gốc
Rootless Docker dùng vpnkit cho mạng. vpnkit chặn việc phân giải DNS trước khi nó tới bất kỳ nameserver nào được cấu hình bên trong container hoặc trong docker-compose.yml. Do đó:
- Thêm
dns: [8.8.8.8, 1.1.1.1]vào service trongdocker-compose.ymlkhông có tác dụng. - Sửa thủ công
/etc/resolv.confbên trong container không có tác dụng.
Cách sửa thực sự phải thực hiện ở cấp daemon rootless Docker, không phải ở cấp container hay compose.
Các bước khắc phục
1. Kiểm tra từ đúng container
Đảm bảo bạn kiểm tra từ container thực sự gửi các yêu cầu ra ngoài cho ứng dụng (ví dụ container PHP-FPM), không chỉ container web server, vì các yêu cầu ra ngoài ở cấp ứng dụng thường chạy qua một tiến trình khác.
docker --context <user> exec <phpfpm-container> curl https://example.com/
2. Kiểm tra cấu hình daemon của người dùng
Tìm tệp cấu hình daemon rootless của người dùng bị ảnh hưởng:
/home/<user>/.config/docker/daemon.json
So sánh với cấu hình tham chiếu chính thức của nền tảng cho daemon rootless Docker.
Nếu thiếu trường hoặc chưa đầy đủ, hãy thay daemon.json bằng định dạng đầy đủ như mong đợi, xem ví dụ
Đừng quên khởi động lại daemon Docker của người dùng đó theo bước 4.
3. Xác minh network driver của người dùng
Xác nhận mạng internal trong docker-compose.yml của người dùng (/home/<USER>/docker-compose.yml) dùng driver bridge:
networks:
internal:
driver: bridge
4. Khởi động lại daemon rootless Docker của người dùng đó
machinectl shell <user>@ /bin/bash -c "systemctl --user start docker"
(Dùng restart thay cho start nếu daemon đang chạy.)
5. Xác minh kết nối sau khi khởi động lại
docker --context <user> exec <phpfpm-container> curl https://example.com/
docker --context <user> exec apache wget -q -O- https://example.com/feed.xml
Cả hai lệnh giờ phải trả về kết quả hợp lệ thay vì hết thời gian chờ.
6. Lệnh chẩn đoán (nếu sự cố vẫn còn)
Thu thập và xem xét các thông tin sau trước khi chuyển lên bộ phận hỗ trợ nền tảng:
hitechcloudcli report --public
docker info
docker --context=<user> network inspect <network-name>
Ghi chú
- Người dùng mới tạo có thể đã có sẵn
daemon.jsonđúng theo mặc định — sự cố này có thể xảy ra khi cấu hình của một người dùng đã có từ trước định dạng tham chiếu hiện tại hoặc đã bị sửa thủ công. - Nếu cách sửa không giải quyết được DNS, hãy kiểm tra lại xem tổ hợp hệ điều hành/network driver của bạn có cần
slirp4netnskhông, và gửi kết quả chẩn đoán cho bộ phận hỗ trợ nền tảng để giúp tái hiện môi trường.
Danh sách kiểm tra tóm tắt
- Kiểm tra DNS từ container ứng dụng/backend, không chỉ container web server
- So sánh
daemon.jsoncủa người dùng với cấu hình tham chiếu rootless chính thức - Đảm bảo network driver của mạng internal là
bridge - Khởi động lại daemon rootless Docker của người dùng
- Kiểm tra lại kết nối ra ngoài từ cả container web server lẫn container backend
- Triệu chứng
- Nguyên nhân gốc
- Các bước khắc phục
- 1. Kiểm tra từ đúng container
- 2. Kiểm tra cấu hình daemon của người dùng
- 3. Xác minh network driver của người dùng
- 4. Khởi động lại daemon rootless Docker của người dùng đó
- 5. Xác minh kết nối sau khi khởi động lại
- 6. Lệnh chẩn đoán (nếu sự cố vẫn còn)
- Ghi chú
- Danh sách kiểm tra tóm tắt