Tworzenie kontenerów przy użyciu Dockerfiles

1. Przegląd

Docker to otwarta platforma do tworzenia, dostarczania i uruchamiania aplikacji. Dzięki Dockerowi możesz oddzielić aplikacje od infrastruktury i traktować infrastrukturę jak zarządzaną aplikację. Docker pomaga szybciej dostarczać, testować i wdrażać kod oraz skracać cykl między pisaniem a uruchamianiem kodu.

Docker łączy funkcje kontenerów jądra z przepływami pracy i narzędziami, które pomagają zarządzać aplikacjami i je wdrażać.

Kontenery Dockera można bezpośrednio wykorzystywać w Kubernetes, co umożliwia ich łatwe uruchamianie w Kubernetes Engine. Po opanowaniu podstawowych informacji o Dockerze będziesz mieć umiejętności potrzebne do tworzenia aplikacji Kubernetes i skonteneryzowanych.

Czego się nauczysz

W tym module nauczysz się:

  • Tworzenie pliku Dockerfile dla przykładowej aplikacji
  • Tworzenie obrazu
  • Uruchamianie obrazu jako kontenera lokalnie
  • Zmiana działania kontenera
  • Przesyłanie obrazu do Artifact Registry

Wymagania wstępne

To jest moduł dla użytkowników początkujących. Zakładamy więc, że nie masz żadnego lub prawie żadnego doświadczenia z Dockerem i kontenerami. Znajomość Cloud Shell i wiersza poleceń jest zalecana, ale nie wymagana.

Samodzielne konfigurowanie środowiska

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub użyj istniejącego. Jeśli nie masz jeszcze konta Gmail ani Google Workspace, musisz je utworzyć.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Nazwa projektu to wyświetlana nazwa uczestników tego projektu. Jest to ciąg znaków, który nie jest używany przez interfejsy API Google. Możesz go w dowolnym momencie zaktualizować.
  • Identyfikator projektu musi być unikalny we wszystkich projektach Google Cloud i jest niezmienny (nie można go zmienić po ustawieniu). Konsola Cloud automatycznie generuje unikalny ciąg znaków. Zwykle nie musisz się nim przejmować. W większości modułów z kodem musisz odwoływać się do identyfikatora projektu (zwykle oznaczanego jako PROJECT_ID). Jeśli Ci się nie podoba, wygeneruj inny losowy identyfikator lub spróbuj użyć własnego i sprawdź, czy jest dostępny. Po utworzeniu projektu jest on „zamrażany”.
  • Istnieje też trzecia wartość, czyli numer projektu, którego używają niektóre interfejsy API. Więcej informacji o tych 3 wartościach znajdziesz w dokumentacji.
  1. Następnie musisz włączyć płatności w konsoli Cloud, aby korzystać z zasobów i interfejsów API Google Cloud. Ukończenie tego laboratorium nie powinno wiązać się z dużymi kosztami, a nawet z żadnymi. Aby wyłączyć zasoby i uniknąć naliczenia opłat po zakończeniu tego samouczka, postępuj zgodnie z instrukcjami „czyszczenia” na końcu ćwiczenia. Nowi użytkownicy Google Cloud mogą skorzystać z bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.

2. Przykładowa aplikacja

Na potrzeby tego modułu udostępniliśmy przykładową aplikację. W tej sekcji pobierzesz kod źródłowy i skompilujesz aplikację w jej natywnej postaci, zanim przejdziesz do procesu konteneryzacji.

Kod źródłowy

Kod źródłowy tego modułu jest dostępny w repozytorium GoogleCloudPlatform/container-developer-workshop wraz z dokumentacją przykładowej aplikacji.

Skonfiguruj git

git config --global user.name ${USER}
git config --global user.email ${USER}@qwiklabs.net

Klonowanie przykładowej aplikacji z repozytorium Cloud Source

gcloud source repos clone sample-app ${HOME}/sample-app &&
cd ${HOME}/sample-app &&
git checkout main

Wyniki

Cloning into '/home/student_03_49720296e995/sample-app'...
remote: Finding sources: 100% (16/16)
remote: Total 16 (delta 0), reused 16 (delta 0)
Receiving objects: 100% (16/16), 47.23 KiB | 681.00 KiB/s, done.
warning: remote HEAD refers to nonexistent ref, unable to checkout.

Project [qwiklabs-gcp-02-4327c4e03d82] repository [sample-app] was cloned to [/home/student_03_49720296e995/sample-app].
Branch 'main' set up to track remote branch 'main' from 'origin'.
Switched to a new branch 'main'

Kompilowanie przykładowej aplikacji

cd ${HOME}/sample-app
./mvnw compile

Wyniki

[INFO] Scanning for projects...
...
[INFO] Compiling 1 source file to /home/student_03_49720296e995/sample-app/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  10.080 s
[INFO] Finished at: 2022-02-23T17:14:30Z
[INFO] ------------------------------------------------------------------------

Uruchamianie przykładowej aplikacji

cd ${HOME}/sample-app
./mvnw exec:java

Wyniki

[INFO] Scanning for projects...
...
Listening at http://localhost:8080

Podgląd uruchomionej aplikacji

  • Kliknięcie przycisku Podgląd w przeglądarce w Cloud Shell
  • Kliknij Podejrzyj na porcie 8080.

Gdy skończysz

  • Aby zatrzymać działającą aplikację, naciśnij CTRL+C w Cloud Shell.

3. Dockerfile

Konteneryzacja aplikacji za pomocą pliku Dockerfile

Jednym ze sposobów spakowania aplikacji do kontenera jest użycie pliku Dockerfile. Plik Dockerfile przypomina skrypt, który instruuje demona, jak złożyć obraz kontenera. Więcej informacji znajdziesz w dokumentacji referencyjnej pliku Dockerfile.

Utwórz pusty plik Dockerfile w repozytorium przykładowej aplikacji.

touch ${HOME}/sample-app/Dockerfile

Otwórz plik Dockerfile w wybranym edytorze.

vi ${HOME}/sample-app/Dockerfile

Wybierz obraz początkowy

Korzystanie z metody Dockerfile do tworzenia kontenera wymaga bezpośredniej wiedzy o aplikacji, aby można było złożyć kontener. Pierwszym krokiem w tworzeniu pliku Dockerfile jest wybranie obrazu, który będzie stanowić podstawę Twojego obrazu.Powinien to być obraz nadrzędny lub podstawowy, utrzymywany i publikowany przez zaufane źródło, zwykle Twoją firmę.

Instrukcja FROM inicjuje nowy etap kompilacji i ustawia obraz bazowy dla kolejnych poleceń sekwencyjnych. Instrukcja FROM jest zwykle pierwszą instrukcją w pliku Dockerfile i może być poprzedzona tylko opcjonalną instrukcją ARG, która obsługuje zmienne.

Składnia: FROM <image>[:<tag> | @<digest>] [AS <name>]

Format obrazu to <image>:<tag> lub <image>@<digest>. Jeśli nie podasz tagu ani skrótu, domyślnie zostanie użyty tag :latest. Format <image> różni się w zależności od rejestru używanego do przechowywania obrazu. W przypadku Artifact Registry format <image> to <region>-docker.pkg.dev/<project ID>/<repository name>/<image name>:<image tag>.

W tym laboratorium użyjemy publicznego obrazu openjdk:11.0-jdk. Dodaj do pliku Dockerfile ten wiersz:

FROM openjdk:11.0-jdk

Ustawianie katalogu roboczego

Instrukcja WORKDIR ustawia katalog roboczy dla wszystkich kolejnych instrukcji w pliku Dockerfile. Więcej informacji znajdziesz w sekcji WORKDIR w dokumentacji referencyjnej pliku Dockerfile.

Składnia: WORKDIR <path>

W tym laboratorium użyjemy katalogu /app jako WORKDIR. Dodaj ten wiersz na końcu pliku Dockerfile:

WORKDIR /app

Kopiowanie plików aplikacji

Instrukcja COPY kopiuje katalogi lub pliki z lokalizacji <source> do ścieżki <destination> w systemie plików obrazu. Można określić wiele zasobów <source>, które są powiązane z kontekstem kompilacji. Kontekst kompilacji omówimy szczegółowo w sekcji Kompilacja. Więcej informacji znajdziesz w sekcji COPY w dokumentacji referencyjnej pliku Dockerfile.

Składnia: COPY <source>... <destination>

W tym laboratorium skopiujemy wszystkie pliki z repozytorium do systemu plików obrazu i dodamy ten wiersz na końcu pliku Dockerfile:

COPY . /app

Kompilowanie aplikacji

Instrukcja RUN wykonuje polecenia w nowej warstwie obrazu na bieżącym obrazie i zatwierdza wyniki. Utworzony obraz będzie używany w kolejnych krokach w pliku Dockerfile. Więcej informacji znajdziesz w sekcji RUN w dokumentacji referencyjnej pliku Dockerfile.

Składnia: RUN <command>

W tym module użyjemy narzędzia Maven, aby skompilować aplikację do pliku JAR. Dodaj ten wiersz na końcu pliku Dockerfile:

RUN ./mvnw compile assembly:single

Uruchom aplikację

Instrukcja CMD zawiera domyślne polecenie dla działającego kontenera. W pliku Dockerfile może być tylko jedna instrukcja CMD. Jeśli podasz więcej niż jedną, tylko ostatnia instrukcja CMD będzie miała zastosowanie. Instrukcje CMD i ENTRYPOINT oferują bardziej zaawansowane funkcje, ale nie są one omawiane w tym module. Więcej informacji znajdziesz w sekcji CMD w dokumentacji referencyjnej pliku Dockerfile.

Składnia: CMD ["executable","param1","param2"]

W tym laboratorium uruchomimy skompilowany plik JAR. Dodaj ten wiersz na końcu pliku Dockerfile:

CMD ["java","-jar","/app/target/sample-app-1.0.0-jar-with-dependencies.jar"]

Końcowy plik Dockerfile

Ostateczny plik Dockerfile będzie wyglądać tak:

FROM openjdk:11.0-jdk
WORKDIR /app
COPY . /app
RUN ./mvnw compile assembly:single
CMD ["java","-jar","/app/target/sample-app-1.0.0-jar-with-dependencies.jar"]

Zatwierdź plik Dockerfile lokalnie

cd ${HOME}/sample-app
git add Dockerfile
git commit -m "Added Dockerfile"

4. Kompilacja

Teraz utworzymy obraz z pliku Dockerfile za pomocą polecenia docker build. To polecenie instruuje demona Dockera, aby utworzył obraz zgodnie z instrukcjami z pliku Dockerfile. Więcej informacji znajdziesz w dokumentacji referencyjnej polecenia docker build.

Tworzenie obrazu

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
docker build --tag sample-app:${IMAGE_TAG} .

Wyniki

Sending build context to Docker daemon  221.2kB
Step 1/4 : FROM openjdk:11.0-jdk
11.0-jdk: Pulling from library/openjdk
0c6b8ff8c37e: Pull complete
412caad352a3: Pull complete
e6d3e61f7a50: Pull complete
461bb1d8c517: Pull complete
e442ee9d8dd9: Pull complete
542c9fe4a7ba: Pull complete
41de18d1833d: Pull complete
Digest: sha256:d72b1b9e94e07278649d91c635e34737ae8f181c191b771bde6816f9bb4bd08a
Status: Downloaded newer image for openjdk:11.0-jdk
---> 2924126f1829
Step 2/4 : WORKDIR /app
---> Running in ea037abb273d
Removing intermediate container ea037abb273d
---> bd9b6d078082
Step 3/4 : COPY . /app
---> b9aec2b5de51
Step 4/4 : RUN ./mvnw compile jar:jar
---> Running in 3f5ff737b7fd
[INFO] Scanning for projects...
...
[INFO] Building jar: /app/target/sample-app-1.0.0.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  22.952 s
[INFO] Finished at: 2022-02-23T18:09:08Z
[INFO] ------------------------------------------------------------------------
Removing intermediate container 331443caebd3
---> 152f65cc441e
Step 5/5 : CMD ["java", "-jar", "/app/target/sample-app-1.0.0.jar"]
---> Running in 3d595a72231c
Removing intermediate container 3d595a72231c
---> 0e40d7548cab
Successfully built 0e40d7548cab
Successfully tagged sample-app:aaa8895

5. Uruchom

Po pomyślnym utworzeniu obrazu kontenera możemy uruchomić aplikację i sprawdzić, czy działa zgodnie z oczekiwaniami, używając polecenia docker run. To polecenie uruchomi kontener na pierwszym planie w wierszu polecenia na potrzeby testowania lub debugowania. Więcej informacji znajdziesz w dokumentacji referencyjnej polecenia docker run.

Uruchamianie kontenera przy użyciu obrazu

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
docker run \
  --rm \
  -p 8080:8080 \
  sample-app:${IMAGE_TAG}

Wyniki

Listening at http://localhost:8080

Wyświetlanie podglądu aplikacji działającej w kontenerze

  • Kliknięcie przycisku Podgląd w przeglądarce w Cloud Shell
  • Kliknij Podejrzyj na porcie 8080.
  • Aby zatrzymać kontenery, naciśnij CTRL+C w Cloud Shell.

Zmiana działania kontenera

Wykonywanie polecenia Docker Run wykorzystuje konfigurację domyślną w pliku Dockerfile. Aby zmodyfikować to działanie, możesz dodać dodatkowe instrukcje i parametry.

Włącz logowanie TRACE

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
docker run \
  --rm \
  -p 8080:8080 \
  sample-app:${IMAGE_TAG} \
  java -Dorg.slf4j.simpleLogger.defaultLogLevel=trace -jar /app/target/sample-app-1.0.0-jar-with-dependencies.jar

Wyświetlanie podglądu aplikacji działającej w kontenerze

  • Kliknięcie przycisku Podgląd w przeglądarce w Cloud Shell
  • Kliknij Podejrzyj na porcie 8080.
  • Przejdź na kartę Cloud Shell i zobacz, że dodatkowe logowanie
  • Aby zatrzymać kontener, naciśnij w Cloud Shell klawisze CTRL+C.

Zmień port

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
docker run \
--rm \
-e PORT=8081 \
-p 8081:8081 \
sample-app:${IMAGE_TAG}

Wyświetlanie podglądu aplikacji działającej w kontenerze

  • Kliknięcie przycisku Podgląd w przeglądarce w Cloud Shell
  • Kliknij Zmień port.
  • Wpisz 8081.
  • Kliknij Zmień i wyświetl podgląd.
  • Aby zatrzymać kontener, naciśnij w Cloud Shell klawisze CTRL+C.

6. Push

Gdy będziemy mieć pewność, że obraz kontenera działa prawidłowo i chcemy udostępnić go do uruchamiania w innych środowiskach lub przez innych użytkowników, musimy przesłać obraz do repozytorium współdzielonego. Powinno to nastąpić w ramach zautomatyzowanego potoku kompilacji, ale w naszym środowisku testowym mamy już skonfigurowane repozytorium i możemy ręcznie przesłać obraz.

Przesyłanie zatwierdzenia pliku Dockerfile do repozytorium sample-app

cd ${HOME}/sample-app
export IMAGE_TAG=$(git rev-parse --short HEAD)
git push

Dodawanie tagu do obrazu na potrzeby Artifact Registry

docker tag sample-app:${IMAGE_TAG} \
    us-central1-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/apps/sample-app:${IMAGE_TAG}

Konfigurowanie danych logowania w Artifact Registry

gcloud auth configure-docker us-central1-docker.pkg.dev

Gdy pojawi się prośba, Do you want to continue (Y/n)?odpowiedzy i naciśnij Enter.

Przesyłanie obrazu do Artifact Registry

docker push us-central1-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/apps/sample-app:${IMAGE_TAG}

Wyniki

 The push refers to repository [us-central1-docker.pkg.dev/qwiklabs-gcp-04-b47ced695a3c/apps/sample-app]
  453b97f86449: Pushed
  e86791aa0382: Pushed
  d404c7ee0850: Pushed
  fe4f44af763d: Pushed
  7c072cee6a29: Pushed
  1e5fdc3d671c: Pushed
  613ab28cf833: Pushed
  bed676ceab7a: Pushed
  6398d5cccd2c: Pushed
  0b0f2f2f5279: Pushed
  aaa8895: digest: sha256:459de00f86f159cc63f98687f7c9563fd65a2eb9bcc71c23dda3351baf13607a size: 2424

7. Gratulacje!

Gratulacje! Codelab został ukończony.

Omówione zagadnienia

  • Utworzono plik Dockerfile dla przykładowej aplikacji.
  • Utworzony obraz
  • Obraz został uruchomiony lokalnie jako kontener.
  • Zmiana działania kontenera
  • przesłanie obrazu do Artifact Registry,