Tracę dane po wyjściu kontenera

394

Pomimo interaktywnego samouczka Dockera i często zadawanych pytań tracę dane po wyjściu kontenera.

Zainstalowałem Docker zgodnie z opisem tutaj: http://docs.docker.io/en/latest/installation/ubuntulinux bez problemu na Ubuntu 13.04.

Ale traci wszystkie dane po wyjściu.

iman@test:~$ sudo docker version
Client version: 0.6.4 
Go version (client): go1.1.2 
Git commit (client): 2f74b1c 
Server version: 0.6.4 
Git commit (server): 2f74b1c 
Go version (server): go1.1.2 
Last stable version: 0.6.4 


iman@test:~$ sudo docker run ubuntu ping
2013/10/25 08:05:47 Unable to locate ping 
iman@test:~$ sudo docker run ubuntu apt-get install ping
Reading package lists... 
Building dependency tree... 
The following NEW packages will be installed: 
  iputils-ping 
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. 
Need to get 56.1 kB of archives. 
After this operation, 143 kB of additional disk space will be used. 
Get:1 http://archive.ubuntu.com/ubuntu/ precise/main iputils-ping amd64 3:20101006-1ubuntu1 [56.1 kB] 
debconf: delaying package configuration, since apt-utils is not installed 
Fetched 56.1 kB in 0s (195 kB/s) 
Selecting previously unselected package iputils-ping. 
(Reading database ... 7545 files and directories currently installed.) 
Unpacking iputils-ping (from .../iputils-ping_3%3a20101006-1ubuntu1_amd64.deb) ... 
Setting up iputils-ping (3:20101006-1ubuntu1) ... 
iman@test:~$ sudo docker run ubuntu ping
2013/10/25 08:06:11 Unable to locate ping 
iman@test:~$ sudo docker run ubuntu touch /home/test
iman@test:~$ sudo docker run ubuntu ls /home/test
ls: cannot access /home/test: No such file or directory 

Przetestowałem to również podczas interaktywnych sesji z tym samym wynikiem. Zapomniałem czegoś?

EDYCJA: WAŻNE DLA NOWYCH UŻYTKOWNIKÓW DOCKER

Jak powiedział @ mohammed-noureldin i inni, tak naprawdę NIE jest to pojemnik wychodzący . Za każdym razem tworzy nowy pojemnik.

iman
źródło
10
Tego nie można nazwać „ wyjściem z kontenera ”, właśnie tworzysz nowy kontener, użycie słowa wyjścia może być bardzo mylące (przez to też byłem zdezorientowany).
Mohammed Noureldin
1
@MohammedNoureldin, masz rację, wyjście nie jest poprawne, ale dokładnie tak myśleliście ty, ja i inni. Więc to jest lepsze słowo w pytaniu, twoja edycja sprawia, że ​​pytanie jest odpowiedzią! Nowi wyszukiwacze nie znajdą tutaj!
iman
Na samym początku pracy z Dockerem pomyślałem, że właściwie z powodu twojego pytania uważam, że ten adres jest po prostu NIEPRAWIDŁOWY. nowy tytuł został sprawdzony i zaakceptowany, nie rozumiem, dlaczego ktoś miałby nalegać na niewłaściwy tytuł, to jest twoje pytanie i twoja decyzja.
Mohammed Noureldin,
3
Zgadzam się z @MohammedNoureldin. Połączenie konkretnego tytułu, przykładu i zaakceptowanej odpowiedzi nie pomaga przyszłym czytelnikom, a zwłaszcza początkującym, zrozumieć Docker. Proponuję zachować tytuł i oryginalne pytanie, ponieważ początkujący z pewnością będą szukać czegoś takiego. Ale dlaczego nie dodasz czegoś opisującego swoje nieporozumienia w momencie pisania postu. Pomoże to wyjaśnić. To jest nasza kultura tutaj w SO ... prawda? :-)
tgogos
2
Miałem ten problem ... za każdym razem, gdy wychodzisz, musisz uruchomić swój kontener, nie uruchamiać go ... uruchomić obraz agane zrobić nowy pojemnik, to pomoże dokerowi uruchomić <identyfikator kontenera>
dokować

Odpowiedzi:

399

Musisz zatwierdzić wprowadzone zmiany w kontenerze, a następnie uruchomić go. Spróbuj tego:

sudo docker pull ubuntu

sudo docker run ubuntu apt-get install -y ping

Następnie pobierz identyfikator kontenera za pomocą tego polecenia:

sudo docker ps -l

Zatwierdź zmiany w kontenerze:

sudo docker commit <container_id> iman/ping 

Następnie uruchom kontener:

sudo docker run iman/ping ping www.google.com

To powinno działać.

Unferth
źródło
9
Dlatego powinienem używać zatwierdzania po każdym uruchomieniu, aby zachować dane.
iman
5
Zatwierdzenia należy używać tylko wtedy, gdy wprowadzasz ZMIANY w kontenerze (np. Instalując nowe narzędzia lub dane), aby zmiany te zostały zapisane, a następnym razem, gdy uruchomisz nowy kontener z tego obrazu, rozpocznie się od momentu ostatniego zapisu lub zatwierdzić, zachowując twoje dane.
Unferth,
7
@ Nie wiem co, jeśli chcę nadal zatwierdzać zmiany? Do tej pory tworzy więcej zdjęć <none>. Jak dodawać zatwierdzenie do istniejącego obrazu?
Marconi
62
Stopniowe zatwierdzanie zmian nie jest „sposobem dokera”. Użyj pliku DOCKERFILE.
user2105103
23
Jak zrobiłbyś to z poziomu kontenera? Rozważ następujący scenariusz: 1) Używam kontenera w następujący sposób: uruchamiam okno dokowane -i -t myimage / bin / bash 2) Wprowadzam pewne zmiany 3) Nie mogę zatwierdzić z poziomu kontenera, więc kiedy wychodzę z kontenera, I
utracę
374

Gdy użyjesz docker rundo uruchomienia kontenera, faktycznie tworzy on nowy kontener na podstawie podanego obrazu.

Oprócz innych użytecznych odpowiedzi tutaj, pamiętaj, że możesz zrestartować istniejący kontener po jego wyjściu, a zmiany nadal tam są.

docker start f357e2faab77 # restart it in the background
docker attach f357e2faab77 # reattach the terminal & stdin
ZeissS
źródło
88
docker pspokazuje tylko działające kontenery dokerów. docker ps -apokazuje również te, które zostały zakończone - i możesz kontynuować. Zatwierdzenie jest konieczne tylko po każdym uruchomieniu, jeśli chcesz zrobić tam migawkę do użycia w przyszłości, w przeciwnym razie sam kontener zostanie w pobliżu, abyś mógł z niej korzystać.
user1278519
2
Pytanie, proszę, więc jeśli jenkinspobiorę dokera serwera i uruchomię go na moim hoście ci i uruchomi on niektóre zadania, które mam, w wyniku czego serwer jenkins zapisuje na dysku niektóre dzienniki. teraz, jeśli mój serwer (który był hostem mojego dokera) zostanie zrestartowany i uruchomię ponownie moją dokerkę Jenkins, czy to znaczy, że straciłem wszystkie pliki dziennika? jeśli tak, to w jaki sposób mogę jenkinsna przykład użyć okna dokowanego, aby ułatwić instalację Jenkins w CI?
Jas
2
@Jas Jeśli trzymasz się tego samego pojemnika i nie tworzysz nowych, nie ma problemów. Docker ma obecnie zasady ponownego uruchamiania, więc można go skonfigurować tak, aby zrestartował ten sam kontener podczas ponownego uruchamiania komputera. Radziłbym również, abyś włożył jenkins do domu w wolumin, aby móc uzyskać do niego dostęp z zewnątrz (kopie zapasowe itp.).
ZeissS,
7
Oto przydatny sposób na skopiowanie plików z kontenera po wyjściu:docker cp $(docker ps -alq):/path/to/file .
Josh Habdas
3
możesz także uruchomić i dołączyć kontener według jego nazwy. (np. docker run -it --name my_debian debiani później docker start my_debian && docker attach my_debian)
Johnny Willer
127

Istnieją następujące sposoby utrwalenia danych kontenera:

  1. Woluminy dokerów

  2. Dokowanie zatwierdzenia

    a) utwórz kontener z obrazu ubuntu i uruchom terminal bash.

       $ docker run -i -t ubuntu:14.04 /bin/bash
    

    b) Wewnątrz zacisku zainstaluj zawinięcie

       # apt-get update
       # apt-get install curl
    

    c) Wyjdź z terminalu kontenerowego

       # exit
    

    d) Zanotuj swój identyfikator kontenera, wykonując następujące polecenie:

       $ docker ps -a
    

    e) zapisz kontener jako nowy obraz

       $ docker commit <container_id> new_image_name:tag_name(optional)
    

    f) sprawdź, czy możesz zobaczyć swój nowy obraz z zainstalowanym curl.

       $ docker images           
    
       $ docker run -it new_image_name:tag_name bash
          # which curl
            /usr/bin/curl
    
kalyani chaudhari
źródło
Czy to konieczne exitwcześniej docker commit? Dzięki.
Abhishek Anand
2
@AbhishekAnand tak, ponieważ za pomocą docker runpolecenia uruchamiasz bash w kontenerze i zostajesz tam ze względu na opcje -ii -t(interaktywne z TTY). Jednak Docker działa na twoim komputerze poza kontenerem, więc po dokonaniu niezbędnych zmian w kontenerze od wewnątrz, aby wrócić do powłoki systemu, musisz exit(lub Ctrl + D) powłokę kontenera. Zwróć również uwagę na #iw $odpowiedzi, które wskazują różne powłoki, w których zapisywane są polecenia.
Erik
Szybkie pytanie: jeśli się nie zgadzam, straciłem dane. Jest jasne. Ale kiedy zmieniam konfigurację Nginx, dlaczego pozostaje ona zaktualizowana? (nie trzeba zatwierdzać) @Erik
grep
@ grrep, jeśli masz jasne i powtarzalne MWE, zadaj nowe pytanie, jeśli jeszcze nie ma takiego konkretnego przypadku użycia.
Erik
3. docker stopnastępnie następuje docker start.
carillonator
59

Oprócz odpowiedzi Unferth zaleca się utworzenie pliku Docker .

W pustym katalogu utwórz plik o nazwie „Dockerfile” z następującą zawartością.

FROM ubuntu
RUN apt-get install ping
ENTRYPOINT ["ping"]

Utwórz obraz za pomocą Dockerfile . Użyjmy tagu, abyśmy nie musieli pamiętać szesnastkowego numeru obrazu.

$ docker build -t iman/ping .

A następnie uruchom obraz w kontenerze.

$ docker run iman/ping stackoverflow.com
salathe
źródło
1
Nigdy nie trzeba robić tego ręcznie więcej niż jeden raz, jest to dokładnie punkt dokera. Utwórz plik dokowania, zatwierdź i prześlij obraz wynikowy. Wyciągnij wspomniany obraz do przodu.
Brandon Bertelsen
11

Mam o wiele prostszą odpowiedź na twoje pytanie, uruchom następujące dwa polecenia

sudo docker run -t -d ubuntu --name mycontainername /bin/bash
sudo docker ps -a

powyższe polecenie ps -a zwraca listę wszystkich kontenerów. Weź nazwę kontenera, który odwołuje się do nazwy obrazu - „ubuntu”. docker auto generuje na przykład nazwy kontenerów - 'lightlyxuyzx'to znaczy, jeśli nie używasz opcji --name.

Ważne są opcje -t i -d, utworzony kontener jest odłączony i można go ponownie podłączyć zgodnie z opisem poniżej z opcją -t.

Dzięki opcji --name możesz nazwać swój kontener w moim przypadku „moja_nazwa_main”.

sudo docker exec -ti mycontainername bash

a powyższe polecenie pomaga zalogować się do kontenera za pomocą powłoki bash. Od tego momentu wszelkie zmiany wprowadzone w kontenerze są automatycznie zapisywane przez dokera. Na przykład -apt-get install curl wewnątrz kontenera Możesz wyjść z kontenera bez żadnych problemów, doker automatycznie zapisuje zmiany.

Przy następnym użyciu Wszystko, co musisz zrobić, to uruchomić te dwa polecenia za każdym razem, gdy chcesz pracować z tym kontenerem.

To polecenie poniżej uruchomi zatrzymany pojemnik:

sudo docker start mycontainername

sudo docker exec -ti mycontainername bash

Kolejny przykład z portami i wspólną przestrzenią podany poniżej:

docker run -t -d --name mycontainername -p 5000:5000 -v ~/PROJECTS/SPACE:/PROJECTSPACE 7efe2989e877 /bin/bash

W moim przypadku: 7efe2989e877 - to imageid poprzedniego uruchomionego kontenera, który uzyskałem

doker ps -a

Magnus Melwin
źródło
4
Z Dockerem 18.09.2 na Ubuntu 18.04 nie działa tak jak jest. Działa, jeśli --namedocker run --name mycontainername -t -d ubuntu /bin/bash
wstawię
3

Moją sugestią jest zarządzanie dokerem za pomocą komponowania dokera. Jest łatwym sposobem zarządzania wszystkimi kontenerami dokera dla twojego projektu, możesz zmapować wersje i połączyć różne kontenery, aby ze sobą współpracowały.

Dokumenty są bardzo proste do zrozumienia, lepsze niż dokumenty dokerów.

Dokumenty Docker-Compose

Najlepsza

Cam T
źródło
3

Powyżej zadanego pytania znajdują się naprawdę świetne odpowiedzi. Być może nie będzie potrzeby kolejnej odpowiedzi, ale nadal chcę wyrazić swoją osobistą opinię na ten temat w najprostszych możliwych słowach.

Oto kilka uwag na temat pojemników i obrazów, które pomogą nam wyciągnąć wniosek:

  • Obrazem dokera może być :
    1. utworzono z danego kontenera
    2. usunięte
    3. używane do tworzenia dowolnej liczby kontenerów
  • Pojemnikiem dokującym może być :
    1. utworzony z obrazu
    2. zaczęło się
    3. zatrzymany
    4. uruchomione ponownie
    5. usunięte
    6. używane do tworzenia dowolnej liczby obrazów
  • Polecenie uruchamiania dokera wykonuje następujące czynności :
    1. Pobiera obraz lub używa obrazu z pamięci podręcznej
    2. Tworzy z niego nowy pojemnik
    3. Uruchamia kontener
  • Gdy plik Docker jest używany do utworzenia obrazu :
    1. Dobrze wiadomo, że obraz zostanie ostatecznie użyty do uruchomienia kontenera dokowanego.
    2. Po wydaniu polecenia kompilacji dokera, doker za kulisami tworzy działający kontener z bazowym systemem plików i wykonuje kroki wewnątrz pliku Docker, aby skonfigurować ten kontener zgodnie z potrzebami programistów.
    3. Po skonfigurowaniu kontenera za pomocą specyfikacji pliku Docker plik zostanie zatwierdzony jako obraz.
    4. Obraz przygotowuje się do rock and roll!

Wniosek :

Jak widzimy, kontener dokera jest niezależny od obrazu dokera.

Kontener można zrestartować, pod warunkiem, że unikalny identyfikator tego kontenera [użyj, docker ps --allaby uzyskać identyfikator] .

Wszelkie operacje, takie jak utworzenie nowego katalogu, tworzenie plików, instalowanie narzędzi itp. Można wykonać wewnątrz kontenera, gdy jest on uruchomiony. Po zatrzymaniu kontener zachowuje wszystkie zmiany. Zatrzymywanie i restartowanie kontenera jest jak ponowne uruchamianie systemu komputerowego.

Już utworzony kontener jest zawsze dostępny do ponownego uruchomienia, ale kiedy wydamy docker runpolecenie, nowy kontener jest tworzony z obrazu, a zatem jest jak nowy system komputerowy. Zmiany wprowadzone w starym kontenerze - jak możemy teraz zrozumieć - nie są dostępne w tym nowym kontenerze.

Ostatnia uwaga :

Wydaje mi się, że teraz jest oczywiste, dlaczego dane wydają się być utracone, ale wciąż są dostępne ... ale w innym [starym] pojemniku. Więc zwróć uwagę na różnicę w docker start& docker runCommand i nigdy się w nich nie mylić.

Kiran Dahibhate
źródło
1

podobny problem (i w żaden sposób sam Dockerfile nie może go naprawić) doprowadził mnie do tej strony.

etap 0: dla wszystkich, mając nadzieję, że Dockerfile może to naprawić: dopóki --dns i --dns-search nie pojawią się w obsłudze Dockerfile - nie ma możliwości zintegrowania zasobów opartych na intranecie.

etap 1: po zbudowaniu obrazu za pomocą Dockerfile (przy okazji to poważna usterka, Dockerfile musi znajdować się w bieżącym folderze), posiadając obraz do wdrożenia tego, co jest oparte na intranecie, poprzez uruchomienie skryptu uruchamiania dokera. przykład: docker run -d \ --dns=${DNSLOCAL} \ --dns=${DNSGLOBAL} \ --dns-search=intranet \ -t pack/bsp \ --name packbsp-cont \ bash -c " \ wget -r --no-parent http://intranet/intranet-content.tar.gz \ tar -xvf intranet-content.tar.gz \ sudo -u ${USERNAME} bash --norc"

etap 2: zastosowanie skryptu uruchamiania dokera w trybie demona, zapewniając lokalne rekordy dns, aby mieć możliwość pobierania i wdrażania lokalnych rzeczy.

ważna kwestia: skrypt uruchamiający powinien kończyć się czymś w rodzaju /usr/bin/sudo -u ${USERNAME} bash --norckontynuowania działania kontenera nawet po zakończeniu skryptów instalacyjnych.

nie , nie jest możliwe uruchomienie kontenera w trybie interaktywnym dla pełnej automatyzacji, ponieważ pozostanie on w wewnętrznej linii poleceń, dopóki nie zostanie naciśnięty CTRL-p CTRL-q .

Nie , jeśli interakcja bash nie zostanie wykonana na końcu skryptu instalacyjnego, kontener zakończy się natychmiast po zakończeniu wykonywania skryptu, tracąc wszystkie wyniki instalacji.

etap 3: kontener nadal działa w tle, ale nie jest jasne, czy kontener zakończył procedurę instalacji, czy nie. za pomocą następującego bloku, aby określić zakończenie procedury wykonywania: while ! docker container top ${CONTNAME} | grep "00[[:space:]]\{12\}bash \--norc" - do echo "." sleep 5 done skrypt będzie kontynuował działanie dopiero po zakończeniu instalacji. i jest to właściwy moment na wywołanie: zatwierdzenia , podając bieżący identyfikator kontenera, a także nazwę obrazu docelowego (może być taki sam jak w procedurze kompilacji / uruchamiania , ale dołączony z tagiem lokalnych celów instalacji. przykład: docker commit containerID pack/bsp:toolchainedzobacz ten link na jak uzyskać właściwy identyfikator kontenera

etap 4: kontener został zaktualizowany o lokalne instalacje, a także został przypisany do nowo przypisanego obrazu (ten z dodanym znacznikiem celu). teraz można bezpiecznie zatrzymać pojemnik. przykład:docker stop packbsp-cont

stage5: w dowolnym momencie, w którym kontener z lokalnymi instalacjami wymaga uruchomienia, uruchom go z wcześniej zapisanym obrazem. przykład:docker run -d -t pack/bsp:toolchained

Oleg Kokorin
źródło
1

genialna odpowiedź tutaj Jak kontynuować dokera, który jest opuszczany przez kilogramy użytkownika

docker start $(docker ps -a -q --filter "status=exited")
(or in this case just docker start $(docker ps -ql) 'cos you don't want to start all of them)

docker exec -it <container-id> /bin/bash

Ta druga linia jest kluczowa. Więc exec jest używany zamiast uruchamiania, a nie na obrazie, ale na containerid. I robisz to po uruchomieniu kontenera.

barlop
źródło
0

Żadna z odpowiedzi nie odnosi się do wyboru tego projektu. Myślę, że doker działa w ten sposób, aby zapobiec tym 2 błędom:

  • Ponowne uruchomienie
  • Błąd częściowy
Minh Nghĩa
źródło