თქვენი Compose სერვისი დროის ლიმიტს კარგავს იმ API-სთან, რომელსაც იმავე მანქანის ბრაუზერი უჩივლებლად ხსნის. სწორედ ეს სხვაობაა მინიშნება: მომუშავე მოთხოვნა გამოდის ჰოსტიდან VPN გვირაბით, ხოლო ჩამოკიდებული მოთხოვნა — კონტეინერიდან საკუთარი ქსელური დასტით. კონტეინერის შიგნით არაფერმა არ იცის გვირაბის მარშრუტები, ამიტომ კერძო დანიშნულება მიუწვდომელი რჩება, როგორც არ უნდა დაიწეროს სახელი. გამოსავალი ჰოსტის გავლით განზრახ ნახტომია და არა უფრო ჭკვიანური მარშრუტიზაციის ცხრილი.

დაიწყეთ იმით, თუ რატომ განსხვავდება ორი გზა, შემდეგ გადაწყვიტეთ სად უნდა იცხოვროს გვირაბმა.

რატომ მუშაობს ჰოსტი და რატომ არა კონტეინერი

გვირაბის აწევა ჰოსტს აძლევს ინტერფეისს, მარშრუტების ერთობლიობას და, როგორც წესი, VPN-ის მიერ მოწოდებულ რეზოლვერის ჩანაწერს. კონტეინერი ამიდან არაფერს მემკვიდრეობით იღებს: ის იწყება ერთი ინტერფეისით ძრავის ხიდზე და ნაგულისხმევი მარშრუტით, რომელიც ამ ხიდზე მიუთითებს. ჰოსტზე დაყენებული მარშრუტები უხილავია ყველაფრისთვის, რაც ამ სახელთა სივრცის შიგნით მუშაობს.

ამიტომ სიმპტომები არათანმიმდევრულად გამოიყურება და არა უბრალოდ გატეხილად. ჰოსტი წყვეტს კერძო სახელს და უკავშირდება, რადგან იქ არსებობს როგორც სახელი, ისე მარშრუტი. კონტეინერი თავის პაკეტს აგზავნის კერძო მისამართზე, სადაც ხიდის გზაზე ვერაფერი მიაღწევს, და მოთხოვნა დროის ლიმიტს გადის. სახელის კონტეინერის hosts ფაილში დამატება არაფერს ცვლის, რადგან თავად მისამართი მიუწვდომელია იქიდან, სადაც კონტეინერი ზის.

მიაღწიეთ ჰოსტს კონტეინერის შიგნიდან

კონტეინერში მყოფი პროცესი, რომელიც localhost-ს რეკავს, კონტეინერს რეკავს. Docker Desktop აქვეყნებს host.docker.internal-ს, როგორც სახელს, რომელიც უკან ძრავის მამოძრავებელ მანქანაზე მიუთითებს; Linux-ის ძრავები მას განუსაზღვრელს ტოვებენ, თუ სერვისი არ მოითხოვს, და სწორედ ამას აკეთებს ქვემოთ მოცემული დაკავშირება. ამით აპლიკაცია მიზნად ისახავს სახელსა და პორტს კერძო მისამართის ნაცვლად.

services:
  app:
    extra_hosts:
      - "host.docker.internal:host-gateway"
    environment:
      INTERNAL_API_HOST: "host.docker.internal:8666"

გვირაბი რჩება ნახტომის ჰოსტის მხარეს, და ამ ცვლადში მოცემული პორტი არის ის, რომელზეც პროქსი მოისმენს. გვირაბის დაკარგული კონტეინერი ახლა ერთ ცნობილ ნახტომზე ფეილდება იმის ნაცვლად, რომ სცადოს მარშრუტი, რომელიც არასდროს ჰქონია.

აირჩიეთ სად ცხოვრობს გვირაბი

კერძო API-ს მჭირდება Compose სერვისისთვის სამი ფორმაა შესაძლებელი, და ისინი იმით განსხვავდებიან, რომელი პროცესი ფლობს გვირაბს. VPN კლიენტი შეიძლება მუშაობდეს კონტეინერის იმიჯის შიგნით, რაც მოითხოვს გვირაბის მოწყობილობის გამოვლენას და მასთან მომავალი ქსელური ადმინისტრირების შესაძლებლობის მიცემას. აპლიკაციას შეუძლია გაიზიაროს ცალკე გვირაბ-კონტეინერის ქსელური სახელთა სივრცე, რათა ორივე პროცესმა ერთი დასტა და ერთი მარშრუტიზაციის ცხრილი დაინახოს. ან გვირაბი შეიძლება დარჩეს ჰოსტზე, ვიწრო გამტარებით ჰოსტიდან კონტეინერში.

პირველი ორი პროფილის ფაილებს, ხელახალი დაკავშირების ქცევას და რეზოლვერის პოლიტიკას ეწევა პროექტში და ფაილის ყოველ სერვისს გვირაბის ჯანმრთელობაზე დამოკიდებულს ხდის. ეს ერთი API გამოძახებისთვის ძალიან ბევრი კავშირია. ერთ შიდა ბოლო წერტილს რომ კითხულობს განვითარების დასტა, ჰოსტის მხარეს გამტარებელი ყველაზე მცირე ცვლილებაა, რომელიც მაინც ინახავს სერტიფიკატებს იქ, სადაც პლატფორმის გუნდი მართავს მათ.

გამოაქვეყნეთ ერთი ვიწრო გზა ჰოსტზე

დაიწყეთ იმით, თუ რას მემკვიდრეობით იღებს გამტარებელი: გაუშვით ის იმ ანგარიშით, რომელიც ფლობს გვირაბს, და მისი გამავალი სოკეტები აიღებენ ჰოსტის მარშრუტებს და ჰოსტის რეზოლვერს. nginx-ის ერთი location ბლოკი ერთ გზას ფარავს.

server {
    listen 8666;
    location /search/ {
        proxy_pass http://10.20.30.40:8090/;
        proxy_set_header Host internal-api.example;
        proxy_read_timeout 60s;
    }
}

მოექეცით მისამართსა და პორტს როგორც დროებით შემცვლელებს და ჩასვით ის წყვილი, რომელზეც API ნამდვილად ისმენს. ყოველი დამატებითი upstream იმსახურებს საკუთარ location ბლოკს, და ყოველმა ბლოკმა მხოლოდ ის გზები უნდა დაუშვას, რომლებსაც ეს სერვისი იძახებს, რათა პროქსი კერძო ქსელში საერთო კარად არ იქცეს. მსმენელი მიაბით ხიდის მისამართს host-gateway-ით მოსული კლიენტებისთვის, loopback-ს მხოლოდ მაშინ, როცა კლიენტი ჰოსტის ქსელურ სახელთა სივრცეს იზიარებს, და არასდროს 0.0.0.0-ს. აირჩიეთ ისეთი პორტიც, რომელიც ჯერ თავისუფალია: უკვე დაკავებული ნომერი პროქსის უმოსმენელს ტოვებს, სანამ კონტეინერი დროის ლიმიტს აგრძელებს, რაც არ განსხვავდება იმ ქსელური ხარვეზისგან, რომლითაც დაიწყეთ.

პორტები, სახელები და TLS-ის გადაწყვეტილება

სახელების გარჩევა ისე იყოფა, როგორც მარშრუტიზაცია. კონტეინერის საჯარო ძიებები ძრავის რეზოლვერზე გადის, ამიტომ ჰოსტზე გარჩეული კერძო სახელი კონტეინერის შიგნით არ გარჩევდება. პროქსია ის კომპონენტი, რომელიც კერძო სახელს გარჩევს, რადგან ის ჰოსტის რეზოლვერს მემკვიდრეობით იღებს.

TLS არის გადაწყვეტილება, რომელიც გადაიდება და შემდეგ ხსნის შემდეგ ხარვეზს. თუ პროქსი ბაიტებს უცვლელად გადასცემს, კონტეინერი ხედავს API-ის საკუთარ სერტიფიკატს და მის სანდოობის საცავში შიდა CA სჭირდება. თუ პროქსი TLS-ს ამთავრებს, ეს ნდობა ჰოსტზე გადადის და აპლიკაცია იწყებს ბმულების აგებას მიღებული host სათაურიდან. აირჩიეთ ერთი წყობა და გამოიყენეთ ყოველ რესურსზე, რადგან მეორის მიერ გამოცემული გადამისამართება მიუთითებს ჰოსტის სახელზე, რომლის გარჩევასაც კონტეინერი ვერ შეძლებს.

შეამოწმეთ სერვისის შიგნიდან

მოთხოვნა გაგზავნეთ კონტეინერიდან და არა ჰოსტიდან: ჩვეულებრივი curl პროქსის გზაზე, შემდეგ თავად აპლიკაციის ჯანმრთელობის შემოწმება. როცა პროქსი პასუხობს, მაგრამ აპლიკაცია მაინც ფეილდება, შეადარეთ სამი რამ: ის ბაზისური URL, რომელსაც ის აშენებს, ნებისმიერი პროქსი ცვლადი მის გარემოში, და ის CA, რომელიც მას სჯერა. ყველა მათგანი კონტეინერის გარემოსა და ჟურნალებშია, და რომელიმეს გასწორება VPN-ს ხელუხლებლად ტოვებს.

ჩაწერეთ არჩეული წყობა პროექტის README-ში, სანამ ის ახალია. წინააღმდეგ შემთხვევაში შემდეგი ადამიანი, ვინც ამ დროის ლიმიტს წააწყდება, იმავე შუადღეს გაატარებს იმის ხელახლა აღმოჩენაში, რომ გვირაბი ჰოსტზე ცხოვრობს.

დაკავშირებული სტატიები