Docker a schimbat modul in care construim, livram si rulam software. In loc de "functioneaza pe masina mea", Docker garanteaza ca aplicatia ta ruleaza la fel peste tot - pe laptopul tau, pe masina unui coleg, in CI/CD si in productie. In acest ghid, vom merge de la zero la deploy-ul unei aplicatii reale.
Ce este Docker?
Docker este o platforma care impacheteaza aplicatia ta si toate dependentele sale intr-o unitate standardizata numita container. Un container este un proces izolat si usor care partajeaza kernel-ul OS-ului gazda, dar are propriul sistem de fisiere, retea si spatiu de procese.
Containere vs Masini Virtuale
| Aspect | Containere | Masini Virtuale |
|---|---|---|
| Pornire | Secunde | Minute |
| Dimensiune | MB | GB |
| SO | Partajeaza kernel-ul gazdei | SO oaspete complet |
| Izolare | Nivel de proces | Nivel hardware |
| Performanta | Aproape nativa | Overhead de la hypervisor |
| Densitate | Sute per gazda | Zeci per gazda |
Instalarea Docker
# macOS brew install --cask docker # Ubuntu/Debian curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER # Verify installation docker --version docker run hello-world
Concepte Fundamentale
Imagini
O imagine este un sablon doar pentru citire cu instructiuni pentru crearea unui container. Gandeste-te la ea ca la un instantaneu al aplicatiei si al mediului sau.
# Pull an image from Docker Hub docker pull node:20-alpine # List local images docker images # Remove an image docker rmi node:20-alpine
Containere
Un container este o instanta in executie a unei imagini. Poti crea, porni, opri si sterge containere.
# Run a container docker run -d --name my-app -p 3000:3000 node:20-alpine # List running containers docker ps # List all containers (including stopped) docker ps -a # Stop a container docker stop my-app # Remove a container docker rm my-app # View logs docker logs my-app # Execute a command inside a running container docker exec -it my-app sh
Scrierea unui Dockerfile
Un Dockerfile este un fisier text cu instructiuni pentru construirea unei imagini. Fiecare instructiune creeaza un strat.
Dockerfile de Baza pentru o Aplicatie Node.js
# Use an official Node.js runtime as base image FROM node:20-alpine # Set working directory WORKDIR /app # Copy package files first (better caching) COPY package.json package-lock.json ./ # Install dependencies RUN npm ci --only=production # Copy application code COPY . . # Expose the port the app runs on EXPOSE 3000 # Command to run the application CMD ["node", "server.js"]
Construire si Rulare
# Build the image docker build -t my-node-app . # Run the container docker run -d -p 3000:3000 my-node-app # Visit http://localhost:3000
Build-uri Multi-Stage
Build-urile multi-stage mentin imaginile de productie mici separand mediul de build de runtime.
# Stage 1: Build FROM node:20-alpine AS builder WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . RUN npm run build # Stage 2: Production FROM node:20-alpine AS runner WORKDIR /app COPY /app/dist ./dist COPY /app/node_modules ./node_modules COPY /app/package.json ./ EXPOSE 3000 CMD ["node", "dist/server.js"]
Aceasta produce o imagine doar cu iesirea compilata si dependentele de productie - fara cod sursa, fara dependente de dezvoltare, fara instrumente de build.
Exemplu Multi-Stage pentru Next.js
FROM node:20-alpine AS deps WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci FROM node:20-alpine AS builder WORKDIR /app COPY /app/node_modules ./node_modules COPY . . RUN npm run build FROM node:20-alpine AS runner WORKDIR /app ENV NODE_ENV=production COPY /app/public ./public COPY /app/.next/standalone ./ COPY /app/.next/static ./.next/static EXPOSE 3000 CMD ["node", "server.js"]
Volume: Date Persistente
In mod implicit, datele din interiorul unui container se pierd cand containerul este eliminat. Volumele rezolva aceasta problema.
# Create a named volume docker volume create my-data # Run with a volume docker run -d -v my-data:/app/data my-app # Bind mount (map host directory to container) docker run -d -v $(pwd)/data:/app/data my-app # List volumes docker volume ls
Retea
Docker creeaza retele izolate pentru ca containerele sa comunice.
# Create a custom network docker network create my-network # Run containers on the same network docker run -d --name api --network my-network my-api docker run -d --name db --network my-network postgres:16 # Containers can reach each other by name # From "api" container: postgres://db:5432
Docker Compose
Docker Compose iti permite sa definesti si sa rulezi aplicatii cu mai multe containere cu un singur fisier YAML.
docker-compose.yml
services: api: build: ./api ports: - "3000:3000" environment: - DATABASE_URL=postgres://user:pass@db:5432/mydb depends_on: - db db: image: postgres:16-alpine environment: - POSTGRES_USER=user - POSTGRES_PASSWORD=pass - POSTGRES_DB=mydb volumes: - pgdata:/var/lib/postgresql/data ports: - "5432:5432" redis: image: redis:7-alpine ports: - "6379:6379" volumes: pgdata:
Comenzi
# Start all services docker compose up -d # View logs docker compose logs -f # Stop all services docker compose down # Rebuild and restart docker compose up -d --build # Scale a service docker compose up -d --scale api=3
.dockerignore
Ca si .gitignore, acest fisier impiedica fisierele inutile sa fie copiate in imagine.
node_modules .git .env *.md .next dist coverage
Cele Mai Bune Practici pentru Productie
1. Foloseste Imagini de Baza Mici
# Bad: 1GB+ FROM node:20 # Good: ~180MB FROM node:20-alpine
2. Nu Rula ca Root
FROM node:20-alpine RUN addgroup -S app && adduser -S app -G app USER app WORKDIR /home/app COPY . .
3. Foloseste Tag-uri de Imagine Specifice
# Bad: can change unexpectedly FROM node:latest # Good: pinned version FROM node:20.11-alpine3.19
4. Valorifica Cache-ul de Build
Ordoneaza instructiunile Dockerfile de la cele mai putin la cele mai frecvent modificate:
FROM node:20-alpine WORKDIR /app # These change rarely - cached COPY package.json package-lock.json ./ RUN npm ci --only=production # This changes often - not cached COPY . .
5. Verificari de Sanatate
HEALTHCHECK \ CMD wget -qO- http://localhost:3000/health || exit 1
6. Foloseste Variabile de Mediu
ENV NODE_ENV=production ENV PORT=3000
Fisa de Referinta pentru Comenzi Docker Comune
# Images docker build -t name:tag . # Build image docker images # List images docker rmi image_name # Remove image docker image prune # Remove unused images # Containers docker run -d -p 3000:3000 image # Run detached docker ps # List running docker stop container_name # Stop docker rm container_name # Remove docker logs -f container_name # Follow logs docker exec -it container sh # Shell into container # Compose docker compose up -d # Start services docker compose down # Stop services docker compose logs -f # Follow all logs docker compose ps # List services # Cleanup docker system prune -a # Remove everything unused
De la Docker la Kubernetes
Docker gestioneaza containere individuale. Cand trebuie sa orchestrezi sute de containere pe mai multe servere, ai nevoie de Kubernetes. Docker si Kubernetes sunt complementare:
- Docker: construieste si ruleaza containere
- Kubernetes: orchestreaza containere la scara (planificare, scalare, auto-vindecare)
Daca esti interesat de pasul urmator, consulta articolul meu despre Introducere in Kubernetes.
Concluzie
Docker este o abilitate fundamentala pentru dezvoltatorii moderni. Elimina inconsistentele de mediu, simplifica deploy-ul si este fundamentul orchestrarii containerelor cu Kubernetes. Incepe cu un Dockerfile simplu, treci la Docker Compose pentru aplicatii multi-serviciu si adopta build-uri multi-stage si cele mai bune practici de securitate pe masura ce cresti.
Cel mai bun mod de a invata Docker este sa containerizezi un proiect la care deja lucrezi. Incepe astazi.