Samouczek: utrwalanie danych w aplikacji kontenera przy użyciu woluminów w programie VS Code

W tym samouczku nauczysz się utrwalać dane w aplikacji kontenera. Po uruchomieniu lub zaktualizowaniu danych dane są nadal dostępne. Istnieją dwa główne typy woluminów używanych do utrwalania danych. Ten samouczek koncentruje się na nazwanych woluminach.

Dowiesz się również o instalacjach powiązań, które kontrolują dokładny punkt instalacji na hoście. Możesz użyć instalacji powiązanych w celu utrwalania danych, ale może również dodawać więcej danych do kontenerów. Podczas pracy nad aplikacją możesz użyć instalacji powiązanej, aby zainstalować kod źródłowy w kontenerze, aby umożliwić mu wyświetlanie zmian kodu, reagowanie i wyświetlanie zmian od razu.

W tym samouczku przedstawiono również warstwy obrazów, buforowanie warstw i kompilacje wieloetapowe.

Z tego samouczka dowiesz się, jak wykonywać następujące czynności:

  • Omówienie danych między kontenerami.
  • Utrwalanie danych przy użyciu nazwanych woluminów.
  • Użyj instalacji wiązania.
  • Wyświetl warstwę obrazu.
  • Zależności pamięci podręcznej.
  • Omówienie kompilacji wieloetapowych.

Wymagania wstępne

W tym samouczku kontynuowano poprzedni samouczek: Tworzenie i udostępnianie aplikacji platformy Docker za pomocą programu Visual Studio Code. Zacznij od tego, który zawiera wymagania wstępne.

Omówienie danych między kontenerami

W tej sekcji uruchomisz dwa kontenery i utworzysz plik w każdym z nich. Pliki utworzone w jednym kontenerze nie są dostępne w innym.

  1. ubuntu Uruchom kontener przy użyciu tego polecenia:

    docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
    

    To polecenie uruchamia wywołanie dwóch poleceń przy użyciu polecenia &&. Pierwsza część wybiera pojedynczą liczbę losową i zapisuje ją w pliku /data.txt. Drugie polecenie obserwuje plik, aby zachować działanie kontenera.

  2. W programie VS Code w obszarze Platformy Docker kliknij prawym przyciskiem myszy kontener ubuntu i wybierz pozycję Dołącz powłokę.

    Screenshot shows the Docker extension with a container selected and a context menu with Attach Shell selected.

    Zostanie otwarty terminal z uruchomioną powłoką w kontenerze ubuntu.

  3. Uruchom następujące polecenie, aby wyświetlić zawartość /data.txt pliku.

    cat /data.txt
    

    W terminalu jest wyświetlana liczba z zakresu od 1 do 10000.

    Aby użyć wiersza polecenia, aby wyświetlić ten wynik, pobierz identyfikator kontenera docker ps przy użyciu polecenia i uruchom następujące polecenie.

    docker exec <container-id> cat /data.txt
    
  4. Uruchom inny ubuntu kontener.

    docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
    
  5. Użyj tego polecenia, aby przyjrzeć się zawartości folderu.

    docker run -it ubuntu ls /
    

    Nie powinno istnieć data.txt plik, ponieważ został zapisany w miejscu tymczasowym tylko dla pierwszego kontenera.

  6. Wybierz te dwa kontenery systemu Ubuntu. Kliknij prawym przyciskiem myszy i wybierz polecenie Usuń. Z wiersza polecenia możesz je usunąć za pomocą docker rm -f polecenia .

Utrwalanie danych zadań do wykonania przy użyciu nazwanych woluminów

Domyślnie aplikacja do wykonania przechowuje swoje dane w bazie danych SQLite w witrynie ./etc/todos/todo.db SQLite Database to relacyjna baza danych, która przechowuje dane w jednym pliku. Takie podejście działa w przypadku małych projektów.

Pojedynczy plik można utrwalać na hoście. Gdy udostępnisz go następnemu kontenerowi, aplikacja może pobrać miejsce, w którym została przerwana. Tworząc wolumin i dołączając lub instalowania, do folderu, w którym są przechowywane dane, można utrwalać dane. Kontener zapisuje dane w pliku todo.db i dane są utrwalane na hoście w woluminie.

W tej sekcji użyj nazwanego woluminu. Platforma Docker utrzymuje lokalizację fizyczną woluminu na dysku. Zapoznaj się z nazwą woluminu, a platforma Docker udostępnia odpowiednie dane.

  1. Utwórz wolumin przy użyciu docker volume create polecenia .

    docker volume create todo-db
    
  2. W obszarze KONTENERY wybierz pozycję wprowadzenie i kliknij prawym przyciskiem myszy. Wybierz pozycję Zatrzymaj , aby zatrzymać kontener aplikacji.

    Aby zatrzymać kontener z wiersza polecenia, użyj docker stop polecenia .

  3. Uruchom kontener wprowadzający, używając następującego polecenia.

    docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
    

    Parametr woluminu określa wolumin do zainstalowania i lokalizacji, /etc/todos.

  4. Odśwież przeglądarkę, aby ponownie załadować aplikację. Jeśli okno przeglądarki zostało zamknięte, przejdź do strony http://localhost:3000/. Dodaj niektóre elementy do listy zadań do wykonania.

    Screenshot shows the sample app with several items added to the list.

  5. Usuń kontener wprowadzający dla aplikacji do wykonania. Kliknij prawym przyciskiem myszy kontener w obszarze platformy Docker i wybierz polecenie Usuń lub użyj docker stop poleceń i docker rm .

  6. Uruchom nowy kontener przy użyciu tego samego polecenia:

    docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
    

    To polecenie instaluje ten sam dysk co poprzednio. Odśwież przeglądarkę. Dodane elementy są nadal na liście.

  7. Ponownie usuń kontener wprowadzający.

Nazwane woluminy i instalacje powiązane, omówione poniżej, są głównymi typami woluminów obsługiwanymi domyślnie przez instalację aparatu platformy Docker.

Właściwości Nazwane woluminy Wiązanie instalacji
Lokalizacja hosta Wybór platformy Docker Kontrolujesz
Przykład instalacji (przy użyciu polecenia -v) my-volume:/usr/local/data /path/to/data:/usr/local/data
Wypełnia nowy wolumin zawartością kontenera Tak Nie.
Obsługuje sterowniki woluminów Tak Nie.

Dostępnych jest wiele wtyczek sterowników woluminów do obsługi systemu plików NFS, SFTP, NetApp i innych. Te wtyczki są szczególnie ważne, aby uruchamiać kontenery na wielu hostach w środowisku klastra, takim jak Swarm lub Kubernetes.

Jeśli zastanawiasz się, gdzie platforma Docker rzeczywiście przechowuje dane, uruchom następujące polecenie.

docker volume inspect todo-db

Przyjrzyj się wynikom podobnym do tego wyniku.

[
    {
        "CreatedAt": "2019-09-26T02:18:36Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
        "Name": "todo-db",
        "Options": {},
        "Scope": "local"
    }
]

Jest Mountpoint to rzeczywista lokalizacja, w której są przechowywane dane. Na większości komputerów potrzebny jest dostęp do katalogu głównego, aby uzyskać dostęp do tego katalogu z hosta.

Używanie instalacji powiązanych

W przypadku instalacji powiązanych można kontrolować dokładny punkt instalacji na hoście. Takie podejście utrwala dane, ale jest często używane do dostarczania większej ilości danych do kontenerów. Możesz użyć instalacji powiązania, aby zainstalować kod źródłowy w kontenerze, aby umożliwić mu wyświetlanie zmian kodu, reagowanie i wyświetlanie zmian od razu.

Aby uruchomić kontener w celu obsługi przepływu pracy programowania, wykonaj następujące kroki:

  1. Usuń wszystkie getting-started kontenery.

  2. W folderze app uruchom następujące polecenie.

    docker run -dp 3000:3000 -w /app -v ${PWD}:/app node:20-alpine sh -c "yarn install && yarn run dev"
    

    To polecenie zawiera następujące parametry.

    • -dp 3000:3000 Tak samo jak poprzednio. Uruchom polecenie w trybie odłączonym i utwórz mapowanie portów.
    • -w /app Katalog roboczy wewnątrz kontenera.
    • -v ${PWD}:/app" Powiąż bieżący katalog z hosta w kontenerze do /app katalogu.
    • node:20-alpine Obraz do użycia. Ten obraz jest obrazem podstawowym aplikacji z pliku Dockerfile.
    • sh -c "yarn install && yarn run dev" Polecenie. Uruchamia powłokę przy użyciu poleceń sh i uruchamia yarn install ją, aby zainstalować wszystkie zależności. Następnie jest uruchamiany program yarn run dev. Jeśli spojrzysz na package.jsonelement , dev skrypt uruchamia polecenie nodemon.
  3. Dzienniki można obserwować przy użyciu polecenia docker logs.

    docker logs -f <container-id>
    
    $ nodemon src/index.js
    [nodemon] 2.0.20
    [nodemon] to restart at any time, enter `rs`
    [nodemon] watching path(s): *.*
    [nodemon] watching extensions: js,mjs,json
    [nodemon] starting `node src/index.js`
    Using sqlite database at /etc/todos/todo.db
    Listening on port 3000
    

    Po wyświetleniu końcowego wpisu na tej liście aplikacja jest uruchomiona.

    Po zakończeniu oglądania dzienników wybierz dowolny klawisz w oknie terminalu lub naciśnij klawisze Ctrl+C w oknie zewnętrznym.

  4. W programie VS Code otwórz plik src/static/js/app.js. Zmień tekst przycisku Dodaj element w wierszu 109.

    - {submitting ? 'Adding...' : 'Add Item'}
    + {submitting ? 'Adding...' : 'Add'}
    

    Zapisz zmianę.

  5. Odśwież przeglądarkę. Powinna zostać wyświetlona zmiana.

    Screenshot shows the sample app with the new text on the button.

Wyświetlanie warstw obrazów

Możesz przyjrzeć się warstwom tworzącym obraz. Uruchom polecenie , docker image history aby wyświetlić polecenie użyte do utworzenia każdej warstwy na obrazie.

  1. Użyj docker image history polecenia , aby wyświetlić warstwy na obrazie wprowadzającym utworzonym wcześniej w samouczku.

    docker image history getting-started
    

    Wynik powinien przypominać te dane wyjściowe.

    IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
    a78a40cbf866        18 seconds ago      /bin/sh -c #(nop)  CMD ["node" "/app/src/ind…   0B                  
    f1d1808565d6        19 seconds ago      /bin/sh -c yarn install --production            85.4MB              
    a2c054d14948        36 seconds ago      /bin/sh -c #(nop) COPY dir:5dc710ad87c789593…   198kB               
    9577ae713121        37 seconds ago      /bin/sh -c #(nop) WORKDIR /app                  0B                  
    b95baba1cfdb        13 days ago         /bin/sh -c #(nop)  CMD ["node"]                 0B                  
    <missing>           13 days ago         /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B                  
    <missing>           13 days ago         /bin/sh -c #(nop) COPY file:238737301d473041…   116B                
    <missing>           13 days ago         /bin/sh -c apk add --no-cache --virtual .bui…   5.35MB              
    <missing>           13 days ago         /bin/sh -c #(nop)  ENV YARN_VERSION=1.21.1      0B                  
    <missing>           13 days ago         /bin/sh -c addgroup -g 1000 node     && addu…   74.3MB              
    <missing>           13 days ago         /bin/sh -c #(nop)  ENV NODE_VERSION=12.14.1     0B                  
    <missing>           13 days ago         /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B                  
    <missing>           13 days ago         /bin/sh -c #(nop) ADD file:e69d441d729412d24…   5.59MB   
    

    Każdy z wierszy reprezentuje warstwę na obrazie. Dane wyjściowe pokazują podstawę u dołu z najnowszą warstwą u góry. Korzystając z tych informacji, można zobaczyć rozmiar każdej warstwy, pomagając zdiagnozować duże obrazy.

  2. Kilka wierszy jest obcinanych. Po dodaniu parametru --no-trunc uzyskasz pełne dane wyjściowe.

    docker image history --no-trunc getting-started
    

Zależności pamięci podręcznej

Po zmianie warstwy należy ponownie utworzyć wszystkie warstwy podrzędne. Oto plik Dockerfile ponownie:

FROM node:20-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "/app/src/index.js"]

Każde polecenie w pliku Dockerfile staje się nową warstwą obrazu. Aby zminimalizować liczbę warstw, możesz przeprowadzić restrukturyzację pliku Dockerfile w celu obsługi buforowania zależności. W przypadku aplikacji opartych na węźle package.json te zależności są zdefiniowane w pliku .

Podejście polega na skopiowaniu tylko tego pliku w pierwszej kolejności, zainstalowaniu zależności, a następnie skopiowaniu wszystkich innych elementów. Proces odtwarza tylko zależności przędzy, jeśli nastąpiła zmiana na package.json.

  1. Zaktualizuj plik Dockerfile , aby skopiować w package.json pierwszej kolejności, zainstalować zależności, a następnie skopiować wszystkie inne elementy. Oto nowy plik:

    FROM node:20-alpine
    WORKDIR /app
    COPY package.json yarn.lock ./
    RUN yarn install --production
    COPY . .
    CMD ["node", "/app/src/index.js"]
    
  2. Skompiluj nowy obraz przy użyciu polecenia docker build.

    docker build -t getting-started .
    

    Powinny zostać wyświetlone dane wyjściowe podobne do następujących:

    Sending build context to Docker daemon  219.1kB
    Step 1/6 : FROM node:12-alpine
    ---> b0dc3a5e5e9e
    Step 2/6 : WORKDIR /app
    ---> Using cache
    ---> 9577ae713121
    Step 3/6 : COPY package* yarn.lock ./
    ---> bd5306f49fc8
    Step 4/6 : RUN yarn install --production
    ---> Running in d53a06c9e4c2
    yarn install v1.17.3
    [1/4] Resolving packages...
    [2/4] Fetching packages...
    info fsevents@1.2.9: The platform "linux" is incompatible with this module.
    info "fsevents@1.2.9" is an optional dependency and failed compatibility check. Excluding it from installation.
    [3/4] Linking dependencies...
    [4/4] Building fresh packages...
    Done in 10.89s.
    Removing intermediate container d53a06c9e4c2
    ---> 4e68fbc2d704
    Step 5/6 : COPY . .
    ---> a239a11f68d8
    Step 6/6 : CMD ["node", "/app/src/index.js"]
    ---> Running in 49999f68df8f
    Removing intermediate container 49999f68df8f
    ---> e709c03bc597
    Successfully built e709c03bc597
    Successfully tagged getting-started:latest
    

    Wszystkie warstwy zostały przebudowane. Ten wynik jest oczekiwany, ponieważ zmieniono plik Dockerfile.

  3. Wprowadź zmianę w src/static/index.html. Na przykład zmień tytuł, aby powiedzieć "The Awesome Todo App".

  4. Skompiluj teraz obraz platformy Docker przy użyciu docker build ponownie. Tym razem dane wyjściowe powinny wyglądać nieco inaczej.

    Sending build context to Docker daemon  219.1kB
    Step 1/6 : FROM node:12-alpine
    ---> b0dc3a5e5e9e
    Step 2/6 : WORKDIR /app
    ---> Using cache
    ---> 9577ae713121
    Step 3/6 : COPY package* yarn.lock ./
    ---> Using cache
    ---> bd5306f49fc8
    Step 4/6 : RUN yarn install --production
    ---> Using cache
    ---> 4e68fbc2d704
    Step 5/6 : COPY . .
    ---> cccde25a3d9a
    Step 6/6 : CMD ["node", "/app/src/index.js"]
    ---> Running in 2be75662c150
    Removing intermediate container 2be75662c150
    ---> 458e5c6f080c
    Successfully built 458e5c6f080c
    Successfully tagged getting-started:latest
    

    Ponieważ używasz pamięci podręcznej kompilacji, powinno to pójść znacznie szybciej.

Kompilacje wieloetapowe

Kompilacje wieloetapowe to niezwykle zaawansowane narzędzie ułatwiające tworzenie obrazu przy użyciu wielu etapów. Istnieje kilka zalet:

  • Oddzielanie zależności czasu kompilacji od zależności środowiska uruchomieniowego
  • Zmniejsz ogólny rozmiar obrazu, wysyłając tylko to, czego aplikacja musi uruchomić

Ta sekcja zawiera krótkie przykłady.

Przykład maven/Tomcat

Podczas kompilowania aplikacji opartych na języku Java potrzebny jest zestaw JDK do skompilowania kodu źródłowego do kodu bajtowego języka Java. Ten zestaw JDK nie jest potrzebny w środowisku produkcyjnym. Możesz używać narzędzi, takich jak Maven lub Gradle, aby ułatwić tworzenie aplikacji. Te narzędzia nie są również potrzebne na końcowym obrazie.

FROM maven AS build
WORKDIR /app
COPY . .
RUN mvn package

FROM tomcat
COPY --from=build /app/target/file.war /usr/local/tomcat/webapps 

W tym przykładzie użyto jednego etapu , buildaby wykonać rzeczywistą kompilację języka Java przy użyciu narzędzia Maven. Drugi etap, zaczynając od "FROM tomcat", kopiuje pliki z etapu build . Końcowy obraz jest tylko ostatnim etapem, który można zastąpić przy użyciu parametru --target .

Przykład platformy React

Podczas kompilowania aplikacji React potrzebne jest środowisko Node do kompilowania kodu JavaScript, arkuszy stylów SASS i nie tylko do statycznych plików HTML, JavaScript i CSS. Jeśli nie wykonujesz renderowania po stronie serwera, nie potrzebujesz nawet środowiska Node dla kompilacji produkcyjnej.

FROM node:20-alpine AS build
WORKDIR /app
COPY package* yarn.lock ./
RUN yarn install
COPY public ./public
COPY src ./src
RUN yarn run build

FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html

W tym przykładzie node:20 użyto obrazu do wykonania kompilacji, która maksymalizuje buforowanie warstw, a następnie kopiuje dane wyjściowe do kontenera nginx .

Czyszczenie zasobów

Zachowaj wszystko, co zostało zrobione do tej pory, aby kontynuować tę serię samouczków.

Następne kroki

Znasz już opcje utrwalania danych dla aplikacji kontenera.

Co chcesz zrobić dalej?