Container không tới được API chỉ mở qua VPN? Hãy proxy nó trên host
Đường hầm sống trên host, nên container không có tuyến tới địa chỉ riêng. Công bố một reverse proxy hẹp và gọi nó bằng host.docker.internal.
Dịch vụ Compose của bạn hết thời gian chờ trước một API mà trình duyệt trên cùng máy vẫn mở bình thường không chút phàn nàn. Chính khác biệt đó là manh mối: yêu cầu chạy được đi ra từ một host có đường hầm VPN, còn yêu cầu treo lại đi ra từ một container có ngăn xếp mạng riêng. Không gì bên trong container biết các tuyến của đường hầm, nên đích riêng tư vẫn không tới được dù tên có viết thế nào. Cách khắc phục là một bước nhảy có chủ đích qua host, không phải một bảng định tuyến khéo hơn.
Bắt đầu từ việc vì sao hai con đường khác nhau, rồi quyết định đường hầm nên sống ở đâu.
Vì sao host chạy được mà container thì không
Dựng đường hầm cho host một giao diện, một tập tuyến và thường là một mục phân giải do VPN cung cấp. Container không thừa hưởng gì trong số đó: nó khởi động với một giao diện trên cầu của engine và một tuyến mặc định trỏ vào cầu đó. Các tuyến cài trên host là vô hình với mọi thứ chạy bên trong không gian tên đó.
Đó là lý do các triệu chứng trông không nhất quán chứ không chỉ là hỏng. Host phân giải tên riêng và kết nối, vì cả tên lẫn tuyến đều tồn tại ở đó. Container gửi gói của nó tới một địa chỉ riêng mà không gì trên đường cầu với tới được, và yêu cầu hết thời gian chờ. Thêm tên vào tệp hosts của container không thay đổi gì, vì bản thân địa chỉ đã không tới được từ chỗ container đứng.
Tới host từ bên trong container
Một tiến trình trong container gọi localhost là đang gọi chính container. Docker Desktop công bố host.docker.internal như một cái tên trỏ ngược về máy đang chạy engine; các engine Linux để nó không xác định trừ khi dịch vụ yêu cầu, và ánh xạ bên dưới làm đúng việc đó. Nhờ vậy ứng dụng nhắm tới một cái tên và một cổng thay vì địa chỉ riêng.
services:
app:
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
INTERNAL_API_HOST: "host.docker.internal:8666"Đường hầm nằm lại phía host của bước nhảy, và cổng trong biến đó là cổng proxy sẽ lắng nghe. Container mất đường hầm giờ hỏng ở một bước nhảy đã biết thay vì thử một tuyến mà nó chưa từng có.
Chọn nơi đường hầm sống
Có ba hình thức cho một dịch vụ Compose cần API riêng, và chúng khác nhau ở chỗ tiến trình nào sở hữu đường hầm. Một client VPN có thể chạy bên trong ảnh container, việc này đòi hỏi lộ ra một thiết bị đường hầm và cấp khả năng quản trị mạng đi kèm. Ứng dụng có thể chia sẻ không gian tên mạng của một container đường hầm riêng, để cả hai tiến trình thấy một ngăn xếp và một bảng định tuyến. Hoặc đường hầm có thể ở lại trên host, với một bộ chuyển tiếp hẹp từ host vào container.
Hai cách đầu kéo tệp hồ sơ, hành vi kết nối lại và chính sách phân giải vào dự án, và làm mọi dịch vụ trong tệp phụ thuộc vào sức khỏe của đường hầm. Như vậy là quá nhiều ràng buộc cho một lần gọi API. Với một ngăn xếp phát triển chỉ đọc một điểm cuối nội bộ, bộ chuyển tiếp phía host là thay đổi nhỏ nhất mà vẫn giữ thông tin đăng nhập ở nơi nhóm nền tảng quản lý chúng.
Công bố một con đường hẹp trên host
Bắt đầu từ thứ bộ chuyển tiếp thừa hưởng: chạy nó dưới tài khoản sở hữu đường hầm và các socket đi ra của nó sẽ nhận tuyến của host và bộ phân giải của host. Một khối location của nginx phủ một con đường.
server {
listen 8666;
location /search/ {
proxy_pass http://10.20.30.40:8090/;
proxy_set_header Host internal-api.example;
proxy_read_timeout 60s;
}
}Coi địa chỉ và cổng là tạm thời rồi đặt cặp mà API thực sự lắng nghe. Mỗi upstream thêm vào xứng đáng có khối location riêng, và mỗi khối chỉ nên cho qua những đường mà dịch vụ này gọi, để proxy không trở thành cánh cửa chung vào mạng riêng. Buộc bộ lắng nghe vào địa chỉ cầu cho các client đến qua host-gateway, vào loopback chỉ khi client chia sẻ không gian tên mạng của host, và không bao giờ vào 0.0.0.0. Cũng hãy chọn một cổng còn trống: một số đã bị chiếm sẽ để proxy không lắng nghe trong khi container tiếp tục hết thời gian chờ, điều không thể phân biệt với sự cố mạng mà bạn bắt đầu.
Cổng, tên và quyết định TLS
Phân giải tên chia tách giống như định tuyến. Các tra cứu công khai của container đi qua bộ phân giải của engine, nên một tên riêng phân giải được trên host sẽ không phân giải được bên trong container. Proxy là thành phần phân giải tên riêng, vì nó thừa hưởng bộ phân giải của host.
TLS là quyết định bị hoãn lại rồi sau đó giải thích lần hỏng tiếp theo. Nếu proxy chuyển tiếp byte nguyên vẹn, container thấy chứng chỉ của chính API và cần CA nội bộ trong kho tin cậy của nó. Nếu proxy kết thúc TLS, sự tin cậy đó chuyển sang host và ứng dụng bắt đầu dựng liên kết từ tiêu đề host mà nó nhận. Chọn một cách sắp xếp và áp dụng cho mọi tài nguyên, vì chuyển hướng do cách kia phát ra trỏ tới một tên máy mà container không thể phân giải.
Kiểm chứng từ bên trong dịch vụ
Gửi yêu cầu từ container, không phải từ host: một curl đơn giản tới đường của proxy, rồi tới kiểm tra sức khỏe của chính ứng dụng. Khi proxy trả lời mà ứng dụng vẫn hỏng, hãy so ba thứ: URL gốc mà nó dựng, bất kỳ biến proxy nào trong môi trường của nó, và CA mà nó tin. Tất cả đều nằm trong môi trường và nhật ký của container, và sửa bất kỳ thứ nào trong đó đều để VPN yên.
Viết cách sắp xếp đã chọn vào README của dự án khi còn mới. Nếu không, người tiếp theo gặp lần hết thời gian chờ này sẽ dành đúng buổi chiều đó để phát hiện lại rằng đường hầm sống trên host.