Docker pe Ubuntu: Ghid Complet de Instalare și Utilizare
Docker este o platformă de containerizare open-source care împachetează aplicațiile și dependențele acestora în unități izolate și portabile numite containere. Spre deosebire de mașinile virtuale, containerele partajează kernelul OS al gazdei, ceea ce le face semnificativ mai ușoare, mai rapide la pornire și mai eficiente din punct de vedere al resurselor — o distincție esențială pentru oricine rulează sarcini de lucru într-un mediu de VPS Hosting unde resursele de calcul afectează direct costul și performanța.
Acest ghid acoperă întregul proces de instalare Docker pe Ubuntu 20.04, 22.04 și 24.04 LTS, inclusiv consolidarea post-instalare, fluxurile de lucru Docker Compose și tiparele de comenzi relevante pentru producție pe care majoritatea tutorialelor le omit.
Cerințe preliminare și cerințe de sistem
Înainte de a executa o singură comandă, verificați următoarele:
- Versiunea Ubuntu: 20.04 LTS (Focal), 22.04 LTS (Jammy) sau 24.04 LTS (Noble). Comanda `lsb_release -cs` utilizată în timpul configurării depozitului va detecta automat numele de cod.
- Arhitectură: `amd64`, `arm64` sau `armhf` sunt toate acceptate de depozitul oficial Docker.
- Versiunea kernelului: Docker necesită kernelul Linux 3.10 sau mai recent. Rulați `uname -r` pentru a confirma.
- Privilegii utilizator: `sudo` sau accesul root este obligatoriu pentru instalare și gestionarea daemonului.
- Spațiu pe disc: Minimum 2 GB liberi pe partiția care găzduiește `/var/lib/docker`, unde Docker stochează imagini, containere, volume și cache de build. Pe sistemele de producție, montați acest director pe o partiție sau un volum dedicat.
Pas critic pre-instalare: Dacă ați instalat anterior Docker din depozitul implicit `apt` al Ubuntu (pachetul `docker.io`), eliminați-l mai întâi pentru a evita conflictele cu pachetele oficiale Docker CE:
“`bash
sudo apt remove docker docker-engine docker.io containerd runc
“`
Pasul 1: Actualizarea pachetelor de sistem
Aduceți indexul de pachete și pachetele instalate la cele mai recente versiuni înainte de a adăuga orice depozit nou:
“`bash
sudo apt update
sudo apt upgrade -y
“`
Aceasta asigură că rezolvatorul de dependențe al `apt` funcționează pe baza metadatelor actuale ale pachetelor și că bibliotecile de bază ale sistemului nu sunt depășite — o sursă comună de erori subtile de rulare cu aplicațiile containerizate.
Pasul 2: Instalarea Docker Engine din depozitul oficial
Depozitele implicite `apt` ale Ubuntu livrează un pachet numit `docker.io`, care este întreținut de Canonical și rămâne de obicei cu câteva versiuni în urma versiunii oficiale Docker. Pentru utilizarea în producție, instalați întotdeauna din propriul depozit Docker.
2.1 Instalarea dependențelor de transport și verificare
“`bash
sudo apt install apt-transport-https ca-certificates curl software-properties-common gnupg lsb-release -y
“`
De ce `gnupg`? Începând cu Ubuntu 22.04, `gpg` nu este întotdeauna prezent implicit. Includerea sa explicită previne eșecul silențios al importului cheii GPG.
2.2 Adăugarea cheii GPG oficiale 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
“`
Pasul `chmod a+r` este frecvent omis în tutoriale, dar este necesar pe sistemele unde `apt` rulează într-un context de utilizator restricționat — fără acesta, managerul de pachete nu poate citi keyring-ul și va genera o eroare `NO_PUBKEY` în timpul `apt update`.
2.3 Adăugarea depozitului stabil 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
“`
Substituția `arch=$(dpkg –print-architecture)` este esențială pe serverele bazate pe ARM. Codificarea hardcoded a `amd64` este o greșeală frecventă care cauzează eșecuri silențioase de rezolvare a pachetelor pe instanțele ARM.
2.4 Instalarea Docker Engine, CLI și plugin-urilor
“`bash
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
“`
Detalii pachete:
| Pachet | Rol |
|---|
| — | — |
|---|
| `docker-ce` | Daemonul Docker Engine (`dockerd`) |
|---|
| `docker-ce-cli` | CLI client (comanda `docker`) |
|---|
| `containerd.io` | Runtime de containere de nivel scăzut (conform OCI) |
|---|
| `docker-buildx-plugin` | Capacități extinse de build (multi-platformă, BuildKit) |
|---|
| `docker-compose-plugin` | Compose V2 integrat ca plugin CLI Docker |
|---|
Notă despre `containerd.io`: Acesta nu este același cu pachetul `containerd` din depozitul implicit Ubuntu. `containerd.io` al Docker este o versiune specifică, testată a runtime-ului containerd. Amestecarea celor două este o sursă cunoscută de eșecuri la pornirea daemonului.
Pasul 3: Verificarea instalării
Confirmați că daemonul este activ și activat pentru a porni la boot:
“`bash
sudo systemctl status docker
sudo systemctl enable docker
“`
Verificați versiunea instalată:
“`bash
sudo docker –version
sudo docker info
“`
`docker info` este mai informativ decât `–version` singur — dezvăluie driverul de stocare utilizat (de obicei `overlay2`), driverul cgroup (`systemd` vs `cgroupfs`) și numărul de CPU-uri și memoria la care Docker poate accesa.
Rulați testul de fum canonic:
“`bash
sudo docker run hello-world
“`
O rulare reușită afișează un mesaj „Hello from Docker!” și confirmă că daemonul Docker, extragerea imaginii din Docker Hub și execuția containerului funcționează corect.
Pasul 4: Configurarea Docker pentru acces non-root
În mod implicit, socket-ul Docker (`/var/run/docker.sock`) este deținut de `root` și grupul `docker`. Orice utilizator care nu face parte din grupul `docker` trebuie să utilizeze `sudo` pentru fiecare comandă Docker.
“`bash
sudo usermod -aG docker $USER
“`
Aplicați apartenența la grup fără a vă deconecta:
“`bash
newgrp docker
“`
Verificați:
“`bash
docker run hello-world
“`
Avertisment de securitate: Apartenența la grupul `docker` este efectiv echivalentă cu `sudo` fără parolă. Un utilizator din grupul `docker` poate monta trivial sistemul de fișiere al gazdei într-un container și poate eluda toate controalele de acces la nivel de sistem de fișiere. Pe sistemele multi-tenant sau serverele partajate, luați în considerare utilizarea Docker rootless în schimb:
“`bash
dockerd-rootless-setuptool.sh install
“`
Modul rootless rulează daemonul Docker și containerele sub un spațiu de nume de utilizator neprivilegiat, reducând dramatic suprafața de atac. Este configurația recomandată pentru orice mediu în care mai mulți utilizatori partajează aceeași gazdă.
Pasul 5: Referință comenzi Docker esențiale
Gestionarea imaginilor
“`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
“`
Sfat pentru producție: Extrageți întotdeauna tag-uri versionate (ex., `nginx:1.27-alpine`) în loc de `latest` în orice flux de lucru automatizat sau de producție. Tag-ul `latest` este mutabil — poate indica o imagine diferită după un push în registry, afectând reproductibilitatea.
Ciclul de viață al containerului
“`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
“`
Inspecția resurselor și a sistemului
“`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` este una dintre cele mai importante comenzi de întreținere pentru serverele cu rulare îndelungată. Fără curățare periodică, cache-ul de build al Docker și containerele oprite pot consuma zeci de gigaocteți pe o gazdă activă de dezvoltare sau CI.
Pasul 6: Docker Compose — Orchestrarea aplicațiilor multi-container
Docker Compose V2 (`docker-compose-plugin` instalat anterior) este invocat ca `docker compose` (cu spațiu), nu ca moștenitul `docker-compose` (cu cratimă). Ambele sintaxe funcționează dacă aveți plugin-ul instalat, dar V2 este standardul actual.
6.1 Înțelegerea structurii fișierului Compose
Creați un director de proiect și un fișier `compose.yml` (numele de fișier preferat în Compose V2; `docker-compose.yml` rămâne acceptat pentru compatibilitate retroactivă):
“`bash
mkdir ~/my-web-app && cd ~/my-web-app
nano compose.yml
“`
Un exemplu realist pentru producție cu Nginx și un serviciu backend:
“`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
“`
Directive cheie Compose explicate:
- `restart: unless-stopped` — Containerul repornește automat după un crash sau repornirea sistemului, cu excepția cazului în care a fost oprit explicit de operator. Aceasta este politica corectă pentru serviciile cu rulare îndelungată; `always` va reporni chiar și containerele oprite intenționat.
- `depends_on` — Controlează ordinea de pornire, dar nu așteaptă ca serviciul să fie *pregătit* (ex., o bază de date care acceptă conexiuni). Pentru controlul pregătirii, utilizați `healthcheck` combinat cu `condition: service_healthy`.
- `volumes` cu `:ro` — Montarea fișierelor de configurare ca read-only împiedică un proces de container compromis să își modifice propria configurație.
6.2 Comenzi flux de lucru 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 Verificarea serviciului în rulare
“`bash
curl -I http://localhost:8080
“`
Un răspuns `200 OK` confirmă că Nginx servește corect. Pentru serviciile care rulează pe o instanță VPS Hosting la distanță, înlocuiți `localhost` cu adresa IP publică a serverului dvs. și asigurați-vă că portul relevant este deschis în firewall-ul dvs. (`ufw allow 8080/tcp`).
Pasul 7: Fundamente de rețea Docker
Înțelegerea modelului de rețea Docker este esențială pentru construirea aplicațiilor multi-container care comunică în siguranță.
Drivere de rețea implicite:
| Driver | Caz de utilizare |
|---|
| — | — |
|---|
| `bridge` | Implicit pentru containere standalone; spațiu de nume de rețea izolat pe gazdă |
|---|
| `host` | Containerul partajează stiva de rețea a gazdei; performanță maximă, zero izolare |
|---|
| `none` | Fără acces la rețea; util pentru procesare în lot sau sarcini de lucru sensibile la securitate |
|---|
| `overlay` | Rețea multi-gazdă pentru clusterele Docker Swarm |
|---|
| `macvlan` | Atribuie o adresă MAC containerului; apare ca dispozitiv fizic în rețea |
|---|
Crearea și utilizarea unei rețele bridge personalizate:
“`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'
“`
Rețelele bridge personalizate oferă rezoluție DNS automată între containere după numele containerului. Rețeaua implicită `bridge` nu oferă acest lucru — aceasta este o distincție critică care cauzează eșecuri de conexiune atunci când dezvoltatorii presupun că containerele din rețeaua implicită se pot accesa reciproc după nume.
Pasul 8: Date persistente cu volume Docker
Containerele sunt efemere prin design. Orice date scrise în sistemul de fișiere al unui container se pierd când containerul este eliminat. Pentru stocarea persistentă, utilizați volume sau bind mount-uri.
“`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
“`
Volume vs. bind mount-uri:
| Caracteristică | Volum denumit | Bind Mount |
|---|
| — | — | — |
|---|
| Gestionat de Docker | Da | Nu |
|---|
| Cale gazdă necesară | Nu | Da |
|---|
| Portabil între gazde | Da (cu drivere de volum) | Nu |
|---|
| Cel mai bun pentru | Date baze de date, starea aplicației | Cod de dezvoltare, fișiere de configurare |
|---|
| Mecanism de backup | `docker run –volumes-from` | Instrumente standard de sistem de fișiere |
|---|
Pasul 9: Menținerea Docker actualizat
Depozitul oficial Docker gestionează actualizările prin mecanismul standard `apt`:
“`bash
sudo apt update
sudo apt upgrade -y
“`
Pentru a actualiza doar pachetele legate de Docker fără a actualiza întregul sistem:
“`bash
sudo apt install –only-upgrade docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
“`
Verificați notele de lansare Docker înainte de actualizările majore de versiune, în special pentru modificările aduse driverului de stocare, gestionării versiunii cgroup sau versiunilor API depreciate care pot afecta fișierele `compose.yml` existente.
Docker vs. abordări alternative de containerizare
| Caracteristică | Docker Engine | Podman | LXC/LXD | containerd (standalone) |
|---|
| — | — | — | — | — |
|---|
| Arhitectură daemon | Daemon centralizat | Fără daemon | Bazat pe daemon | Bazat pe daemon |
|---|
| Suport rootless | Da (v20+) | Nativ | Limitat | Da |
|---|
| Suport Docker Compose | Nativ | Prin `podman-compose` | Nu | Nu |
|---|
| Conformitate OCI | Da | Da | Nu (format LXC) | Da |
|---|
| Integrare Kubernetes | Prin shim-ul CRI-dockerd | CRI nativ | Nu | CRI nativ |
|---|
| Suport Windows/macOS | Docker Desktop | Limitat | Nu | Nu |
|---|
| Cel mai potrivit pentru | Dezvoltare generală și producție | Axat pe securitate, rootless | Containere de sistem, VM-uri | Noduri Kubernetes |
|---|
Pentru echipele care rulează sarcini de lucru containerizate la scară pe bare metal, un mediu de Dedicated Servers vă oferă control complet asupra parametrilor kernelului, planificării I/O de stocare și configurației de rețea — toate acestea afectând direct densitatea containerelor și performanța.
Listă de verificare pentru consolidarea în producție
Înainte de a rula Docker într-un mediu de producție, abordați următoarele:
Configurarea daemonului (`/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` cu `max-size` și `max-file`: Fără rotația jurnalelor, fișierele de jurnal JSON ale Docker vor umple discul. Aceasta este una dintre cele mai frecvente cauze ale întreruperilor neașteptate ale serverului pe gazdele containerizate.
- `userns-remap: "default"`: Activează remaparea spațiului de nume de utilizator, astfel încât root-ul containerului (UID 0) se mapează la un UID neprivilegiat pe gazdă.
- `live-restore: true`: Permite containerelor să continue să ruleze dacă daemonul Docker se blochează sau este repornit în timpul unei actualizări — esențial pentru întreținerea fără timp de nefuncționare.
- `no-new-privileges: true`: Împiedică procesele containerului să obțină privilegii suplimentare prin binare `setuid` sau `setgid`.
Considerații privind rețeaua și firewall-ul:
Docker manipulează `iptables` direct și ocolește regulile `ufw` în mod implicit. Un container cu un port publicat (`-p 8080:80`) va fi accesibil de pe internet chiar dacă `ufw deny 8080` este setat. Pentru a aplica regulile `ufw` peste manipularea `iptables` a Docker, adăugați `"iptables": false` în `daemon.json` și gestionați rutarea manual, sau utilizați `–network host` al Docker cu reguli explicite `ufw`.
Pentru proiectele care necesită terminarea HTTPS, asociați aplicația containerizată cu un proxy invers configurat corespunzător (Nginx sau Traefik) și un certificat valid. SSL Certificates sunt o cerință preliminară pentru orice serviciu web de producție care rulează în spatele unui stack containerizat.
Dacă sarcina dvs. de lucru implică inferență de machine learning, servirea modelelor sau procesare de date accelerată GPU în interiorul containerelor, NVIDIA Container Toolkit se integrează direct cu Docker Engine. GPU Hosting oferă hardware-ul de bază necesar pentru aceste sarcini de lucru.
Pentru echipele care gestionează mai multe proiecte cu management de containere bazat pe web, VPS with cPanel oferă un mediu de panou de control gestionat care poate completa implementările bazate pe Docker pentru stive de aplicații mai simple.
Concluzii tehnice cheie și matrice de decizie
Când să utilizați Docker pe un VPS față de un server dedicat:
- Utilizați un VPS pentru medii de dezvoltare, staging și sarcini de lucru de producție cu trafic scăzut până la mediu, unde densitatea containerelor este de 10–50 de containere.
- Utilizați un server dedicat când densitatea containerelor depășește 50 de instanțe, când aveți nevoie de performanță I/O previzibilă (fără efect de vecin zgomotos) sau când reglarea parametrilor kernelului (`sysctl`) este necesară pentru sarcina dvs. de lucru.
Listă de verificare operațională înainte de lansare:
- Configurați rotația jurnalelor în `daemon.json` (`max-size`, `max-file`)
- Activați `live-restore` pentru a supraviețui repornirilor daemonului fără timp de nefuncționare al containerului
- Utilizați volume denumite, nu bind mount-uri, pentru datele serviciilor cu stare
- Fixați versiunile imaginilor în toate fișierele `compose.yml` — nu utilizați niciodată `latest` în producție
- Activați `userns-remap` sau rulați Docker rootless pe gazdele multi-tenant
- Auditați regulile `iptables` după instalarea Docker pentru a confirma că politica firewall-ului nu este ocolită
- Setați `restart: unless-stopped` pe toate serviciile cu rulare îndelungată
- Rulați `docker system prune` pe un job cron programat pentru a preveni epuizarea discului
- Utilizați rețele bridge personalizate pentru toată comunicarea inter-container — nu vă bazați niciodată pe bridge-ul implicit pentru descoperirea serviciilor
Întrebări frecvente
Docker pe Ubuntu utilizează `systemd` sau `cgroupfs` ca driver cgroup implicit?
Începând cu Docker Engine 20.10, driverul cgroup implicit pe sistemele bazate pe `systemd` (inclusiv toate versiunile moderne Ubuntu LTS) este `systemd`. Aceasta se aliniază cu cerințele Kubernetes și evită instabilitatea cauzată de rularea simultană a doi manageri cgroup. Puteți verifica cu `docker info | grep -i cgroup`.
Care este diferența dintre `docker compose down` și `docker compose stop`?
`docker compose stop` oprește containerele în rulare, dar le păstrează împreună cu rețelele asociate. `docker compose down` oprește containerele și apoi le elimină împreună cu rețelele create de Compose. Adăugarea `–volumes` la `down` elimină și volumele denumite definite în fișierul Compose — utilizați acest flag cu precauție în producție, deoarece șterge permanent datele persistente.
De ce Docker ocolește regulile de firewall `ufw` pe Ubuntu?
Docker inserează propriile reguli `iptables` în lanțurile `DOCKER` și `DOCKER-USER`, care sunt evaluate înaintea regulilor lanțului `ufw` al `INPUT`. Aceasta înseamnă că un port publicat cu `-p` este accesibil de pe internet indiferent de politica `ufw`. Atenuarea corectă este să adăugați reguli direct în lanțul `DOCKER-USER`, sau să legați porturile publicate la o interfață specifică (ex., `-p 127.0.0.1:8080:80`) când accesul extern nu este necesar.
Cum limitez CPU-ul și memoria pe care le poate consuma un container Docker?
Utilizați flag-uri de constrângere a resurselor la runtime: `docker run –memory="512m" –cpus="1.5" my-image`. În Compose, setați acestea sub cheia `deploy.resources` (Compose V2) sau cheile de nivel superior `mem_limit` și `cpus`. Fără limite, un singur container scăpat de sub control poate epuiza resursele gazdei și poate opri toate celelalte containere de pe aceeași gazdă.
Pot rula Docker în interiorul unui container Docker (Docker-in-Docker)?
Da, dar este puternic descurajat pentru utilizarea în producție. Modelul comun pentru pipeline-urile CI este montarea socket-ului Docker al gazdei (`-v /var/run/docker.sock:/var/run/docker.sock`) în containerul CI, ceea ce oferă containerului control complet asupra daemonului Docker al gazdei — un risc semnificativ de securitate. O alternativă mai sigură este utilizarea flag-ului `–allow security.insecure` al BuildKit sau a instrumentelor dedicate precum Kaniko sau Buildah, care construiesc imagini OCI fără a necesita un daemon Docker.
