Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2024-XX-XX] Tworzenie wydajnych obrazów dockerowych w Springu #246

Merged
merged 11 commits into from
Jun 28, 2024

Conversation

BartoszPietrowiak
Copy link
Contributor

No description provided.

@@ -0,0 +1,329 @@
---
layout: post
title: "Tworzenie wydajnych obrazów dockerowych w Springu"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO to raczej tworzenie jest wydajniejsze a nie same obrazy. Może lepiej by było "Wydajne tworzenie" zamiast "Tworzenie wydajnych"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione


W poprzedniej sekcji został pokazany standardowy plik Dockerfile dla zbudowania aplikacji Spring Bootowej. Jedną z zawartych w nim instrukcji jest przekopiowanie pliku .jar do obrazu. Standardowo wykonuje się to za pomocą jednej instrukcji co powoduje, że każda zmiana w jakimkolwiek pliku aplikacji wymaga utworzenia warstwy od nowa.

Jest to bardzo niekorzystne, ponieważ niesie to za sobą wykorzystywanie nadmiernej przestrzeni dyskowej. Przyjmując, że plik .jar waży około 20 MB (gdzie większość to zależności aplikacji) wykonanie 10 wersji aplikacji zajmie nam 200 MB, pomimo że zmiany, jakie wykonaliśmy, były bardzo niewielkie i dotyczyły tylko kodów źródłowych (ważących kilkanaście KB).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"ważących kilkanaście KB" - nie zawsze, czasami kody potrafią być bardzo duże ;) może zmieńmy na "ważących przeciętnie kilkanaście KB"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione

Tutaj naprzeciw wyszli nam twórcy Spring Boota, dodając od wersji 2.3 możliwość budowania warstwowego pliku jar (eng. **layered jars**).

## Jak działa Spring Boot layered jar?
Spring Boot layered jar zmienia sposób budowania pliku .jar, dzieląc jego części na konkretne warstwy. Wykorzystuje w tym celu plik **layers.idx**. Plik ten zawiera listę warts oraz części pliku .jar, które są w niej zawarte. Warstwy w pliku zapisane są w kolejności, w jakiej powinny zostać dodane do obrazu Dockerowego. Domyślnie plik składa się z poniższych warstw:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"listę warts" -> "listę warstw"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione

- **snapshot-dependencies** - zawiera zależności aplikacji, które są w wersji SNAPSHOT
- **application** - zawiera kod źródłowy aplikacji

Dzięki takiemu rozwiązaniu jesteśmy w stanie podzielić instrukcję kopiowania pliku .jar na kilka mniejszych instrukcji i zapewnić wykorzystanie ponownych warstw, gdy zmienimy tylko kod źródłowy aplikacji.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"zapewnić wykorzystanie ponownych warstw" -> "zapewnić ponowne wykorzystanie warstw"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione

COPY --from=builder /work/spring-boot-loader/ ./
COPY --from=builder /work/snapshot-dependencies/ ./
COPY --from=builder /work/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A tak z ciekawości - wcześniej mieliśmy CMD a tutaj ENTRYPOINT - pomiędzy jednym i drugim jest różnica. Dlaczego CMD stał się zły?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CMD nie stał się zły, gdzieś w momencie pisania własnych obrazów zasugerowałem się przykładami z Internetu i tam był ENTRYPOINT. Poprawić to tak żeby było spójnie?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ujednolicone do CMD

<layers xmlns="http://www.springframework.org/schema/boot/layers"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
https://www.springframework.org/schema/boot/layers/layers-{spring-boot-xsd-version}.xsd">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spring-boot-xsd-version - może warto zaznaczyć, że tu trzeba wpisać numerek ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dodane

<layer>dependencies</layer>
<layer>spring-boot-loader</layer>
<layer>snapshot-dependencies</layer>
<layer>jaxb-dependencies</layer>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ta kolejność sugeruje, że jaxb zmienia się częściej niż snapshot

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zamienione

}
intoLayer("dependencies")
}
layerOrder = listOf("dependencies", "spring-boot-loader", "snapshot-dependencies", "application", "jaxb-dependencies")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jaxb-dependencies na końcu? chyba bez sensu

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione

COPY --from=builder /work/dependencies/ ./
COPY --from=builder /work/spring-boot-loader/ ./
COPY --from=builder /work/snapshot-dependencies/ ./
COPY --from=builder /work/jaxb-dependencies/ ./
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ta kolejność sugeruje, że jaxb zmienia się częściej niż snapshot

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione



## Podsumowanie
Wykorzystanie warstwowego budowania plików jar może pomóc z znacznym zmniejszeniu pamięci dyskowaej wykorzystywanej na przechowywanie gotowych obrazów Docker. Warto pamiętać o prawidłowej kolejności operacji w pliku Dockerfile oraz o możliwości definiowania własnych warstw zależności.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"pamięci dyskowaej" -> "pamięci dyskowej"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione

</layers>
```

Należy pamiętaj aby przy konfiguracji pliku layers.xml uzupełnić wersję zapisaną pod zmienną _spring-boot-xsd-version_

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: należy pamiętać

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oraz przecinek przed aby

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione


Należy pamiętaj aby przy konfiguracji pliku layers.xml uzupełnić wersję zapisaną pod zmienną _spring-boot-xsd-version_

2.Do plugina tworzącego warstwowego jarka dodajemy wskazanie na pliku z konfiguracją warstw

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spacja, literówka i kolokwializm :)
sugestia:
w konfiguracji plugina tworzącego warstwowego jara wskazujemy plik z konfiguracją warstw

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

w konfiguracji plugina tworzącego warstwowy .jar wskazujemy plik z konfiguracją warstw
?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione

@pogoma pogoma changed the title [2024-07-12] Tworzenie wydajnych obrazów dockerowych w Springu [2024-XX-XX] Tworzenie wydajnych obrazów dockerowych w Springu May 31, 2024
---

## Jak działa budowanie obrazów Dockerowych?
Budowanie obrazów Dockerowych polega na tworzeniu niemodyfikowalnych "szablonów" aplikacji i jej zależności, które mogą być uruchamiane w izolowanych kontenerach. Proces ten jest zautomatyzowany za pomocą plików o nazwie Dockerfile.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

obrazów dockerowych (z małej)
to "jej" wydaje mi się tu zbędne

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione

## Jak działa budowanie obrazów Dockerowych?
Budowanie obrazów Dockerowych polega na tworzeniu niemodyfikowalnych "szablonów" aplikacji i jej zależności, które mogą być uruchamiane w izolowanych kontenerach. Proces ten jest zautomatyzowany za pomocą plików o nazwie Dockerfile.

Każdy plik Dockerfile zawiera listę instrukcji wykonywanych w podanej kolejności w momencie budowania obrazu. Docker otrzymaną listę instrukcji konwertuje na warstwy składające się na budowany obraz i posiadające określony rozmiar w przestrzeni dyskowej.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docker konwertuje otrzymaną listę instrukcji na warstwy, które składają się na budowany obraz i mają określony rozmiar w przestrzeni dyskowej.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione


![Schemat budowania obrazu](/assets/img/posts/2024-07-12-wydajne-tworzenie-obrazów-dockerowych-w-springu/builder.png)

Podczas uruchomienia budowania builder podejmuję próbę ponownego wykorzystania warstw z poprzednich wersji. Jeśli warstwa obrazu się nie zmieni, builder wyciąga ją z cache, a jeśli warstwa uległa zmianie tworzy ją na nowo.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jeśli warstwa obrazu jest niezmieniona, builder wyciąga ją z cache. Jeśli warstwa uległa zmianie, tworzy ją na nowo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione


![Schemat budowania obrazu z cache](/assets/img/posts/2024-07-12-wydajne-tworzenie-obrazów-dockerowych-w-springu/cache.png)

W tym wypadku bardzo ważna jest kolejność deklarowania instrukcji tak, aby największa ich ilość była pobierania z cache. Dla powyższego przykładu możemy wykonać optymalizację:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tak stricte gramatycznie to w tym zdaniu "ich" odnosiłoby się do instrukcji...a chodzi chyba o warstwy?
odwróciłabym to zdanie (chyba, że jednak źle interpretuję)

Aby z cache była pobierana jak największa liczba warstw, bardzo ważna jest kolejność deklarowania instrukcji.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione

W tym wypadku bardzo ważna jest kolejność deklarowania instrukcji tak, aby największa ich ilość była pobierania z cache. Dla powyższego przykładu możemy wykonać optymalizację:
![Schemat budowania obrazu z cache optymalizacja](/assets/img/posts/2024-07-12-wydajne-tworzenie-obrazów-dockerowych-w-springu/cache2.png)

Dzięki temu przy następnym budowaniu trzy warstwy zostaną ponownie wykorzystane zamiast dwóch.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dzięki temu, przy następnym budowaniu, builder ponownie wykorzysta trzy, a nie tylko dwie warstwy.

może tak?

Copy link
Contributor Author

@BartoszPietrowiak BartoszPietrowiak Jun 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tak brzmi lepiej, poprawiłem

</layers>
```

Należy pamiętaj aby przy konfiguracji pliku layers.xml uzupełnić wersję zapisaną pod zmienną _spring-boot-xsd-version_

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oraz przecinek przed aby


Należy pamiętaj aby przy konfiguracji pliku layers.xml uzupełnić wersję zapisaną pod zmienną _spring-boot-xsd-version_

2.Do plugina tworzącego warstwowego jarka dodajemy wskazanie na pliku z konfiguracją warstw

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

w konfiguracji plugina tworzącego warstwowy .jar wskazujemy plik z konfiguracją warstw
?

}
}
```
W pliku dockerfile dodajemy kopiowanie nowej warstwy:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dockerfile

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione



## Podsumowanie
Wykorzystanie warstwowego budowania plików jar może pomóc ze znacznym zmniejszeniem pamięci dyskowej wykorzystywanej na przechowywanie gotowych obrazów Docker. Warto pamiętać o prawidłowej kolejności operacji w pliku Dockerfile oraz o możliwości definiowania własnych warstw zależności.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warstwowe budowanie plików .jar może znacznie zmniejszyć wykorzystanie pamięci dyskowej, w której przechowujemy gotowe obrazy Docker.
?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione

- docker
---

## Jak działa budowanie obrazów Dockerowych?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo, jako przymiotnik, "dockerowy" możemy pisać małą literą

Copy link
Contributor Author

@BartoszPietrowiak BartoszPietrowiak Jun 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione

@pogoma pogoma merged commit f83d225 into master Jun 28, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants