Logo

Wprowadzenie do Dockera

Opis: Zostanie omówione wprowadzenie do Dockera, w tym problem środowiska developerskiego, podstawowe pojęcia i konfiguracja narzędzia, a także praca z kontenerami, tworzenie obrazów przy użyciu Dockerfile oraz ich uruchamianie, umożliwiające budowanie i uruchamianie aplikacji (np. React) w izolowanym środowisku.

Problem środowiska developerskiego

W pracy programisty jednym z najczęstszych źródeł problemów nie jest sam kod, lecz środowisko, w którym ten kod jest uruchamiany. Różnice w konfiguracji potrafią powodować błędy, które są trudne do wykrycia i jeszcze trudniejsze do odtworzenia u innych osób.

Różnice między systemami (Windows / macOS / Linux)

Każdy system operacyjny działa nieco inaczej:

  • inne systemy plików (np. różnice w ścieżkach: \ vs /)

  • różne uprawnienia do plików

  • inne sposoby instalacji i zarządzania programami

  • różnice w działaniu terminala i narzędzi systemowych

Przykład: aplikacja działa poprawnie na Linuxie, ale na Windowsie pojawiają się błędy związane z uprawnieniami lub ścieżkami.

Problem "u mnie działa"

To klasyczny problem w zespołach developerskich:

Program działa na komputerze autora, ale nie działa u innych osób.

Powody:

  • inne wersje języka (np. Node.js)

  • inne wersje bibliotek

  • brakujące zależności

  • różnice w konfiguracji systemu

Efekt:

  • strata czasu na debugowanie

  • trudności we współpracy zespołowej

  • problemy przy wdrażaniu aplikacji

Zależności Node.js i npm

W projektach opartych o Node.js pojawia się dodatkowa warstwa problemów:

  • różne wersje Node.js (np. 16 vs 18)

  • różne wersje npm

  • konflikty między paczkami

  • brak spójności między środowiskami

Mimo pliku package.json, który opisuje zależności, nadal mogą występować różnice wynikające z:

  • systemu operacyjnego

  • architektury sprzętu

  • wersji runtime

Sens izolacji środowiska

Aby rozwiązać powyższe problemy, stosuje się izolację środowiska.

Polega ona na tym, że:

  • aplikacja działa w odseparowanym środowisku

  • środowisko zawiera dokładnie te same wersje narzędzi i bibliotek

  • jest niezależne od systemu hosta

Dzięki temu:

  • każdy programista pracuje w identycznych warunkach

  • eliminujemy problem "u mnie działa"

  • łatwiej wdrażać aplikacje na serwerach

Podsumowanie - dlaczego Docker?

Docker rozwiązuje powyższe problemy poprzez:

  • tworzenie spójnych, powtarzalnych środowisk

  • izolację aplikacji i ich zależności

  • możliwość uruchomienia projektu identycznie na każdym systemie

Podstawy Dockera (pojęcia)

Aby efektywnie korzystać z Dockera, należy najpierw zrozumieć jego podstawowe pojęcia i sposób działania. Ten dział wprowadza kluczową terminologię, na której opiera się dalsza praca.

Co to jest Docker

Docker to narzędzie, które umożliwia uruchamianie aplikacji w izolowanych środowiskach, zwanych kontenerami.

Można o nim myśleć jako o:

  • lekkiej warstwie uruchomieniowej dla aplikacji

  • sposobie na "spakowanie" aplikacji razem z całym jej środowiskiem (biblioteki, zależności, konfiguracja)

Dzięki temu aplikacja działa identycznie:

  • na komputerze developera

  • na komputerze innego członka zespołu

  • na serwerze produkcyjnym

Image vs Container

To dwa najważniejsze pojęcia w Dockerze.

Image (obraz)
To "przepis" lub szablon aplikacji. Zawiera:

  • kod aplikacji

  • zależności

  • konfigurację

  • instrukcję uruchomienia

Image jest niezmienny (immutable) - nie uruchamia się samodzielnie.

Container (kontener)
To działająca instancja obrazu.

Czyli:

  • image - definicja

  • container - działający program

Można mieć wiele kontenerów utworzonych z jednego obrazu.

Konteneryzacja (w prostych słowach)

Konteneryzacja to sposób uruchamiania aplikacji w odizolowanych "paczkach".

W praktyce oznacza to:

  • aplikacja + wszystkie zależności są zamknięte w jednym środowisku

  • środowisko działa niezależnie od systemu operacyjnego użytkownika

  • nie ma konfliktów między projektami

Prosta analogia:

  • kontener = "pudełko", w którym jest wszystko, co potrzebne do uruchomienia aplikacji

Dlaczego Docker != maszyna wirtualna

Docker często jest mylony z maszynami wirtualnymi, ale to inne podejście.

Maszyna wirtualna (VM):

  • emuluje cały system operacyjny

  • zawiera własne jądro (kernel)

  • jest ciężka (dużo RAM, wolniejszy start)

Docker (kontenery):

  • współdzieli kernel systemu hosta

  • uruchamia tylko aplikację i jej zależności

  • jest lekki i szybki

Najważniejsza różnica:

  • VM = pełny komputer w komputerze

  • Docker = izolowany proces w systemie

Podsumowanie

Docker wprowadza nowy sposób pracy z aplikacjami:

  • zamiast instalować wszystko lokalnie -> uruchamiamy kontener

  • zamiast martwić się konfiguracją -> używamy gotowego obrazu

Instalacja i konfiguracja Dockera

W tym etapie student przechodzi od teorii do praktyki - instaluje Dockera i uruchamia pierwszy kontener.

Docker Desktop (Windows / macOS)

Najprostszym sposobem instalacji Dockera na systemach desktopowych jest użycie Docker Desktop.

Kroki instalacji:

  • Wejdź na oficjalną stronę Dockera

  • Pobierz Docker Desktop dla swojego systemu (Windows lub macOS)

  • Uruchom instalator i przejdź przez standardowy proces instalacji

  • Po zakończeniu uruchom aplikację

Wymagania (ważne):

  • Windows: włączone WSL2 (Windows Subsystem for Linux)

  • macOS: kompatybilny procesor (Intel lub Apple Silicon)

Pierwsze uruchomienie

Po uruchomieniu Docker Desktop:

  • aplikacja startuje w tle

  • pojawia się ikona Dockera w pasku systemowym

  • Docker automatycznie uruchamia tzw. Docker Engine

Warto sprawdzić, czy wszystko działa poprawnie.

W terminalu wpisz:

docker --version

Jeśli pojawi się numer wersji - Docker jest poprawnie zainstalowany.

Test działania - pierwszy kontener

Najprostszy test to uruchomienie gotowego obrazu testowego:

docker run hello-world

Co się tutaj dzieje?

Po wykonaniu tej komendy Docker:

  1. Sprawdza, czy obraz hello-world istnieje lokalnie

  2. Jeśli nie - pobiera go z repozytorium (Docker Hub)

  3. Tworzy kontener na podstawie obrazu

  4. Uruchamia go

  5. Wyświetla komunikat testowy

Jeśli wszystko działa poprawnie, zobaczysz komunikat informujący, że Docker działa prawidłowo.

Typowe problemy

Na tym etapie mogą pojawić się błędy:

  • Docker nie jest uruchomiony
    - uruchom Docker Desktop

  • Brak WSL2 (Windows)
    - doinstaluj i ustaw jako domyślny backend

  • Brak uprawnień
    - uruchom terminal jako administrator

Podsumowanie

Po wykonaniu powyższych kroków:

  • Docker jest zainstalowany

  • działa w tle jako usługa

  • potrafisz uruchomić pierwszy kontener

To fundament pod dalszą pracę (obrazy, Dockerfile, docker-compose).

Podstawowe komendy Dockera

Po zainstalowaniu Dockera kolejnym krokiem jest nauczenie się podstawowych komend, które pozwalają zarządzać kontenerami i obrazami. To absolutne minimum potrzebne do pracy.

docker run - uruchamianie kontenera

To najważniejsza komenda.

Służy do:

  • uruchamiania nowego kontenera

  • pobierania obrazu (jeśli go nie ma lokalnie)

Przykład:

docker run hello-world

Uruchamianie nginx (praktyczny przykład)

Uruchommy prosty serwer WWW:

docker run -d -p 8080:80 nginx

Co oznaczają parametry:

  • -d - tryb w tle (detached)

  • -p 8080:80 - mapowanie portów (localhost:8080 -> kontener:80)

  • nginx - nazwa obrazu

Po uruchomieniu wejdź w przeglądarce na:

http://localhost:8080

Powinna pojawić się strona powitalna nginx.

docker ps - lista kontenerów

Pokazuje działające kontenery:

docker ps

Aby zobaczyć wszystkie (również zatrzymane):

docker ps -a

docker stop - zatrzymywanie kontenera

Zatrzymuje działający kontener.

docker stop <ID_kontenera>

ID można skopiować z docker ps.

docker images - lista obrazów

Wyświetla wszystkie obrazy zapisane lokalnie:

docker images

Zobaczysz m.in.:

  • nazwę obrazu

  • tag (wersję)

  • rozmiar

docker rm - usuwanie kontenera

Usuwa zatrzymany kontener:

docker rm <ID_kontenera>

Jeśli kontener działa - najpierw trzeba go zatrzymać (docker stop).

Typowy workflow (praktyka)

Najczęstszy scenariusz pracy wygląda tak:

  1. Uruchom kontener:

    docker run -d -p 8080:80 nginx
  2. Sprawdź, czy działa:

    docker ps
  3. Zatrzymaj:

    docker stop <ID>
  4. Usuń:

    docker rm <ID>

Podsumowanie

Te komendy pozwalają na podstawową kontrolę nad Dockerem:

  • uruchamiasz kontenery

  • sprawdzasz ich stan

  • zatrzymujesz i usuwasz

To fundament przed przejściem do bardziej zaawansowanych tematów.

Dockerfile - podstawy

W poprzednich etapach korzystałeś z gotowych obrazów. Teraz przechodzimy krok dalej - tworzenie własnych obrazów za pomocą pliku Dockerfile.

Czym jest Dockerfile

Dockerfile to plik tekstowy zawierający instrukcje, jak zbudować obraz Dockera.

Można go traktować jako:

  • przepis na stworzenie środowiska

  • deklaratywną konfigurację aplikacji

Dzięki Dockerfile:

  • każdy może zbudować identyczny obraz

  • środowisko jest powtarzalne i wersjonowane

Podstawowe instrukcje

Dockerfile składa się z kolejnych instrukcji wykonywanych krok po kroku.

FROM - baza obrazu

Określa bazowy obraz, od którego zaczynasz

  • to jak "system operacyjny + środowisko"

  • np. masz już zainstalowany Node

Bez FROM Docker nie wie, na czym budować obraz

FROM node:18

WORKDIR - katalog roboczy

Ustawia katalog roboczy w kontenerze

  • coś jak cd /app

  • wszystkie kolejne komendy działają w tym folderze

Jeśli folder nie istnieje - Docker go tworzy

WORKDIR /app

COPY - kopiowanie plików

Kopiuje pliki z Twojego komputera do kontenera

  • pierwszy . skąd (Twój projekt)

  • drugi . dokąd (/app, bo WORKDIR)

COPY package.json .
COPY . .

RUN - wykonywanie poleceń

Wykonuje komendę podczas budowania obrazu

  • instalacja zależności

  • konfiguracja środowiska

  • budowanie aplikacji

Ważne:

  • RUN działa przy docker build

  • jego efekt zapisuje się w obrazie

RUN npm install

CMD - komenda startowa

Określa co ma się uruchomić, gdy startuje kontener

  • to jest "komenda startowa"

  • uruchamia się przy docker run

CMD ["npm", "start"]

Struktura prostego obrazu Node / React

Najprostszy możliwy Dockerfile dla aplikacji React (np. stworzonej przez create-react-app) wygląda tak:

FROM node:18

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

CMD ["npm", "start"]

Co robi każda linia?

  • FROM node:18
    pobiera bazowy obraz z Node.js (wersja 18 - potrzebna do Reacta)

  • WORKDIR /app
    ustawia katalog roboczy w kontenerze

  • COPY package*.json ./
    kopiuje plik package.json oraz package.lock.json. Tylko pliki z zależnościami, nic więcej

  • RUN npm install
    instaluje zależności (tworzy node_modules)

  • COPY . .
    kopiuje całą resztę projektu do kontenera

  • CMD ["npm", "start"]
    uruchamia aplikację React po starcie kontenera (dev server)

Dlaczego to jest ułożone w tej kolejności?

Najpierw kopiujesz package.json, potem npm install

Dzięki temu:

  • Docker zapamiętuje (cache) instalację zależności

  • nie musi ich instalować od nowa przy każdej zmianie kodu

Podsumowanie w jednym zdaniu

Pobierasz Node - ustawiasz folder - instalujesz zależności - kopiujesz kod - uruchamiasz aplikację

Budowanie obrazu

1. Wejdź do katalogu projektu

Tam gdzie masz: Dockerfile i package.json

2. Zbuduj obraz

docker build -t react-app .

Co oznacza ta komenda?

  • docker build - buduje obraz

  • -t react-app - nadaje nazwę obrazowi

  • . - użyj aktualnego katalogu (tam jest Dockerfile)

3. Uruchom kontener

docker run -p 3000:3000 react-app
  • -p 3000:3000 - mapowanie portów (localhost - kontener)

4. Otwórz w przeglądarce

http://localhost:3000

Podsumowanie

Dockerfile pozwala:

  • zautomatyzować tworzenie środowiska

  • tworzyć własne obrazy

  • przenosić aplikacje między systemami bez problemów

To kluczowy element pracy z Dockerem.