Docker na Ubuntu: Kompletny przewodnik instalacji i użytkowania
Docker to otwartoźródłowa platforma konteneryzacji, która pakuje aplikacje i ich zależności w izolowane, przenośne jednostki zwane kontenerami. W przeciwieństwie do maszyn wirtualnych, kontenery współdzielą jądro systemu operacyjnego hosta, co czyni je znacznie lżejszymi, szybszymi w uruchamianiu i bardziej efektywnymi pod względem zasobów — kluczowa różnica dla każdego, kto uruchamia obciążenia w środowisku VPS Hosting, gdzie zasoby obliczeniowe bezpośrednio wpływają na koszty i wydajność.
Ten przewodnik obejmuje pełny proces instalacji Docker na Ubuntu 20.04, 22.04 i 24.04 LTS, w tym utwardzanie po instalacji, przepływy pracy Docker Compose oraz wzorce poleceń istotne dla środowisk produkcyjnych, które większość poradników pomija.
Wymagania wstępne i wymagania systemowe
Przed wykonaniem jakiegokolwiek polecenia sprawdź następujące kwestie:
- Wersja Ubuntu: 20.04 LTS (Focal), 22.04 LTS (Jammy) lub 24.04 LTS (Noble). Polecenie `lsb_release -cs` używane podczas konfiguracji repozytorium automatycznie wykryje nazwę kodową.
- Architektura: `amd64`, `arm64` i `armhf` są obsługiwane przez oficjalne repozytorium Docker.
- Wersja jądra: Docker wymaga jądra Linux w wersji 3.10 lub wyższej. Uruchom `uname -r`, aby to potwierdzić.
- Uprawnienia użytkownika: `sudo` lub dostęp root jest wymagany do instalacji i zarządzania demonem.
- Miejsce na dysku: Co najmniej 2 GB wolnego miejsca na partycji hostującej `/var/lib/docker`, gdzie Docker przechowuje obrazy, kontenery, wolumeny i pamięć podręczną kompilacji. W systemach produkcyjnych zamontuj ten katalog na dedykowanej partycji lub wolumenie.
Krytyczny krok przed instalacją: Jeśli wcześniej instalowałeś Docker z domyślnego repozytorium `apt` Ubuntu (pakiet `docker.io`), najpierw go usuń, aby uniknąć konfliktów z oficjalnymi pakietami Docker CE:
“`bash
sudo apt remove docker docker-engine docker.io containerd runc
“`
Krok 1: Aktualizacja pakietów systemowych
Zaktualizuj indeks pakietów i zainstalowane pakiety do najnowszych wersji przed dodaniem nowego repozytorium:
“`bash
sudo apt update
sudo apt upgrade -y
“`
Zapewnia to, że mechanizm rozwiązywania zależności `apt` działa na aktualnych metadanych pakietów i że biblioteki bazowe systemu nie są przestarzałe — co jest częstym źródłem subtelnych błędów środowiska uruchomieniowego w konteneryzowanych aplikacjach.
Krok 2: Instalacja Docker Engine z oficjalnego repozytorium
Domyślne repozytoria `apt` Ubuntu zawierają pakiet o nazwie `docker.io`, który jest utrzymywany przez Canonical i zazwyczaj pozostaje kilka wersji za oficjalnym wydaniem Docker. Do użytku produkcyjnego zawsze instaluj z własnego repozytorium Docker.
2.1 Instalacja zależności transportu i weryfikacji
“`bash
sudo apt install apt-transport-https ca-certificates curl software-properties-common gnupg lsb-release -y
“`
Dlaczego `gnupg`? Począwszy od Ubuntu 22.04, `gpg` nie zawsze jest domyślnie obecny. Jawne jego dołączenie zapobiega cichemu niepowodzeniu importu klucza GPG.
2.2 Dodanie oficjalnego klucza GPG Docker
“`bash
sudo install -m 0755 -d /usr/share/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg –dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
sudo chmod a+r /usr/share/keyrings/docker-archive-keyring.gpg
“`
Krok `chmod a+r` jest często pomijany w poradnikach, ale jest niezbędny w systemach, gdzie `apt` działa w kontekście ograniczonego użytkownika — bez niego menedżer pakietów nie może odczytać pęku kluczy i zgłosi błąd `NO_PUBKEY` podczas `apt update`.
2.3 Dodanie stabilnego repozytorium Docker
“`bash
echo
"deb [arch=$(dpkg –print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg]
https://download.docker.com/linux/ubuntu
$(lsb_release -cs) stable" |
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
“`
Podstawienie `arch=$(dpkg –print-architecture)` jest niezbędne na serwerach opartych na ARM. Zakodowanie na stałe `amd64` to częsty błąd, który powoduje ciche niepowodzenia rozwiązywania pakietów na instancjach ARM.
2.4 Instalacja Docker Engine, CLI i wtyczek
“`bash
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
“`
Opis pakietów:
| Pakiet | Rola |
|---|
| — | — |
|---|
| `docker-ce` | Demon Docker Engine (`dockerd`) |
|---|
| `docker-ce-cli` | Klient CLI (polecenie `docker`) |
|---|
| `containerd.io` | Niskopoziomowe środowisko uruchomieniowe kontenerów (zgodne z OCI) |
|---|
| `docker-buildx-plugin` | Rozszerzone możliwości kompilacji (wieloplatformowe, BuildKit) |
|---|
| `docker-compose-plugin` | Compose V2 zintegrowane jako wtyczka Docker CLI |
|---|
Uwaga dotycząca `containerd.io`: To nie jest to samo co pakiet `containerd` w domyślnym repozytorium Ubuntu. `containerd.io` Docker to specyficzna, przetestowana wersja środowiska uruchomieniowego containerd. Mieszanie obu jest znanym źródłem błędów uruchamiania demona.
Krok 3: Weryfikacja instalacji
Potwierdź, że demon jest aktywny i włączony do uruchamiania przy starcie systemu:
“`bash
sudo systemctl status docker
sudo systemctl enable docker
“`
Sprawdź zainstalowaną wersję:
“`bash
sudo docker –version
sudo docker info
“`
`docker info` jest bardziej informatywne niż samo `–version` — ujawnia używany sterownik pamięci masowej (zazwyczaj `overlay2`), sterownik cgroup (`systemd` vs `cgroupfs`) oraz liczbę CPU i ilość pamięci dostępnej dla Docker.
Uruchom kanoniczny test dymny:
“`bash
sudo docker run hello-world
“`
Pomyślne uruchomienie wyświetla komunikat „Hello from Docker!” i potwierdza, że demon Docker, pobieranie obrazu z Docker Hub i wykonywanie kontenerów działają poprawnie.
Krok 4: Konfiguracja Docker dla dostępu bez uprawnień root
Domyślnie gniazdo Docker (`/var/run/docker.sock`) jest własnością `root` i grupy `docker`. Każdy użytkownik spoza grupy `docker` musi używać `sudo` dla każdego polecenia Docker.
“`bash
sudo usermod -aG docker $USER
“`
Zastosuj członkostwo w grupie bez wylogowywania się:
“`bash
newgrp docker
“`
Zweryfikuj:
“`bash
docker run hello-world
“`
Ostrzeżenie dotyczące bezpieczeństwa: Członkostwo w grupie `docker` jest praktycznie równoważne z `sudo` bez hasła. Użytkownik w grupie `docker` może łatwo zamontować system plików hosta w kontenerze i ominąć wszystkie kontrole dostępu na poziomie systemu plików. W systemach wielodostępnych lub współdzielonych serwerach rozważ zamiast tego użycie rootless Docker:
“`bash
dockerd-rootless-setuptool.sh install
“`
Tryb rootless uruchamia demona Docker i kontenery w nieuprzywilejowanej przestrzeni nazw użytkownika, znacznie zmniejszając powierzchnię ataku. Jest to zalecana konfiguracja dla każdego środowiska, w którym wielu użytkowników współdzieli ten sam host.
Krok 5: Podstawowe polecenia Docker — dokumentacja
Zarządzanie obrazami
“`bash
Pull a specific image version from Docker Hub
docker pull nginx:1.27-alpine
List locally cached images
docker images
Remove a specific image
docker rmi nginx:1.27-alpine
Remove all dangling (untagged) images to reclaim disk space
docker image prune
Remove all unused images (not just dangling)
docker image prune -a
“`
Wskazówka produkcyjna: Zawsze pobieraj wersjonowane tagi (np. `nginx:1.27-alpine`) zamiast `latest` w zautomatyzowanych lub produkcyjnych przepływach pracy. Tag `latest` jest zmienny — może wskazywać na inny obraz po wypchnięciu do rejestru, co narusza odtwarzalność.
Cykl życia kontenera
“`bash
Run a container interactively with a pseudo-TTY
docker run -it ubuntu:22.04 /bin/bash
Run a container in detached mode with port mapping and a name
docker run -d -p 8080:80 –name my-nginx nginx:1.27-alpine
List running containers
docker ps
List all containers (including stopped)
docker ps -a
Stop a running container gracefully (SIGTERM, then SIGKILL after timeout)
docker stop my-nginx
Start a stopped container
docker start my-nginx
Remove a stopped container
docker rm my-nginx
Force-remove a running container (sends SIGKILL immediately)
docker rm -f my-nginx
View real-time logs
docker logs -f my-nginx
Execute a command inside a running container
docker exec -it my-nginx /bin/sh
“`
Inspekcja zasobów i systemu
“`bash
Display real-time resource usage statistics
docker stats
Inspect detailed container metadata (JSON)
docker inspect my-nginx
Display disk usage by Docker objects
docker system df
Remove all stopped containers, unused networks, dangling images, and build cache
docker system prune
“`
`docker system prune` to jedno z najważniejszych poleceń konserwacyjnych dla długo działających serwerów. Bez okresowego czyszczenia pamięć podręczna kompilacji Docker i zatrzymane kontenery mogą zajmować dziesiątki gigabajtów na aktywnym hoście deweloperskim lub CI.
Krok 6: Docker Compose — orkiestracja aplikacji wielokontenerowych
Docker Compose V2 (`docker-compose-plugin` zainstalowany wcześniej) jest wywoływany jako `docker compose` (ze spacją), a nie jako przestarzały `docker-compose` (z łącznikiem). Obie składnie działają, jeśli masz zainstalowaną wtyczkę, ale V2 jest aktualnym standardem.
6.1 Zrozumienie struktury pliku Compose
Utwórz katalog projektu i plik `compose.yml` (preferowana nazwa pliku w Compose V2; `docker-compose.yml` pozostaje obsługiwana dla zachowania wstecznej kompatybilności):
“`bash
mkdir ~/my-web-app && cd ~/my-web-app
nano compose.yml
“`
Realistyczny przykład produkcyjny z Nginx i usługą backendową:
“`yaml
services:
web:
image: nginx:1.27-alpine
ports:
- "8080:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./html:/usr/share/nginx/html:ro
depends_on:
- app
restart: unless-stopped
app:
image: node:20-alpine
working_dir: /usr/src/app
volumes:
- ./app:/usr/src/app
command: node server.js
environment:
- NODE_ENV=production
restart: unless-stopped
“`
Wyjaśnienie kluczowych dyrektyw Compose:
- `restart: unless-stopped` — Kontener restartuje się automatycznie po awarii lub ponownym uruchomieniu systemu, chyba że został jawnie zatrzymany przez operatora. Jest to właściwa polityka dla długo działających usług; `always` będzie restartować nawet celowo zatrzymane kontenery.
- `depends_on` — Kontroluje kolejność uruchamiania, ale nie czeka, aż usługa będzie *gotowa* (np. baza danych akceptująca połączenia). Do bramkowania gotowości użyj `healthcheck` w połączeniu z `condition: service_healthy`.
- `volumes` z `:ro` — Montowanie plików konfiguracyjnych jako tylko do odczytu zapobiega modyfikowaniu własnej konfiguracji przez skompromitowany proces kontenera.
6.2 Polecenia przepływu pracy Compose
“`bash
Start all services in detached mode
docker compose up -d
View logs for all services
docker compose logs -f
View logs for a specific service
docker compose logs -f web
List running Compose services
docker compose ps
Scale a specific service to multiple replicas
docker compose up -d –scale app=3
Stop services without removing containers
docker compose stop
Stop and remove containers, networks, and volumes
docker compose down –volumes
Rebuild images before starting (useful after code changes)
docker compose up -d –build
“`
6.3 Weryfikacja działającej usługi
“`bash
curl -I http://localhost:8080
“`
Odpowiedź `200 OK` potwierdza, że Nginx działa poprawnie. W przypadku usług działających na zdalnej instancji VPS Hosting, zastąp `localhost` publicznym adresem IP swojego serwera i upewnij się, że odpowiedni port jest otwarty w zaporze sieciowej (`ufw allow 8080/tcp`).
Krok 7: Podstawy sieci Docker
Zrozumienie modelu sieciowego Docker jest niezbędne do budowania aplikacji wielokontenerowych, które komunikują się bezpiecznie.
Domyślne sterowniki sieciowe:
| Sterownik | Przypadek użycia |
|---|
| — | — |
|---|
| `bridge` | Domyślny dla samodzielnych kontenerów; izolowana przestrzeń nazw sieci na hoście |
|---|
| `host` | Kontener współdzieli stos sieciowy hosta; maksymalna wydajność, zerowa izolacja |
|---|
| `none` | Brak dostępu do sieci; przydatny do przetwarzania wsadowego lub obciążeń wrażliwych na bezpieczeństwo |
|---|
| `overlay` | Sieć wielohostowa dla klastrów Docker Swarm |
|---|
| `macvlan` | Przypisuje adres MAC do kontenera; pojawia się jako urządzenie fizyczne w sieci |
|---|
Tworzenie i używanie niestandardowej sieci mostkowej:
“`bash
Create an isolated network
docker network create my-app-network
Run containers attached to the custom network
docker run -d –name db –network my-app-network postgres:16-alpine
docker run -d –name api –network my-app-network my-api-image
Containers on the same custom bridge network can resolve each other by name
Inside 'api', you can connect to 'db' using the hostname 'db'
“`
Niestandardowe sieci mostkowe zapewniają automatyczne rozwiązywanie DNS między kontenerami według nazwy kontenera. Domyślna sieć `bridge` tego nie robi — to kluczowa różnica, która powoduje błędy połączeń, gdy programiści zakładają, że kontenery w domyślnej sieci mogą się wzajemnie osiągać po nazwie.
Krok 8: Trwałe dane z wolumenami Docker
Kontenery są z założenia efemeryczne. Wszelkie dane zapisane wewnątrz systemu plików kontenera są tracone po jego usunięciu. Do trwałego przechowywania używaj wolumenów lub montowań bind.
“`bash
Create a named volume
docker volume create pgdata
Use the volume with a container
docker run -d
–name postgres-db
-e POSTGRES_PASSWORD=securepassword
-v pgdata:/var/lib/postgresql/data
postgres:16-alpine
List volumes
docker volume ls
Inspect a volume (shows mount point on host)
docker volume inspect pgdata
Remove unused volumes
docker volume prune
“`
Wolumeny vs. montowania bind:
| Funkcja | Nazwany wolumen | Montowanie bind |
|---|
| — | — | — |
|---|
| Zarządzany przez Docker | Tak | Nie |
|---|
| Wymagana ścieżka hosta | Nie | Tak |
|---|
| Przenośny między hostami | Tak (ze sterownikami wolumenów) | Nie |
|---|
| Najlepszy do | Danych bazy danych, stanu aplikacji | Kodu deweloperskiego, plików konfiguracyjnych |
|---|
| Mechanizm kopii zapasowej | `docker run –volumes-from` | Standardowe narzędzia systemu plików |
|---|
Krok 9: Aktualizowanie Docker
Oficjalne repozytorium Docker obsługuje aktualizacje przez standardowy mechanizm `apt`:
“`bash
sudo apt update
sudo apt upgrade -y
“`
Aby zaktualizować tylko pakiety związane z Docker bez uaktualniania całego systemu:
“`bash
sudo apt install –only-upgrade docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
“`
Sprawdź informacje o wydaniu Docker przed głównymi aktualizacjami wersji, szczególnie pod kątem zmian w sterowniku pamięci masowej, obsłudze wersji cgroup lub przestarzałych wersjach API, które mogą wpłynąć na istniejące pliki `compose.yml`.
Docker a alternatywne podejścia do konteneryzacji
| Funkcja | Docker Engine | Podman | LXC/LXD | containerd (samodzielny) |
|---|
| — | — | — | — | — |
|---|
| Architektura demona | Scentralizowany demon | Bez demona | Oparty na demonie | Oparty na demonie |
|---|
| Obsługa rootless | Tak (v20+) | Natywna | Ograniczona | Tak |
|---|
| Obsługa Docker Compose | Natywna | Przez `podman-compose` | Nie | Nie |
|---|
| Zgodność z OCI | Tak | Tak | Nie (format LXC) | Tak |
|---|
| Integracja z Kubernetes | Przez shim CRI-dockerd | Natywne CRI | Nie | Natywne CRI |
|---|
| Obsługa Windows/macOS | Docker Desktop | Ograniczona | Nie | Nie |
|---|
| Najlepsze zastosowanie | Ogólny rozwój i produkcja | Zorientowane na bezpieczeństwo, rootless | Kontenery systemowe, maszyny wirtualne | Węzły Kubernetes |
|---|
Dla zespołów uruchamiających skonteneryzowane obciążenia na dużą skalę na sprzęcie bare metal, środowisko Dedicated Servers daje pełną kontrolę nad parametrami jądra, harmonogramowaniem I/O pamięci masowej i konfiguracją sieci — co bezpośrednio wpływa na gęstość kontenerów i wydajność.
Lista kontrolna utwardzania produkcyjnego
Przed uruchomieniem Docker w środowisku produkcyjnym zajmij się następującymi kwestiami:
Konfiguracja demona (`/etc/docker/daemon.json`):
“`json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2",
"userns-remap": "default",
"live-restore": true,
"no-new-privileges": true
}
“`
- `log-opts` z `max-size` i `max-file`: Bez rotacji logów pliki logów JSON Docker zapełnią dysk. Jest to jedna z najczęstszych przyczyn nieoczekiwanych awarii serwerów na hostach ze skonteneryzowanymi aplikacjami.
- `userns-remap: "default"`: Włącza remapowanie przestrzeni nazw użytkowników, dzięki czemu root kontenera (UID 0) mapuje się na nieuprzywilejowany UID na hoście.
- `live-restore: true`: Pozwala kontenerom działać, gdy demon Docker ulega awarii lub jest restartowany podczas aktualizacji — kluczowe dla konserwacji bez przestojów.
- `no-new-privileges: true`: Zapobiega uzyskiwaniu przez procesy kontenerów dodatkowych uprawnień przez binaria `setuid` lub `setgid`.
Kwestie sieciowe i dotyczące zapory sieciowej:
Docker bezpośrednio manipuluje `iptables` i domyślnie omija reguły `ufw`. Kontener z opublikowanym portem (`-p 8080:80`) będzie dostępny z internetu nawet jeśli `ufw deny 8080` jest ustawiony. Aby wymusić reguły `ufw` nad manipulacją `iptables` przez Docker, dodaj `"iptables": false` do `daemon.json` i zarządzaj routingiem ręcznie, lub użyj `–network host` Docker z jawnymi regułami `ufw`.
W przypadku projektów wymagających terminacji HTTPS, połącz swoją skonteneryzowaną aplikację z odpowiednio skonfigurowanym odwrotnym proxy (Nginx lub Traefik) i ważnym certyfikatem. SSL Certificates są warunkiem wstępnym dla każdej produkcyjnej usługi webowej działającej za skonteneryzowanym stosem.
Jeśli Twoje obciążenie obejmuje wnioskowanie uczenia maszynowego, serwowanie modeli lub przetwarzanie danych z akceleracją GPU wewnątrz kontenerów, NVIDIA Container Toolkit integruje się bezpośrednio z Docker Engine. GPU Hosting zapewnia niezbędny sprzęt dla tych obciążeń.
Dla zespołów zarządzających wieloma projektami z webowym zarządzaniem kontenerami, VPS with cPanel oferuje zarządzane środowisko panelu sterowania, które może uzupełniać wdrożenia oparte na Docker dla prostszych stosów aplikacji.
Kluczowe wnioski techniczne i macierz decyzyjna
Kiedy używać Docker na VPS a na serwerze dedykowanym:
- Używaj VPS do środowisk deweloperskich, stagingu i produkcyjnych obciążeń o niskim i średnim ruchu, gdzie gęstość kontenerów wynosi 10–50 kontenerów.
- Używaj serwera dedykowanego, gdy gęstość kontenerów przekracza 50 instancji, gdy potrzebujesz przewidywalnej wydajności I/O (bez efektu hałaśliwego sąsiada) lub gdy dostrajanie parametrów jądra (`sysctl`) jest wymagane dla Twojego obciążenia.
Lista kontrolna operacyjna przed uruchomieniem produkcyjnym:
- Skonfiguruj rotację logów w `daemon.json` (`max-size`, `max-file`)
- Włącz `live-restore`, aby przetrwać restarty demona bez przestojów kontenerów
- Używaj nazwanych wolumenów, a nie montowań bind, dla danych usług stanowych
- Przypinaj wersje obrazów we wszystkich plikach `compose.yml` — nigdy nie używaj `latest` w produkcji
- Włącz `userns-remap` lub uruchom rootless Docker na hostach wielodostępnych
- Sprawdź reguły `iptables` po instalacji Docker, aby potwierdzić, że polityka zapory sieciowej nie jest omijana
- Ustaw `restart: unless-stopped` dla wszystkich długo działających usług
- Uruchamiaj `docker system prune` w zaplanowanym zadaniu cron, aby zapobiec wyczerpaniu dysku
- Używaj niestandardowych sieci mostkowych do całej komunikacji między kontenerami — nigdy nie polegaj na domyślnym moście do wykrywania usług
FAQ
Czy Docker na Ubuntu używa domyślnie `systemd` czy `cgroupfs` jako sterownika cgroup?
Od Docker Engine 20.10 domyślnym sterownikiem cgroup w systemach opartych na `systemd` (w tym wszystkich nowoczesnych wydaniach Ubuntu LTS) jest `systemd`. Jest to zgodne z wymaganiami Kubernetes i pozwala uniknąć niestabilności spowodowanej jednoczesnym działaniem dwóch menedżerów cgroup. Możesz to zweryfikować za pomocą `docker info | grep -i cgroup`.
Jaka jest różnica między `docker compose down` a `docker compose stop`?
`docker compose stop` zatrzymuje działające kontenery, ale zachowuje je wraz z powiązanymi sieciami. `docker compose down` zatrzymuje kontenery, a następnie usuwa je wraz z sieciami utworzonymi przez Compose. Dodanie `–volumes` do `down` usuwa również nazwane wolumeny zdefiniowane w pliku Compose — używaj tej flagi ostrożnie w produkcji, ponieważ trwale usuwa dane trwałe.
Dlaczego Docker omija reguły zapory sieciowej `ufw` na Ubuntu?
Docker wstawia własne reguły `iptables` w łańcuchach `DOCKER` i `DOCKER-USER`, które są oceniane przed regułami łańcucha `INPUT` `ufw`. Oznacza to, że port opublikowany za pomocą `-p` jest dostępny z internetu niezależnie od polityki `ufw`. Właściwym rozwiązaniem jest bezpośrednie dodawanie reguł do łańcucha `DOCKER-USER` lub powiązanie opublikowanych portów z konkretnym interfejsem (np. `-p 127.0.0.1:8080:80`), gdy dostęp zewnętrzny nie jest wymagany.
Jak ograniczyć CPU i pamięć, którą może zużywać kontener Docker?
Użyj flag ograniczenia zasobów w czasie wykonywania: `docker run –memory="512m" –cpus="1.5" my-image`. W Compose ustaw je pod kluczem `deploy.resources` (Compose V2) lub kluczami najwyższego poziomu `mem_limit` i `cpus`. Bez limitów pojedynczy niekontrolowany kontener może wyczerpać zasoby hosta i zatrzymać wszystkie inne kontenery na tym samym hoście.
Czy mogę uruchomić Docker wewnątrz kontenera Docker (Docker-in-Docker)?
Tak, ale jest to zdecydowanie odradzane do użytku produkcyjnego. Powszechnym wzorcem dla potoków CI jest montowanie gniazda Docker hosta (`-v /var/run/docker.sock:/var/run/docker.sock`) do kontenera CI, co daje kontenerowi pełną kontrolę nad demonem Docker hosta — co stanowi znaczące ryzyko bezpieczeństwa. Bezpieczniejszą alternatywą jest użycie flagi `–allow security.insecure` BuildKit lub dedykowanych narzędzi takich jak Kaniko lub Buildah, które budują obrazy OCI bez potrzeby demona Docker.
