Misma tarea, tres herramientas
Cada bloque resuelve lo mismo con Docker, Kubernetes y Terraform. Los ejemplos de Terraform usan el provider de Docker (kreuzwerker/docker) para poder probarlos en tu PC.
Cómo leer esta página
Cada bloque es una tarea, resuelta en tres columnas. No hace falta conocer las tres herramientas: leé la columna de la que estés usando y compará.
- Docker Compose
- Archivo
docker-compose.yml+ comandodocker compose. Corre contenedores en tu PC. - Kubernetes
- Manifiestos YAML + comando
kubectl. Corre contenedores en un cluster. - Terraform
- Archivos
.tf+ comandoterraform. Acá usa el provider de Docker, así cada ejemplo se puede probar en tu PC. - Bloques oscuros
- Código o comandos para copiar. Lo que está entre
< >se reemplaza. - Notas grises
- Aclaraciones o diferencias importantes de esa herramienta.
1 · Levantar una app y abrir un puerto
Un nginx accesible en localhost:8080, declarado en archivo.
services:
web:
image: nginx:1.27
ports:
- "8080:80"
apiVersion: apps/v1
kind: Deployment
metadata: { name: web }
spec:
selector: { matchLabels: { app: web } }
template:
metadata: { labels: { app: web } }
spec:
containers:
- name: web
image: nginx:1.27
---
apiVersion: v1
kind: Service
metadata: { name: web }
spec:
type: NodePort
selector: { app: web }
ports: [{ port: 80, nodePort: 30080 }]
Docker Desktop: localhost:30080. O kubectl port-forward svc/web 8080:80.
resource "docker_image" "web" {
name = "nginx:1.27"
}
resource "docker_container" "web" {
name = "web"
image = docker_image.web.image_id
ports {
internal = 80
external = 8080
}
}
2 · Aplicar cambios (y ver antes qué va a pasar)
Las tres son declarativas: describís el estado final y la herramienta calcula qué hacer.
docker compose config
docker compose up -d
config muestra el YAML final. No hay “preview” de cambios.
kubectl diff -f k8s/
kubectl apply -f k8s/
diff compara contra lo que hay en el cluster.
terraform init
terraform plan -out=tfplan
terraform apply tfplan
El plan muestra + ~ - por recurso.
3 · Ver qué está corriendo
Listado y detalle de lo que administra cada herramienta.
docker compose ps
docker ps -a
docker inspect web
kubectl get pods -o wide
kubectl get deploy,svc
kubectl describe pod <pod>
terraform state list
terraform state show docker_container.web
terraform output
Muestra lo que Terraform cree que existe; plan lo contrasta con la realidad.
4 · Ver logs y entrar al contenedor
Depurar la aplicación que está corriendo.
docker logs -f web
docker exec -it web sh
kubectl logs -f deploy/web
kubectl logs <pod> --previous
kubectl exec -it deploy/web -- sh
docker o kubectl. Para depurar a Terraform mismo:$env:TF_LOG = "DEBUG"
terraform plan
5 · Pasar configuración (variables de entorno)
Valores no secretos que cambian por entorno.
services:
api:
image: chanchito:1.0.0
environment:
- NODE_ENV=production
- LOG_LEVEL=info
apiVersion: v1
kind: ConfigMap
metadata: { name: api-config }
data:
NODE_ENV: production
LOG_LEVEL: info
# en el contenedor:
# envFrom:
# - configMapRef: { name: api-config }
variable "log_level" {
type = string
default = "info"
}
resource "docker_container" "api" {
# ...
env = ["LOG_LEVEL=${var.log_level}"]
}
Valores por entorno en dev.tfvars / prod.tfvars.
6 · Manejar un secreto (contraseña)
Que no quede en el repo ni se imprima en pantalla.
# .env (en .gitignore)
# MONGO_PASSWORD=<password>
services:
db:
image: mongo:7
environment:
- MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD}
kubectl create secret generic mongo \
--from-literal=MONGO_PASSWORD=<password>
envFrom:
- secretRef: { name: mongo }
Los Secrets son base64, no cifrados.
variable "mongo_password" {
type = string
sensitive = true
}
$env:TF_VAR_mongo_password = "<password>"
Igual queda en el .tfstate: protegé el estado.
7 · Persistir datos (volumen para Mongo)
Que los datos sobrevivan aunque el contenedor se recree.
services:
db:
image: mongo:7
volumes:
- mongo-data:/data/db
volumes:
mongo-data:
kind: PersistentVolumeClaim
apiVersion: v1
metadata: { name: mongo-data }
spec:
accessModes: [ReadWriteOnce]
resources: { requests: { storage: 1Gi } }
# en el Pod: volumes + volumeMounts
# mountPath: /data/db
resource "docker_volume" "mongo" {
name = "mongo-data"
}
resource "docker_container" "db" {
# ...
volumes {
volume_name = docker_volume.mongo.name
container_path = "/data/db"
}
}
8 · Conectar un servicio con otro
La app encuentra a la base por nombre, nunca por IP.
mongodb://user:pass@db:27017/miapp
Todos los servicios del compose comparten una red; el host es el nombre del servicio.
mongodb://user:pass@db:27017/miapp
El host es el nombre del Service (db.<namespace> desde otro namespace).
resource "docker_network" "app" {
name = "app-net"
}
# en cada contenedor:
networks_advanced {
name = docker_network.app.name
}
La red es un recurso explícito; el host es el name del contenedor.
9 · Escalar a 3 réplicas
Más copias de la misma app.
docker compose up -d --scale api=3
Sin puerto fijo en el host (tres contenedores no pueden usar el mismo).
kubectl scale deploy api --replicas=3
Mejor: replicas: 3 en el YAML y apply. El Service balancea solo.
resource "docker_container" "api" {
count = 3
name = "api-${count.index}"
image = docker_image.api.image_id
}
Terraform crea copias, pero no balancea ni recrea si se caen.
10 · Actualizar a una versión nueva
Pasar de chanchito:1.0.0 a chanchito:1.1.0.
docker build -t chanchito:1.1.0 .
# cambiar image: en el compose
docker compose up -d
Recrea el contenedor: hay un corte breve.
kubectl set image deploy/api api=chanchito:1.1.0
kubectl rollout status deploy/api
Rolling update: sin corte si hay 2+ réplicas.
resource "docker_image" "api" {
name = "chanchito:1.1.0" # antes 1.0.0
}
terraform apply # -/+ docker_container.api
11 · Volver a la versión anterior
La nueva versión falló.
# volver a image: chanchito:1.0.0
docker compose up -d
Por eso conviene taggear versiones y no usar latest.
kubectl rollout undo deploy/api
kubectl rollout history deploy/api
Guarda revisiones anteriores (un ReplicaSet por versión).
git revert HEAD
terraform plan
terraform apply
No hay “undo”: el historial es git. Volvés el código y aplicás.
12 · Borrar todo
Bajar lo que levantaste. Ojo con los datos.
docker compose down # conserva volúmenes
docker compose down -v # ⚠ borra los datos
kubectl delete -f k8s/
kubectl delete ns chanchito # ⚠ todo el namespace
terraform plan -destroy
terraform destroy
Borra todo lo que figura en el estado, volúmenes incluidos.
No encontré esa tarea. Probá con otra palabra.