w Praktyce
4 godz. 33 min · Docker · Full-stack i Programowanie
Wojciech PołowniakSr. Fullstack EngineerW początkowych sekcjach kursu, zrozumiesz czym jest Docker i jakie ma zalety wobec rozwiązań oferujących pracę z serwerami lokalnymi, np. XAMPP - poznasz jego architekturę, założenia oraz najważniejsze pojęcia, których nieznajomość często spędza sen z powiek nawet doświadczonym programistom.
Jako że Docker jest to narzędzie dla programistów i administratorów systemów operacyjnych, lwia część pracy z tym narzędziem odbywa się w konsoli. Przedstawię Ci najważniejsze polecenia powiązane z tą technologią oraz zestaw dobrych praktyk i protipów które zawstydzą niejednego inżyniera oprogramowania.
W tej sekcji tego kursu przejdziemy przez najważniejsze punkty tworzenia skonteneryzowanych aplikacji z perspektywy programisty aplikacji internetowych - jeśli chcesz szybko rozpocząć swoją przygodę z Dockerem, ponieważ znasz już podstawy teorii i czujesz się wystarczająco pewnie - możesz zacząć z tego miejsca! A jeśli tempo będzie zbyt szybkie - zawsze możesz wrócić do części teoretycznej pracy z Dockerem
Przebudowywanie zasobów na żywo, dynamiczne odczytywanie zawartości plików... To podstawowe koncepty które współcześni programiści sieci web biorą za pewnik. Przy nieznajomości Dockera, łatwo jest strzelić sobie w stopę i utrudnić swoją pracę, zabierając sobie możliwość korzystania z powyższych funkcjonalności. W tym kursie, pokażę Ci jak wygodnie pracować z Dockerem w środowisku developerskim.
Jedną z wielu zalet Dockera jest niewątpliwie proste przenoszenie zmian konfiguracji i infrastruktury ze środowiska developerskiego na produkcyjne. W tym kursie, poza przyswojeniem podstawowej wiedzy na temat Dockera poznasz szereg dobrych praktyk w kontekście bezpieczeństwa oraz przygotowywania Twoich aplikacji pod środowisko, na którym będzie uruchomiona Twoja aplikacja gdy uznasz że jest gotowa by ujrzeć światło dzienne.
Ten kurs to zestaw kompleksowej wiedzy dzięki której dowiesz się jak od zera, na żywo, stworzyć aplikację na Twoim lokalnym środowisku - i jakie kroki należy podjąć, aby móc zobaczyć ją w internecie - wszystko w kontekście Dockera, wysokiej skalowalności i bezpieczeństwa. W jednej z ostatnich lekcji kursu zobaczysz jak robię deploy na serwery DigitalOcean by uzyskać link do swojej nowo zbudowanej aplikacji internetowej.
Ten kurs jest kierowany do webdeveloperów, bądź zaawansowanych programistów którzy nie pracowali jeszcze z Dockerem. Przydatne może być zrozumienie interfejsu linii poleceń czyli tzw. konsoli, oraz podstawowa wiedza na temat web developmentu czy systemów operacyjnych. Jeśli potrafisz korzystać z systemu kontroli wersji git, na pewno ułatwi to Tobie zrozumienie konceptu pracy z poleceniami dockera. Niemniej, każde zagadnienie staram się tłumaczyć na bieżąco.
Cześć!
W tej lekcji przejdziemy się przez przykładowy proces.
Budowania obrazu produkcyjnego jednej z aplikacji, nad którymi kiedyś pracowałem.
Nie jest to proces idealny, natomiast jest.
Przykładem tego, jak możecie pracować z
chwilami w waszych środowiskach produkcyjnych.
No i oczywiście tutaj są.
Jest to narysowane tak, aby nie było wiadomo jaki to jest projekt.
W związku z czym przejdę tutaj przez ten.
Plik, wytłumaczę co się tutaj dzieje.
Wytłumaczę jakie tutaj są polecenia w tym filmu użyte i dlaczego.
No i. Być może postaram się przekazać kilka
dobrych praktyk w kontekście bezpieczeństwa.
Więc pierwszą rzeczą, która nam się rzuca
w oczy to widzimy, że obraz ten jest budowany.
Z wersji 14 17.
Ta wersja mogłaby już spokojnie zostać podbita na jakąś wyższą 17 16.
Ostatnią stabilną wersją na moment nagrywania kursu, więc jest to.
Już troszkę starsze.
Chociaż nawet bardzo szybko zmienia swoje wersje.
Ale ważna jest tutaj to, że po pierwsze
korzystamy z Alpina, czyli te obrazy są lżejsze.
Natomiast nie jest to po prostu też latest.
Jeżeli widzicie sam obraz, który
ma coś takiego, że po prostu jest nazwa obrazu bez żadnego tagu.
Jest to zła. Praktyka.
Najlepiej zawsze dodawać jawnie tag o który którą wersję kontenera nam chodzi.
Następnie mamy tutaj argumenty, które mogą
zostać przekazane do Docker Bilda na etapie budowania.
Czyli jeśli chcielibyśmy.
Aby w naszym.
W naszych informacjach o tym obrazie np.
przy Docker image jpeg wyświetlały się informacje o tym, kiedy ten obraz został.
Ustawiony, czy.
Jaki jest commit gotowy, czyli hash hash gita dla tego obrazu, który został
wygenerowany, to możecie to przekazać w parametrach do docker Bilda.
I tutaj widzimy, że poprzez tabelki
wystawiamy te informacje na zewnątrz i jest pewna konwencja tego jak powinno.
Się pisać literki.
Tutaj oczywiście możecie przejść sobie do dokumentacji.
Natomiast konwencja jest taka, że jest to odwrotna notacja domenowe.
Nie wiem jaka jest poprawna. Nazwa.
Tego po polsku. W każdym razie tak jak macie np.
. Www kropka google dot.
COM to tak naprawdę domeny są.
Czytane od prawej do lewej, czyli najpierw w domenie.
COM znajdowane jest google i następnie podkategoria www.
I akurat w przypadku tabelek jest to
odwrócona notacja, to znaczy najpierw widzimy nazwę organizacji.
Następnie open container to jest to po prostu tutaj specyfikacja.
Oczywiście też możemy przejść do niej
bezpośrednio, nie konkretnie, tylko do słowa kluczowego w dokumentacji Dockera.
No i są to takie ogólnie przyjęte.
Literki, które mogą zostać.
Wykorzystywane przez różne skrypty, przez automatyzację czy po prostu przez.
Developerów, którzy znają się na tych wartościach i wiedzą gdzie ich.
Szukać. No i możemy tutaj sobie wpisać np.
autora danego obrazu.
I jego adres email w domenie kiedy ten obraz został.
Stworzony, jaki był hash danego komitetu, nazwa tego projektu, link do repozytorium.
Czy link do danego pliku z którego zostało to wygenerowane?
Licencja. No i generalnie wszystkie customowe.
Rzeczy właśnie robimy w tej odwróconej notacji.
Czyli najpierw dajemy sobie tą nazwę domeny, potem nazwę naszej.
Organizacji i dowolne.
Pole, które chcemy opisać. Tutaj.
Jest to projekt, który bazował na audio i video, w związku z czym
niestety domyślny obraz nie wystarczył, aby aplikacja działała poprawnie.
W związku z czym trzeba było doinstalować różne zależności.
Czyli np. w Debianie.
Trzeba byłoby zrobić apt get update i wtedy apt get install.
Wszystkich pojedynczych. Zależności.
Czyli to są wszystko zależności, które musiały zostać zainstalowane.
I teraz właśnie zauważyłem, że
obraz definitywnie został przygotowany pod Debiana.
Natomiast został zmieniony tutaj na Alpine.
Czyli gdybyśmy spróbowali. Go zbudować.
On by nie zadziałał, ponieważ w Alpine nie wykorzystujemy.
Poleceń apt get update install aby zaktualizować nasze zależności.
Czyli moglibyśmy tutaj zrobić jakiegoś streama Może.
Albo jeżeli nam zależy na jakiejś
konkretnej wersji Debiana to po prostu podać ją tutaj.
Więc jeśli przejdziemy dalej, to
oczywiście w tej warstwie wszystkie zależności zostały zainstalowane.
Tutaj zostały dodawane jakieś polecenia,
które były powiązane z Dockera, czyli w momencie startu.
Aplikacji na przykład nasze entry pointy mogły być tutaj zdefiniowane.
No i kolejną ważną rzeczą jest to, że nie wiem czy zauważyliście, ale korzystaliśmy.
Z roota na wszystkich obrazach, które do tej pory uruchomiliśmy.
Domyślnym użytkownikiem był root.
I też nie jest to idealna. Praktyka.
Generalnie nie powinniśmy uruchamiać naszych aplikacje jako root.
Pomimo tego, że kontenery są.
Ze kapsułą owiane i raczej ciężko.
Jest się wydostać poza nie.
Chyba, że faktycznie mamy do czynienia z
hakerem, który korzysta z różnych exploitów.
To dobra praktyka mówi, aby po.
Prostu nie uruchamiać aplikacji jako root,
w związku z czym trzeba tego użytkownika nie dodać.
I to są po prostu polecenia związane z zarządzaniem użytkownikami w Debianie.
Tutaj dodajemy jakieś zależności naszego. Projektu.
To znaczy. Kod źródłowy, uaktualniane uprawnienia do.
FSA.
Dla tego projektu.
Zmieniamy Owner Ship i to jest bardzo ważny krok.
Zmiana użytkownika, czyli domyślnie.
User ustawiony jest na roota.
W momencie kiedy my wiemy, że już nie
będziemy aplikować żadnych poleceń, które mogą.
Wymagać dostępu do roota do administratora.
Tak naprawdę na systemach uniksowych.
Możemy zmienić tego użytkownika.
Na użytkownika nie.
Wtedy wszystkie polecenia poniżej.
Tej klauzuli będą wywoływane jako nie root.
Więc jak widzicie tutaj tych poleceń jest naprawdę sporo i są też takie, których nie
wspomniałem w poprzednich lekcjach, ale to dlatego, bo raczej wykorzystuje.
Się je tylko i wyłącznie przy budowaniu obrazów produkcyjnych.
A aby budować obrazy produkcyjne.
To też trzeba być bardzo ostrożnym, bo z reguły takie aplikacje są już wystawione
w internecie, więc każdy ma do nich dostęp.
Jeżeli wie co robi, jest w stanie łatwo
wkraść się na odpowiednie wersje danych, systemów operacyjnych czy
języków programowania, jeżeli zna odpowiednie exploity do
dyspozycji albo po prostu korzysta ze specjalnego oprogramowania.
Więc jeśli chodzi o.
Ogólnokrajowe rzeczy, to można to tak podsumować, żeby nie uruchamiać.
Kontenerów jako root, czyli na.
Pewno tego user user czy jakakolwiek inna nazwa jaką sobie
ustawiliśmy, żeby się pojawiła przed końcem tego filmu.
Ona się może pojawić naprawdę. W ostatniej linijce.
To nie ma znaczenia, ważne żeby to było faktycznie w pliku.
No i też tutaj. Jako że to.
Jest aplikacja narodowa
to zamiast npm install powinniśmy tutaj wykorzystać npm,
które po prostu będzie zainstalowało zależności w trybie produkcyjnym
i będzie miało kilka innych kroków powiązanych z logiką.
I jeśli chodzi o bezpieczeństwo.
Ogólnie też warto jest dodać sobie tutaj flagę Ignore scripts,
czyli ta flaga sprawi, że wasze skrypty, które możecie mieć w pakiet Jacksonie np.
Install one nie zostaną wykonane.
No i to też się aplikuje do wszystkich.
Zależności, które pobieracie.
Czyli jeżeli macie zależność ICS, ktoś wypchnie nową wersję tej zależności i
doda w post install jakiś złośliwy kod, no to dzięki temu Wasza
aplikacja nie ucierpi, ponieważ po prostu tego posta instalacja nie wywoła.
No i tutaj jest jakieś czyszczenie
plików FSA po wykonanej pracy, ale tak jak mówiłem nie jest to obraz idealny.
Moglibyśmy tutaj wykorzystać na przykład Multi stage buildy.
Czyli zamiast instalować tutaj zależności FSA, a potem je usuwać
moglibyśmy po prostu zbudować tą aplikację.
Jeżeli to jest jakaś prywatna paczka NPM owe np.
na gicie i po prostu skopiować kod źródłowy poprzez kopi dash dash from
czyli wykorzystując właśnie warstwę z innego build czyli multi sequence.
Więc to tyle w tym materiale.
Mam nadzieję, że daje wam to jakieś.
Pojęcie o tym jak mogą wyglądać obrazy produkcyjne.
Ważne jest to, żeby one. Były.
J.w.
Czyli żeby nie dało się im też zmieniać treści, żeby one się nie
kompilowane na przykład w runtime, czyli żeby nie było sytuacji, że dopiero npm
install dzieje się wewnątrz entry point, bo po prostu będzie nam opóźniać start
naszej aplikacji za każdym razem jak będziemy uruchamiać nowy kontener z danego
obrazu i ten npm install będzie się za każdym razem wykonywał.
Także myślę, że to wszystko.
W tej sekcji tego kursu i w następnej
sekcji, czyli w poradach i trikach omówię kilka dobrych praktyk i przydatnych
skryptów, które możecie wykorzystać w pracy z tokenem.
Zarówno na środowiskach produkcyjnych.
Jak i deweloperskich.
Dockerfile · 9 min
FROM node:14.17.0-slim
# set this with shell variables at build-time.
# If they aren't set, then not-set will be default.
ARG CREATED_DATE=not-set
ARG SOURCE_COMMIT=not-set
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8
# www.google.com.
# labels from https://github.com/opencontainers/image-spec/blob/master/annotations.md
LABEL org.opencontainers.image.authors=author@domain
LABEL org.opencontainers.image.created=$CREATED_DATE
LABEL org.opencontainers.image.revision=$SOURCE_COMMIT
LABEL org.opencontainers.image.title="My super NodeJS project"
LABEL org.opencontainers.image.url=https://bitbucket.org/myorg/myname/src/master/docker/prod/Dockerfile
LABEL org.opencontainers.image.source=https://bitbucket.org/myorg/myname/src/master
LABEL org.opencontainers.image.licenses=MIT
LABEL com.myorg.packageversion="5.4.1"
# install dependencies for additional modules and app to work
RUN apt-get update &&\
apt-get install -yq gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \
libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \
libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \
libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 \
ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget \
lsof screen nano sudo ca-certificates expect iproute2 libgbm1
# Add container related bash scripts
ADD ./docker/scripts /scripts
# Create user and group for running puppeteer
RUN groupadd -r nonrootuser && useradd -r -g nonrootuser \
&& mkdir -p /home/nonrootuser/.ssh \
&& chown -R nonrootuser:nonrootuser /home/nonrootuser \
&& chown -R nonrootuser:nonrootuser /scripts \
&& chmod a+x /scripts/*
ADD . /home/nonrootuser/src
# update permissions for ssh keys for it to be readable
RUN cp -R /home/nonrootuser/src/ssh/* /home/nonrootuser/.ssh/ \
&& rm -Rf /home/nonrootuser/src/ssh \
&& chown -R nonrootuser:nonrootuser /home/nonrootuser/.ssh
# make sure nonrootuser is the owner of the app
RUN chown -R nonrootuser:nonrootuser /home/nonrootuser/src
RUN chown -R nonrootuser:nonrootuser /usr/local/
USER nonrootuser
WORKDIR /home/nonrootuser/src
RUN npm ci --ignore-scripts
# Remove ssh keys after pulling the private package as those are no longer needed
RUN rm -rf ~/.ssh/