რატომ უგულებელყოფენ Docker-ის კონტეინერები VPN-ის DNS გადამწყვეტს
კონტეინერი გაშვებისას ჰოსტის გადამწყვეტს აკოპირებს, ამიტომ VPN, რომელიც DNS-ს მოგვიანებით გადაწერს, მის შიგნით უხილავი რჩება. გადაეცით გადამწყვეტი ცხადად.
VPN ჩართულია, ბრაუზერი შიდა საიტებს აღწევს, და კონტეინერი მაინც ვერ ხსნის იმავე სახელებს. პაკეტის ინსტალაცია იღუპება სახელის გადაწყვეტის შეცდომით, მაგალითად EAI_AGAIN, ან აპლიკაცია ვერ პოულობს მონაცემთა ბაზის ჰოსტს, რომელსაც ჰოსტის მანქანა ყოველგვარი საჩივრის გარეშე ხსნის. კონტეინერი არ იყენებს იმ გადამწყვეტს, რომელიც VPN-მა დააყენა. Docker-მა ჰოსტის გადამწყვეტის კონფიგურაცია კონტეინერის შექმნისას დააკოპირა, და ამის შემდეგ ვერაფერმა ის ხელახლა არ დააკოპირა.
გადამწყვეტის ორი ხედი ერთ მანქანაზე
Linux-ზე Docker შექმნის მომენტში თითოეულ კონტეინერს აძლევს ჰოსტის გადამწყვეტის კონფიგურაციის ასლს, ფილტრავს loopback მისამართებს და 127.0.0.11-ზე ატარებს ჩაშენებულ DNS სერვერს, რომელიც მოთხოვნებს გარეთ გადასცემს. VPN კლიენტი, რომელიც /etc/resolv.conf-ს კონტეინერის გაშვების შემდეგ გადაწერს, მის შიგნით არაფერს ცვლის. კონტეინერის გადატვირთვა მხოლოდ მაშინ ეხმარება, როცა იმ მომენტში ჰოსტის გადამწყვეტი შემთხვევით სწორია.
Docker Desktop macOS-ზე ან Windows-ზე ფენას ამატებს, რადგან დემონი ვირტუალურ მანქანაში ცხოვრობს. შეიძლება ჰოსტის VPN გადამწყვეტი არასოდეს იყოს ხილული იმ VM-ისთვის, ამიტომ გადატვირთვა საერთოდ არაფერს ცვლის. გადაწყვეტის არჩევამდე შეადარეთ ორი ხედი: docker exec mycontainer cat /etc/resolv.conf ჰოსტის გადამწყვეტების სიის გვერდით.
კონტეინერი, რომელიც საჯარო გადამწყვეტს ჩამოთვლის, მაშინ როცა ჰოსტი შიდას ჩამოთვლის, საჯარო სახელებს გადაწყვეტს და შიდაზე ჩავარდება. ეს გაყოფა ამ პრობლემის ხელმოწერაა.
ვარიანტი A: გვირაბის გადამწყვეტის გადაცემა თითოეულ კონტეინერზე
Docker იღებს DNS პარამეტრებს თითოეული კონტეინერისთვის, და ეს ყველაზე მცირე მომუშავე ცვლილებაა. ჯერ წაიკითხეთ VPN-ის გადამწყვეტის მისამართები: scutil --dns macOS-ზე, resolvectl status ან კლიენტის საკუთარი სტატუსის გამომავალი Linux-ზე. შემდეგ გაუშვით კონტეინერი მათთან ერთად, მაგალითად docker run --dns 192.168.2.1 --dns 192.168.123.1 myimage. Compose-ში იგივე პარამეტრი სერვისის ქვეშ მდებარე სიაა, სადაც ის ვერსიათა კონტროლში ცხოვრობს და არა ვიღაცის shell-ის ისტორიაში.
/etc/docker/daemon.json-ში dns მასივი ყოველ ახალ კონტეინერზე ვრცელდება, რაც უფრო მოწესრიგებულად ჟღერს და ასე არ არის. ის ასევე ვრცელდება მაშინ, როცა გვირაბი გათიშულია, და მაშინ მხოლოდ VPN-ით ხელმისაწვდომი გადამწყვეტი ჩვეულებრივ გამოსახულების ჩამოტვირთვას ამტვრევს. კონტეინერისეული პარამეტრები უფრო ადვილად დასაბუთებადი და უფრო ადვილად გასაუქმებელია.
ვარიანტი B: კონტეინერმა ჰოსტის ქსელი გაიზიაროს
ჰოსტის ქსელი ასლს სრულად გვერდს უვლის, რადგან კონტეინერი ჰოსტის გადამწყვეტსა და ჰოსტის გვირაბს იყენებს. ის ასევე აშორებს ქსელურ იზოლაციას, რომელიც ალბათ გინდოდათ, და Docker Desktop-ის ქვეშ ერთნაირად არ იქცევა. Linux-ზე ეს პრაგმატული არჩევანია ერთჯერადი ხელსაწყოსთვის, რომელმაც შიდა სახელები უნდა გადაწყვიტოს.
კონსტრუირებისთვის არც ერთი ვარიანტი არ ვრცელდება, რადგან კონსტრუირების ნაბიჯები გაშვების დროის დროშებს არ მემკვიდრეობს. ააშენეთ ჰოსტის ქსელით იქ, სადაც პლატფორმა იძლევა საშუალებას, ან დამოკიდებულებების ინსტალაცია შეინარჩუნეთ იმ ეტაპზე, რომელსაც გვირაბი არ სჭირდება.
რას არც ერთი ვარიანტი არ ასწორებს
DNS მისამართი უსარგებლოა, თუ კონტეინერს მისკენ მარშრუტი არ აქვს. VPN გადამწყვეტი ჩვეულებრივ გვირაბის მისამართთა სივრცეში ზის, ამიტომ კონტეინერს იმ პრეფიქსისკენ გზა სჭირდება. Docker-ის ნაგულისხმევი ხიდი ჩვეულებრივ ჰოსტის გავლით გარეთ მარშრუტიზაციას აკეთებს, და ეს საკმარისია, როცა ჰოსტს გვირაბის მარშრუტი აქვს და გადაცემა ჩართულია. საკუთარი მისამართთა პულებით მორგებული ხიდური ქსელები შეიძლება VPN-ის ქვექსელს შეეჯახოს, და მაშინ მოთხოვნები სულ სხვაგან მიდის.
სანამ თავად გადამწყვეტს გამართავთ, შეამოწმეთ Docker ქსელის ქვექსელი VPN-ის ქვექსელთან. გადაფარვა წარმოქმნის ჩავარდნას, რომელიც ზუსტად გატეხილ DNS სერვერს ჰგავს.
შეამოწმეთ კონტეინერის შიგნით
სცადეთ getent hosts db.internal-ით კონტეინერის შიგნით და არა ბრაუზერით ან ენის გაშვების გარემოთი, რადგან ისინი საკუთარ DNS პოლიტიკასა და საკუთარ ქეშს იყენებენ. თუ getent სახელს ხსნის და აპლიკაცია მაინც ჩავარდება, გადამწყვეტი ახლა სწორია და დარჩენილი პრობლემა აპლიკაციის დონეზეა. თუ არ ხსნის, DNS ნაბიჯი დასრულებული არ არის.
DNS პარამეტრების შეცვლის შემდეგ კონტეინერი ხელახლა შექმენით. მოქმედ კონტეინერში /etc/resolv.conf-ის რედაქტირება მასთან ერთად ქრება და კონფიგურაციის პრობლემას ზუსტად იმდენ ხანს მალავს, რამდენიც ვინმეს მის გადატვირთვას სჭირდება.