Vì sao các container Docker phớt lờ bộ phân giải DNS của VPN
Container sao chép bộ phân giải của máy chủ khi khởi động, nên một VPN ghi lại DNS sau đó vẫn vô hình bên trong nó. Hãy truyền bộ phân giải một cách rõ ràng.
VPN đang bật, trình duyệt truy cập được các trang nội bộ, mà container vẫn không phân giải được cùng những tên đó. Quá trình cài gói chết với lỗi phân giải tên như EAI_AGAIN, hoặc một ứng dụng không tìm thấy máy chủ cơ sở dữ liệu mà máy chủ thể phân giải mà không hề phàn nàn. Container không dùng bộ phân giải mà VPN đã cài. Docker đã sao chép cấu hình bộ phân giải của máy chủ thể khi container được tạo, và không có gì sao chép lại nó sau đó.
Hai góc nhìn về bộ phân giải trên cùng một máy
Trên Linux, Docker cấp cho mỗi container một bản sao của cấu hình bộ phân giải của máy chủ thể tại thời điểm tạo, lọc bỏ các địa chỉ loopback và chạy một máy chủ DNS nhúng tại 127.0.0.11 chuyển tiếp các truy vấn ra ngoài. Một ứng dụng khách VPN ghi lại /etc/resolv.conf sau khi container đã khởi động không thay đổi gì bên trong nó. Khởi động lại container chỉ giúp khi bộ phân giải của máy chủ thể tình cờ đúng vào lúc đó.
Docker Desktop trên macOS hoặc Windows thêm một lớp, vì daemon sống trong một máy ảo. Bộ phân giải VPN của máy chủ thể có thể không bao giờ hiển thị với VM đó, nên khởi động lại không thay đổi gì cả. So sánh hai góc nhìn trước khi chọn cách khắc phục: docker exec mycontainer cat /etc/resolv.conf bên cạnh danh sách bộ phân giải của máy chủ thể.
Một container liệt kê bộ phân giải công cộng trong khi máy chủ thể liệt kê bộ phân giải nội bộ sẽ phân giải được tên công cộng và thất bại với tên nội bộ. Sự phân đôi đó chính là dấu hiệu của vấn đề này.
Lựa chọn A: truyền bộ phân giải của đường hầm cho từng container
Docker chấp nhận cài đặt DNS cho từng container, và đó là thay đổi nhỏ nhất có tác dụng. Trước tiên hãy đọc các địa chỉ bộ phân giải của VPN: scutil --dns trên macOS, resolvectl status hoặc đầu ra trạng thái của chính ứng dụng khách trên Linux. Sau đó khởi động container với chúng, ví dụ docker run --dns 192.168.2.1 --dns 192.168.123.1 myimage. Trong Compose, cùng cài đặt đó là một danh sách dưới dịch vụ, nơi nó sống trong kiểm soát phiên bản thay vì lịch sử shell của ai đó.
Một mảng dns trong /etc/docker/daemon.json áp dụng cho mọi container mới, nghe có vẻ gọn gàng hơn và không phải vậy. Nó cũng áp dụng khi đường hầm ngừng hoạt động, và khi đó một bộ phân giải chỉ truy cập được qua VPN sẽ làm hỏng việc tải image thông thường. Cài đặt cho từng container dễ biện luận hơn và dễ hoàn tác hơn.
Lựa chọn B: để container chia sẻ mạng của máy chủ thể
Mạng của máy chủ thể bỏ qua hoàn toàn bản sao, vì container dùng bộ phân giải của máy chủ thể và đường hầm của máy chủ thể. Nó cũng loại bỏ sự cô lập mạng mà bạn có lẽ muốn, và nó không hành xử giống nhau dưới Docker Desktop. Trên Linux, đây là lựa chọn thực dụng cho một công cụ dùng một lần cần phân giải tên nội bộ.
Với các bản build, không lựa chọn nào áp dụng được, vì các bước build không kế thừa cờ thời gian chạy. Hãy build với mạng của máy chủ thể ở nơi nền tảng cho phép, hoặc giữ việc cài đặt phụ thuộc ở một giai đoạn không cần đường hầm.
Điều mà không lựa chọn nào khắc phục được
Một địa chỉ DNS là vô dụng nếu container không có tuyến đến nó. Bộ phân giải của VPN thường nằm bên trong không gian địa chỉ của đường hầm, nên container cần một đường đến tiền tố đó. Cầu nối mặc định của Docker thường định tuyến ra ngoài qua máy chủ thể, và thế là đủ khi máy chủ thể có tuyến của đường hầm và tính năng chuyển tiếp được bật. Các mạng cầu tùy chỉnh với nhóm địa chỉ riêng có thể đụng độ với mạng con của VPN, và khi đó các truy vấn đi tới một nơi hoàn toàn khác.
Hãy kiểm tra mạng con của mạng Docker so với mạng con của VPN trước khi gỡ lỗi chính bộ phân giải. Sự chồng lấn tạo ra một lỗi trông đúng như một máy chủ DNS hỏng.
Xác minh bên trong container
Hãy kiểm tra bằng getent hosts db.internal bên trong container thay vì bằng trình duyệt hoặc môi trường chạy của ngôn ngữ, vì những thứ đó áp dụng chính sách DNS và bộ nhớ đệm của riêng chúng. Nếu getent phân giải được tên mà ứng dụng vẫn thất bại, thì bộ phân giải giờ đã đúng và vấn đề còn lại nằm ở tầng ứng dụng. Nếu nó không phân giải được, bước DNS chưa hoàn tất.
Hãy tạo lại container sau khi thay đổi cài đặt DNS của nó. Việc sửa /etc/resolv.conf bên trong một container đang chạy sẽ biến mất cùng với nó và che giấu vấn đề cấu hình đúng trong khoảng thời gian ai đó cần để khởi động lại nó.