Mam aplikację, która wykonuje różne zabawne rzeczy za pomocą Git (np. Uruchamianie git clone i git push) i próbuję to dokować.
Mam problem, ale muszę dodać klucz SSH do kontenera, aby mógł go użyć „użytkownik”.
Próbowałem go skopiować /root/.ssh/
, zmienić $HOME
, utworzyć git ssh i wciąż nie mam szczęścia.
Oto plik Docker w celach informacyjnych:
#DOCKER-VERSION 0.3.4
from ubuntu:12.04
RUN apt-get update
RUN apt-get install python-software-properties python g++ make git-core openssh-server -y
RUN add-apt-repository ppa:chris-lea/node.js
RUN echo "deb http://archive.ubuntu.com/ubuntu precise universe" >> /etc/apt/sources.list
RUN apt-get update
RUN apt-get install nodejs -y
ADD . /src
ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa
RUN cd /src; npm install
EXPOSE 808:808
CMD [ "node", "/src/app.js"]
app.js
uruchamia polecenia git jak git pull
Odpowiedzi:
Jest to trudniejszy problem, jeśli musisz korzystać z SSH podczas kompilacji. Na przykład, jeśli używasz
git clone
, lub w moim przypadkupip
inpm
do pobrania z prywatnego repozytorium.Rozwiązaniem, które znalazłem, jest dodanie kluczy za pomocą
--build-arg
flagi. Następnie możesz użyć nowego--squash
polecenia eksperymentalnego (dodano 1.13) do scalenia warstw, aby klucze nie były już dostępne po usunięciu. Oto moje rozwiązanie:Kompilacja polecenia
Plik Docker
Aktualizacja: Jeśli korzystasz z Docker 1.13 i masz eksperymentalne funkcje, możesz dołączyć
--squash
do komendy build, która scali warstwy, usuwa klucze SSH i ukrywa jedocker history
.źródło
id_rsa.pub
pliku, ponieważ nie jest to wymagane.$(openssl rsa -in ~/.ssh/id_rsa)
zamiast niegoOkazuje się, że podczas korzystania z Ubuntu ssh_config jest niepoprawny. Musisz dodać
do pliku Docker, aby rozpoznać twój klucz ssh.
źródło
RUN echo " Host example.com" >> /root/.ssh/config RUN echo " User <someusername>" >> /root/.ssh/config
Klucz ssh pozostaje przechowywany w obrazie, nawet jeśli usuniesz klucz w poleceniu warstwy po dodaniu go (zobacz komentarze w tym poście ).
W moim przypadku jest to w porządku, więc używam tego:
źródło
Jeśli używasz komponowania dokowania , łatwym wyborem jest przekazanie agenta SSH w ten sposób:
źródło
SSH_AUTH_SOCK
jest zmienną, która zawiera ścieżkę do agenta sshSSH_AUTH_SOCK
blog.joncairns.com/2013/12/understanding-ssh-agent-and-ssh-add$SSH_AUTH_SOCK
, musisz zamontować tę ścieżkę -/run/host-services/ssh-auth.sock
.Rozszerzając odpowiedź Petera Graingera Byłem w stanie korzystać z wersji wieloetapowej dostępnej od Dockera 17.05. Oficjalna strona zawiera:
Mając to na uwadze, mój przykład
Dockerfile
obejmuje trzy etapy budowy. Ma on na celu stworzenie produkcyjnego obrazu aplikacji WWW klienta..dockerignore
powtarza zawartość.gitignore
pliku (zapobiega kopiowaniunode_modules
i wynikowymdist
katalogom projektu):Przykład polecenia, aby zbudować obraz:
Jeśli twój prywatny klucz SSH nie ma hasła, podaj pusty
SSH_KEY_PASSPHRASE
argument.Tak to działa:
1). Tylko na pierwszym etapie
package.json
,yarn.lock
pliki i prywatny klucz SSH są kopiowane do pierwszej pośredniej obrazu nazwiesources
. Aby uniknąć dalszych monitów o hasło SSH, jest ono automatycznie dodawane dossh-agent
. Wreszcieyarn
polecenie instaluje wszystkie wymagane zależności z NPM i klonuje prywatne repozytoria git z Bitbucket przez SSH.2). Drugi etap buduje i minimalizuje kod źródłowy aplikacji internetowej i umieszcza go w
dist
katalogu następnego obrazu pośredniego o nazwieproduction
. Zauważ, że zainstalowany kod źródłowynode_modules
jest kopiowany z obrazu o nazwiesources
wyprodukowanej w pierwszym etapie przez ten wiersz:Prawdopodobnie może to być również następująca linia:
Mamy tylko
node_modules
katalog z pierwszej pośredniej obrazu tutaj, noSSH_KEY
iSSH_KEY_PASSPHRASE
już argumenty. Cała reszta wymagana do kompilacji jest kopiowana z naszego katalogu projektu.3). W trzecim etapie zmniejszamy rozmiar końcowego obrazu, który zostanie oznaczony jako
ezze/geoport:0.6.0
, włączając tylkodist
katalog z drugiego obrazu pośredniego o nazwieproduction
i instalując Node Express do uruchomienia serwera WWW.Wyświetlanie listy obrazów daje takie dane wyjściowe:
gdzie nieoznaczone obrazy odpowiadają pierwszemu i drugiemu pośredniemu etapowi kompilacji.
Jeśli uciekniesz
nie będzie widać żadnych wzmianek
SSH_KEY
iSSH_KEY_PASSPHRASE
w końcowym obrazie.źródło
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
ale kiedy sprawdzam inny RUN lub nawet w tym samym RUN wykonanie poleceniassh-add -l
powoduje, że „Agent nie ma tożsamości”. Zaczynam ściągać włosy, jakieś myśli?Aby wstrzyknąć ci klucz ssh, w kontenerze masz wiele rozwiązań:
Używając pliku Docker z
ADD
instrukcją, możesz wstrzyknąć go podczas procesu kompilacjiPo prostu robienie czegoś takiego
cat id_rsa | docker run -i <image> sh -c 'cat > /root/.ssh/id_rsa'
Korzystanie z
docker cp
polecenia, które pozwala wstrzykiwać pliki podczas działania kontenera.źródło
apt-get install openssh-server
i wkładając mój klucz do /root/.ssh/id_rsa i działało dobrze. Jakiego obrazu używasz?Jednym z rozwiązań wieloplatformowych jest użycie montowania wiązania w celu udostępnienia
.ssh
folderu hosta w kontenerze:Takie podejście, podobnie jak przekazywanie agentów, sprawi, że klucze publiczne będą dostępne dla kontenera. Dodatkową zaletą jest to, że działa również z użytkownikiem innym niż root i zapewni ci połączenie z GitHub. Jednym zastrzeżeniem, które należy wziąć pod uwagę, jest to, że cała zawartość (w tym klucze prywatne) z
.ssh
folderu będą udostępniane, więc takie podejście jest pożądane tylko w przypadku programowania i tylko w przypadku zaufanych obrazów kontenerów.źródło
docker build
tylko podczasdocker run
docker-compose up
w moim lokalnym systemie Windows 10. Jak powinienem użyć twojego rozwiązania w tym scenariuszu?Kontenery dokowe należy postrzegać jako własne „usługi”. Aby rozdzielić obawy, należy oddzielić funkcje:
1) Dane powinny znajdować się w kontenerze danych: użyj połączonego woluminu, aby sklonować repozytorium. Ten kontener danych można następnie połączyć z potrzebującą go usługą.
2) Użyj kontenera, aby uruchomić zadanie klonowania git (tj. To tylko zadanie klonowania), łącząc z nim kontener danych podczas jego uruchamiania.
3) To samo dla klucza ssh: włóż to wolumin (jak zasugerowano powyżej) i połącz go z usługą klonowania git, gdy go potrzebujesz
W ten sposób zarówno zadanie klonowania, jak i klucz są efemeryczne i aktywne tylko w razie potrzeby.
Teraz, jeśli twoja aplikacja jest interfejsem git, możesz rozważyć zastosowanie interfejsów API REST github lub bitbucket bezpośrednio do wykonania swojej pracy: do tego właśnie zostały zaprojektowane.
źródło
Ta linia stanowi problem:
Określając pliki, które chcesz skopiować do obrazu, możesz używać tylko ścieżek względnych - względem katalogu, w którym znajduje się plik Docker. Zamiast tego powinieneś użyć:
I umieść plik id_rsa w tym samym katalogu, w którym znajduje się plik Docker.
Sprawdź to, aby uzyskać więcej informacji: http://docs.docker.io/reference/builder/#add
źródło
docker cp
po prostu umieszcza go w pojemniku, a nie na zdjęciu, prawda?Mieliśmy podobny problem podczas instalacji npm w czasie kompilacji dokera.
Zainspirowani rozwiązaniem Daniela van Flymena i połączeniem go z przepisem git url , znaleźliśmy nieco prostszą metodę uwierzytelniania instalacji npm z prywatnych repozytoriów github - zamiast kluczy użyliśmy tokenów oauth2.
W naszym przypadku zależności npm określono jako „git + https://github.com/ ...”
W celu uwierzytelnienia w kontenerze adresy URL muszą zostać przepisane, aby były odpowiednie do uwierzytelnienia ssh (ssh: //[email protected]/) lub uwierzytelnienia tokena (https: // $ {GITHUB_TOKEN} @ github.com /)
Komenda kompilacji:
Niestety korzystam z Dockera 1.9, więc opcja -squash jeszcze nie istnieje, w końcu trzeba ją dodać
Plik Docker:
źródło
Przekaż gniazdo uwierzytelniania ssh do kontenera:
Twój skrypt będzie mógł wykonać
git clone
.Dodatkowo: Jeśli chcesz, aby sklonowane pliki należały do określonego użytkownika, musisz go użyć,
chown
ponieważ użycie innego użytkownika niż root w kontenerze zakończy sięgit
niepowodzeniem.Możesz zrobić to publikowanie w środowisku kontenera kilka dodatkowych zmiennych:
Po sklonowaniu należy wykonać,
chown $OWNER_USER:$OWNER_GROUP -R <source_folder>
aby ustawić właściwą własność przed opuszczeniem kontenera, aby pliki były dostępne dla użytkownika innego niż root poza kontenerem.źródło
-u root:$(id -u $USER)
przynajmniej pliki należące do tej samej grupy podstawowej, co użytkownik, co powinno uczynić je przynajmniej czytelnymi,sudo
chyba że coś tworzy je z0600
uprawnieniami.-u root:$(id -u $USER)
powinno być-g
./tmp/ssh_auth.sock: No such file or directory
go teraz/tmp/ssh-vid8Zzi8UILE/agent.46016
na mojej maszynie/tmp
do twojego kontenera. Lub literówka w poleceniu uruchomienia dokera. Upewnij się, że instrukcja bind jest poprawna-v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock
: kolejność jest ważna, a średnik jest również ważny. Aby uzyskać dalszą pomoc, sprawdź dokumentację dokera .Jak skomentował już eczajk w odpowiedzi Daniela van Flymena, nie wydaje się bezpieczne usuwanie kluczy i ich używanie
--squash
, ponieważ nadal będą widoczne w historii (docker history --no-trunc
).Zamiast tego w Docker 18.09 możesz teraz korzystać z funkcji „buduj sekrety”. W moim przypadku sklonowałem prywatne repozytorium git przy użyciu mojego klucza SSH hosta z następującym plikiem w pliku Docker:
Aby móc z tego skorzystać, musisz włączyć nowy backend BuildKit przed uruchomieniem
docker build
:I musisz dodać
--ssh default
parametr dodocker build
.Więcej informacji na ten temat tutaj: https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066
źródło
ssh-add ~/.ssh/id_rsa
i 2) dodaj hosta git do znanych_hostów, tj. Dla bitbucket:RUN ssh-keyscan -H bitbucket.org >> ~/.ssh/known_hosts
Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access and the repository exists.
To pomimo przekazania--ssh default
flagi w mojej kompilacji dokera i użycia--mount=type=ssh
w poleceniu uruchomienia tam, gdzie jagit clone
. Jestem w stanie sklonować to samo repo bez problemu na komputerze kompilacji. Po prostu zawodzi w kontenerze kompilatora dokerów. Podejrzewam, że wersja Mac Dockera tak naprawdę nie przekazuje klienta ssh.Ten problem jest naprawdę denerwujący. Ponieważ nie można dodawać / kopiować żadnego pliku poza kontekstem pliku dokującego, co oznacza, że nie można po prostu połączyć ~ / .ssh / id_rsa z katalogiem /root/.ssh/id_rsa obrazu, a kiedy zdecydowanie potrzebujesz klucza do zrobienia czegoś. jak klon git z prywatnego linku repo ... podczas budowania obrazu dokera.
W każdym razie znalazłem rozwiązanie tego obejścia, nie przekonujące, ale działało dla mnie.
w twoim pliku dokera:
scenariusz do zrobienia w jednym zdjęciu:
za każdym razem, gdy musisz uruchomić kontener z tego obrazu z pewnymi wymaganiami ssh, po prostu dodaj -v dla polecenia run, na przykład:
Uruchom okno dokowane -v ~ / .ssh / id_rsa: /root/.ssh/id_rsa - nazwa polecenia obraz kontenera
Dzięki temu rozwiązaniu nie ma klucza prywatnego zarówno w źródle projektu, jak i w wbudowanym obrazie dokera, więc nie trzeba się już martwić o bezpieczeństwo.
źródło
docker cp
? Służy do „Kopiowania plików / folderów między kontenerem a hostem”.docker cp
może załatwić sprawę. Jednak w tej sytuacji potrzebowałem ssh_key podczas budowania obrazu i nie ma w tym czasie żadnego kontenera ... dzięki temu zaktualizuję moje niejasne wyrażenie.Natrafiłem dzisiaj na ten sam problem i nieco zmodyfikowana wersja z poprzednimi postami uznałem to podejście za bardziej przydatne dla mnie
(Pamiętaj, że flaga tylko do odczytu, więc kontener w żadnym wypadku nie zepsuje mojego klucza ssh).
Wewnątrz kontenera mogę teraz uruchomić:
Więc nie dostaję
Bad owner or permissions on /root/.ssh/..
błędu, który zauważył @krossźródło
ssh-agent bash -c "ssh-add..."
. Następnie mogę przekazać to prawo do uruchomienia dokera. Użyłem wszystkich poprzednich przykładóweval ssh-agent
, a następnie ssh-add i nie mogłem znaleźć sposobu, aby przekazać toeval
za pomocą polecenia uruchomienia dokera.„możesz selektywnie zezwolić zdalnym serwerom na dostęp do lokalnego agenta ssh, tak jakby działał na serwerze”
https://developer.github.com/guides/using-ssh-agent-forwarding/
źródło
Możesz także połączyć swój katalog .ssh między hostem a kontenerem, nie wiem czy ta metoda ma wpływ na bezpieczeństwo, ale może to być najłatwiejsza metoda. Coś takiego powinno działać:
Pamiętaj, że okno dokowane działa z sudo (chyba że tego nie robisz), w takim przypadku będziesz używać kluczy root ssh.
źródło
Bad owner or permissions on /root/.ssh/config
.docker run
, ale nie podczasdocker build
.Począwszy od
docker API 1.39+
(Sprawdź wersję interfejsu API za pomocądocker version
) kompilacji--ssh
dokera umożliwia opcję z gniazdem agenta lub kluczami, aby umożliwić silnikowi Docker przekazywanie połączeń agenta SSH.Kompilacja poleceń
Plik Docker
Więcej informacji:
źródło
could not parse ssh: [default=~/.ssh/id_rsa]: stat ~/.ssh/id_rsa: no such file or directory
. Użyj pełnej ścieżki, jeśli to nie działa.Jeśli nie dbasz o bezpieczeństwo swoich kluczy SSH, znajdziesz tutaj wiele dobrych odpowiedzi. Jeśli to zrobisz, najlepszą odpowiedzią, jaką znalazłem, był link w komentarzu powyżej do tego komentarza GitHub autorstwa diegocsandrim . Aby inni mogli to zobaczyć i na wypadek, gdyby repozytorium kiedykolwiek zniknęło, oto zredagowana wersja tej odpowiedzi:
Większość rozwiązań tutaj pozostawia klucz prywatny na obrazie. Jest to złe, ponieważ każdy, kto ma dostęp do obrazu, ma dostęp do twojego klucza prywatnego. Ponieważ nie wiemy wystarczająco dużo o zachowaniu się
squash
, nadal może tak być, nawet jeśli usuniesz klucz i zmiażdżysz tę warstwę.Generujemy adres URL przed podpisaniem, aby uzyskać dostęp do klucza za pomocą aws s3 cli, i ograniczamy dostęp przez około 5 minut, zapisujemy ten adres URL przed podpisaniem w pliku w katalogu repo, a następnie w pliku dokera dodajemy go do obrazu.
W pliku dockerfile mamy polecenie RUN, które wykonuje wszystkie następujące kroki: użyj wstępnego sing URL, aby uzyskać klucz ssh, uruchom instalację npm i usuń klucz ssh.
Wykonując to w jednym poleceniu, klucz ssh nie będzie przechowywany w żadnej warstwie, ale adres URL przed podpisaniem zostanie zapisany i nie stanowi to problemu, ponieważ adres URL nie będzie ważny po 5 minutach.
Skrypt kompilacji wygląda następująco:
Plik Docker wygląda następująco:
źródło
W późniejszych wersjach okna dokowanego (17.05) można używać kompilacji wieloetapowych . Jest to najbezpieczniejsza opcja, ponieważ poprzednie kompilacje mogą być używane tylko przez następną kompilację, a następnie są niszczone
Aby uzyskać więcej informacji, zobacz odpowiedź na moje pytanie dotyczące przepływu stosu
źródło
Zwięzły przegląd wyzwań związanych z SSH wewnątrz kontenerów Docker znajduje się tutaj . Aby połączyć się z zaufanymi pilotami z poziomu kontenera bez ujawniania tajemnic, istnieje kilka sposobów:
~/.ssh
w kontenerze. (Tylko rozwój, potencjalnie niepewny)Poza tym istnieje również możliwość korzystania z magazynu kluczy działającego w osobnym kontenerze dokowanym, dostępnym w czasie wykonywania podczas korzystania z funkcji Utwórz. Wadą tego rozwiązania jest dodatkowa złożoność związana z maszyną niezbędną do utworzenia magazynu kluczy i zarządzania nim, takiego jak Vault firmy HashiCorp .
W przypadku użycia klucza SSH w autonomicznym kontenerze Docker zapoznaj się z powyższymi metodami i rozważ ich wady w zależności od konkretnych potrzeb. Jeśli jednak uruchamiasz się w trybie tworzenia i chcesz udostępnić klucz do aplikacji w czasie wykonywania (odzwierciedlający praktyczne funkcje PO), spróbuj tego:
docker-compose.env
plik i dodaj go do swojego.gitignore
pliku.docker-compose.yml
i dodajenv_file
do usługi wymagającej klucza.process.node.DEPLOYER_RSA_PUBKEY
W przypadku aplikacji Node.js.Powyższe podejście jest idealne do opracowywania i testowania i chociaż może spełniać wymagania produkcyjne, w produkcji lepiej jest użyć jednej z innych metod określonych powyżej.
Dodatkowe zasoby:
źródło
Do budowania kontenerów można użyć kompilacji wieloetapowej. Możesz zastosować następujące podejście:
Etap 1 budowanie obrazu za pomocą ssh
Etap 2: zbuduj swój kontener
dodaj atrybut env do pliku tworzenia:
następnie przekaż argumenty ze skryptu budowania w następujący sposób:
I usuń pośredni pojemnik dla bezpieczeństwa. Pomoże Ci to wiwatować.
źródło
Prostym i bezpiecznym sposobem na osiągnięcie tego bez zapisywania klucza w warstwie obrazu Docker lub przechodzenia przez gimnastykę ssh_agent jest:
Jako jeden z poniższych kroków
Dockerfile
utwórz.ssh
katalog, dodając:RUN mkdir -p /root/.ssh
Poniżej zaznaczono, że chcesz zamontować katalog ssh jako wolumin:
VOLUME [ "/root/.ssh" ]
Upewnij się, że Twój kontener
ssh_config
wie, gdzie znaleźć klucze publiczne, dodając ten wiersz:RUN echo " IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config
Pokaż
.ssh
katalog użytkownika lokalnego w kontenerze w czasie wykonywania:docker run -v ~/.ssh:/root/.ssh -it image_name
Lub
dockerCompose.yml
dodaj to pod kluczem głośności usługi:- "~/.ssh:/root/.ssh"
Twój finał
Dockerfile
powinien zawierać coś takiego:źródło
Próbuję rozwiązać problem w inny sposób: dodając publiczny klucz ssh do obrazu. Ale podczas moich prób odkryłem, że „docker cp” służy do kopiowania z kontenera na host. Punkt 3 w odpowiedzi skrzypienia wydaje się mówić, że możesz użyć dokera cp do wstrzyknięcia plików do kontenera. Zobacz https://docs.docker.com/engine/reference/commandline/cp/
fragment
źródło
Możesz przekazać autoryzowane klucze do swojego kontenera za pomocą folderu współdzielonego i ustawić uprawnienia za pomocą pliku dokera w następujący sposób:
A twoje uruchomienie dokera zawiera coś takiego jak poniższe, aby udostępnić katalog auth na hoście (trzymając klucze autoryzowane) z kontenerem, a następnie otworzyć port ssh, który będzie dostępny przez port 7001 na hoście.
Możesz spojrzeć na https://github.com/jpetazzo/nsenter, który wydaje się być innym sposobem na otwarcie powłoki na kontenerze i wykonywanie poleceń w kontenerze.
źródło
Późno na imprezę, co powiesz na to, co sprawi, że klucze systemu operacyjnego hosta będą dostępne do rootowania wewnątrz kontenera w locie:
Nie jestem zwolennikiem używania Dockerfile do instalowania kluczy, ponieważ iteracje twojego kontenera mogą pozostawić klucze prywatne.
źródło
Próbowałem wymyślić, jak dodać klucze podpisu do kontenera, które będą używane w czasie wykonywania (nie kompilacji) i natknąłem się na to pytanie. Sekrety dokerów wydają się być rozwiązaniem mojego przypadku użycia, a ponieważ nikt jeszcze o tym nie wspomniał, dodam je.
źródło
W moim przypadku miałem problem z nodejs i „npm i” ze zdalnego repozytorium. Naprawiłem dodawanie użytkownika „node” do kontenera nodejs i 700 do ~ / .ssh w kontenerze.
Plik Docker:
run.sh:
docker-compose.yml:
potem zaczęło działać
źródło
Najprostszy sposób, załóż konto startera i użyj: ssh-import-id
źródło
ssh-import-id
wygląda na to, że importuje tylko klucze publiczne.W działającym kontenerze dokera możesz wydać ssh-keygen za pomocą opcji dokera -i (interaktywnej). Spowoduje to przekazanie monitów kontenera o utworzenie klucza w kontenerze dokera.
źródło
W przypadku kluczy debian / root / autoryzowanych_kluczy:
źródło