Próbuję utworzyć kontener Docker, który działa jak pełna maszyna wirtualna. Wiem, że mogę użyć instrukcji EXPOSE w pliku Docker, aby odsłonić port, i mogę użyć -p
flagi z, docker run
aby przypisać porty, ale czy po uruchomieniu kontenera istnieje polecenie otwarcia / mapowania dodatkowych portów na żywo?
Załóżmy na przykład, że mam kontener Docker z uruchomionym sshd. Ktoś inny używający kontenera ssh i instaluje httpd. Czy istnieje sposób na ujawnienie portu 80 w kontenerze i zamapowanie go na port 8080 na hoście, aby ludzie mogli odwiedzić serwer WWW działający w kontenerze bez jego ponownego uruchamiania?
Odpowiedzi:
Nie można tego zrobić za pomocą Dockera, ale można uzyskać dostęp do nieosłoniętego portu kontenera z komputera hosta.
jeśli masz kontener, który z czymś działającym na jego porcie 8000, możesz uruchomić
Aby uzyskać adres IP kontenera, uruchom 2 polecenia:
Wewnętrznie Docker uruchamia się, aby wywołać iptables po uruchomieniu obrazu, więc być może niektóre warianty będą działać.
aby odsłonić port kontenera 8000 na porcie hostów lokalnych 8001:
Jednym ze sposobów rozwiązania tego problemu jest skonfigurowanie innego kontenera z żądanym mapowaniem portów i porównanie wyników iptables-save (musiałem jednak usunąć niektóre inne opcje, które zmuszają ruch do przejścia przez doker pełnomocnik).
UWAGA: jest to dokowanie niwelujące, więc należy to zrobić ze świadomością, że może on tworzyć niebieski dym
LUB
Inną alternatywą jest poszukiwanie opcji (nowa? Post 0.6.6?) -P - która wykorzysta losowe porty hosta, a następnie połączy je.
LUB
w wersji 0.6.5 możesz użyć funkcji LINK, aby wywołać nowy kontener, który będzie komunikował się z istniejącym, z dodatkowym przekazywaniem flag -p tego kontenera? (Nie korzystałem jeszcze z LINK-ów)
LUB
z dokerem 0.11? możesz użyć,
docker run --net host ..
aby podłączyć kontener bezpośrednio do interfejsów sieciowych hosta (tzn. sieć nie ma odstępów między nazwami), a zatem wszystkie porty otwierane w kontenerze są widoczne.źródło
CONTAINER_IP=$(docker inspect container_name | jq .[0].NetworkSettings.IPAddress | sed -r 's/\"([^\"]+)\"/\1/''])'); iptables -t nat -A DOCKER -p tcp --dport 8001 -j DNAT --to-destination ${CONTAINER_IP}:8000
jq
ised
można użyć-f
opcjidocker inspect
:CONTAINER_IP=$(docker inspect -f '{{ .NetworkSettings.IPAddress }}' container_name)
jshon -e 0 -e NetworkSettings -e Networks -e bridge -e IPAddress -u
Oto co bym zrobił:
źródło
sudo docker
a nie tylkodocker
?docker commit
byłem gotowy ponownie przetestować aplikację zamiast spędzać godziny na ponownej instalacji wszystkiego.Chociaż nie możesz ujawnić nowego portu istniejącego kontenera, możesz uruchomić nowy kontener w tej samej sieci Docker i zmusić go do przekazywania ruchu do oryginalnego kontenera.
Przykład działania
Uruchom usługę internetową, która nasłuchuje na porcie 80, ale nie ujawniaj swojego portu wewnętrznego 80 (ups!):
Znajdź adres IP swojej sieci Docker:
Uruchom
verb/socat
z widocznym portem 8080 i poproś go o przekazywanie ruchu TCP do portu 80 tego adresu IP:Możesz teraz uzyskać dostęp do pastebin na http: // localhost: 8080 / , a twoje żądania idą do
socat:1234
tego, do którego je przesyła dalejpastebin:80
, a odpowiedź przechodzi tą samą ścieżką w odwrotną stronę.źródło
verb/socat:alpine
, ponieważ jego obraz ma 5% powierzchni (chyba że napotkasz niezgodności libc lub DNS ).alpine/socat
--net myfoldername_default
do mojejverb/socat
komendy uruchamiania, ponieważ uruchomiłem nienaświetlony kontener w kompozycji dokera, która tworzy sieć.Hacki IPtables nie działają, przynajmniej w Docker 1.4.1.
Najlepszym sposobem byłoby uruchomienie innego kontenera z odsłoniętym portem i przekaźnik z socat. Oto, co zrobiłem, aby (tymczasowo) połączyć się z bazą danych za pomocą SQLPlus:
Plik Docker:
źródło
FROM
obrazu podstawowego co kontener DB, aby efektywnie wykorzystać zasoby.Oto inny pomysł. Użyj SSH do przekierowania portów; ma to tę zaletę, że działa również w systemie OS X (i prawdopodobnie w systemie Windows), gdy host Dockera jest maszyną wirtualną.
źródło
Musiałem poradzić sobie z tym samym problemem i byłem w stanie go rozwiązać bez zatrzymywania któregokolwiek z moich uruchomionych kontenerów. To rozwiązanie jest aktualne od lutego 2016 r. Przy użyciu Docker 1.9.1. W każdym razie ta odpowiedź jest szczegółową wersją odpowiedzi @ ricardo-branco, ale bardziej szczegółową dla nowych użytkowników.
W moim scenariuszu chciałem tymczasowo połączyć się z MySQL działającym w kontenerze, a ponieważ inne kontenery aplikacji są z nim połączone, zatrzymywanie, rekonfigurowanie i ponowne uruchamianie kontenera bazy danych nie było uruchomieniem.
Ponieważ chciałbym uzyskać dostęp do bazy danych MySQL zewnętrznie (z Sequel Pro poprzez tunelowanie SSH), użyję portu
33306
na hoście. (Nie3306
, na wypadek, gdyby działała zewnętrzna instancja MySQL.)Około godziny poprawiania iptables okazało się bezowocne, mimo że:
Krok po kroku, oto co zrobiłem:
Edytuj
dockerfile
, umieszczając to w środku:Następnie zbuduj obraz:
Następnie uruchom go, łącząc się z działającym kontenerem. (Użyj
-d
zamiast-rm
trzymać go w tle, dopóki nie zostanie wyraźnie zatrzymany i usunięty. W tym przypadku chcę, aby działał tylko tymczasowo).źródło
Aby dodać do akceptowanego
iptables
rozwiązania odpowiedzi , musiałem uruchomić jeszcze dwa polecenia na hoście, aby otworzyć je na świat zewnętrzny.Uwaga: otwierałem port https (443), mój wewnętrzny adres IP dokera to
172.17.0.2
Uwaga 2: Te reguły są tymczasowe i będą obowiązywać tylko do momentu ponownego uruchomienia kontenera
źródło
Możesz użyć SSH, aby utworzyć tunel i odsłonić swój kontener na hoście.
Możesz to zrobić na dwa sposoby, od kontenera do hosta i od hosta do kontenera. Ale potrzebujesz narzędzia SSH, takiego jak OpenSSH w obu (klient w jednym i serwer w innym).
Na przykład w kontenerze możesz to zrobić
Adres IP kontenera można znaleźć w tym wierszu (w kontenerze):
Następnie na hoście możesz po prostu zrobić:
źródło
Jeśli żadna odpowiedź nie zadziała dla kogoś - sprawdź, czy docelowy kontener jest już uruchomiony w sieci dokerów:
Zapisz na później w zmiennej
$NET_NAME
:Jeśli tak, należy uruchomić kontener proxy w tej samej sieci.
Następnie wyszukaj alias kontenera:
Zapisz na później w zmiennej
$ALIAS
:Teraz uruchom
socat
w kontenerze w sieci,$NET_NAME
aby połączyć się z$ALIAS
odsłoniętym (ale nie opublikowanym) portem kontenera ed:źródło
Możesz użyć sieci nakładek, takiej jak Weave Net , która przypisze unikalny adres IP do każdego kontenera i pośrednio udostępni wszystkie porty każdej kontenerowej części sieci.
Weave zapewnia również integrację sieci hosta . Jest domyślnie wyłączony, ale jeśli chcesz również uzyskać dostęp do adresów IP kontenera (i wszystkich jego portów) z hosta, możesz uruchomić, po prostu uruchom
weave expose
.Pełne ujawnienie: pracuję w Weaveworks.
źródło
Jest poręczne opakowanie HAProxy.
To tworzy HAProxy do docelowego kontenera. bułka z masłem.
źródło
Oto kilka rozwiązań:
https://forums.docker.com/t/how-to-expose-port-on-running-container/3252/12
źródło
Przeczytaj najpierw odpowiedź Ricardo . To zadziałało dla mnie.
Istnieje jednak scenariusz, w którym nie zadziała to, jeśli uruchomiony kontener został wyrzucony przy użyciu narzędzia dokującego-komponuj. Wynika to z faktu, że program dokujący-komponuj (korzystam z programu dokującego 1.17) tworzy nową sieć. Można rozwiązać ten scenariusz
docker network ls
Następnie dołącz następujące elementy
docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus --net network_name
źródło
Nie jest możliwe mapowanie portów na żywo, ale istnieje wiele sposobów na przekazanie kontenerowi Docker poziomu odpowiadającego rzeczywistemu interfejsowi, jaki miałaby maszyna wirtualna.
Interfejsy Macvlan
Docker zawiera teraz sterownik sieci Macvlan . Umożliwia to podłączenie sieci Docker do interfejsu „świata rzeczywistego” i umożliwia przypisanie tych adresów sieciowych bezpośrednio do kontenera (podobnie jak tryb mostkowania maszyn wirtualnych).
pipework
może także odwzorować prawdziwy interfejs na kontener lub skonfigurować interfejs podrzędny w starszych wersjach Dockera.Routing IP
Jeśli masz kontrolę nad siecią, możesz kierować dodatkowe sieci do hosta Docker w celu użycia w kontenerach.
Następnie przypisz tę sieć do kontenerów i skonfiguruj hosta Docker do kierowania pakietów przez sieć dokerów.
Wspólny interfejs hosta
Ta
--net host
opcja umożliwia udostępnienie interfejsu hosta w kontenerze, ale prawdopodobnie nie jest to dobra konfiguracja do uruchamiania wielu kontenerów na jednym hoście ze względu na wspólną naturę.źródło