README · by ansango
← Volver al libro

Explorando Docker

Comandos para explorar el entorno: docker version, docker system info, descargar imágenes, docker container inspect, exec, retornar resultados, logging, stats, health checks, system events, cAdvisor y Prometheus

~4 min de lectura
Resumen

Esta nota cubre los comandos para explorar y operar el entorno Docker: versión, info del server, descargar imágenes, inspeccionar containers, entrar a un container corriendo con exec, retornar resultados de comandos, logging, estadísticas, health checks, system events, y monitoring con cAdvisor y Prometheus. Es la navaja suiza del día a día con Docker.

Versión e info del server

docker version

$ docker version
Client:
 Cloud integration: v1.0.24
 Version:           20.10.17
 API version:       1.41
 Go version:        go1.17.11
 OS/Arch:           darwin/amd64
Server: Docker Desktop 4.10.1 (82475)
 Engine:
  Version:          20.10.17
  API version:      1.41 (minimum version 1.12)
 containerd:
  Version:          1.6.6
 runc:
  Version:          1.1.2
Útil para troubleshooting

Cuando hay errores de “API version mismatch” entre client y server, este comando te dice exactamente qué versión tiene cada pieza. Client y server pueden tener versiones diferentes, lo cual es útil en desarrollo.

docker system info

Información completa del server: storage driver, kernel, OS, plugins, número de containers, runtime por defecto.

$ docker system info
Server:
 Containers: 11
 Images: 6
 Server Version: 20.10.17
 Storage Driver: overlay2
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Kernel Version: 5.10.104-linuxkit
 Operating System: Docker Desktop
 Architecture: x86_64
Storage root

Por defecto, /var/lib/docker. Si necesitas cambiarlo, edita la config del daemon (daemon.json) con --data-root al arrancar manualmente.

Descargar imágenes

docker image pull ubuntu:latest
# latest: Pulling from library/ubuntu
# 405f018f9d1d: Pull complete
# Digest: sha256:b6b83d3c331794420340093eb706a6f152d9c1fa51b262d9bf34594887c2c7ac
# Status: Downloaded newer image for ubuntu:latest

Solo descarga los layers que cambiaron desde la última vez. No se actualiza automáticamente; tienes que hacer pull explícitamente. latest es flotante — en producción usa tags con versión específica o el SHA-256.

# Pull por SHA (la forma más precisa de garantizar la versión exacta)
docker image pull ubuntu@sha256:b6b83d3c331794420340093eb706a6f152d9c1fa51b262d9bf34594887c2c7ac
SHAs no se pueden truncar

A diferencia de los container IDs (que se pueden abreviar), los SHA-256 de imágenes deben ir completos.

Inspeccionar un container

docker container inspect da output JSON verboso con toda la metadata:

$ docker container inspect <container_id>
[{
    "Id": "3c4f916619a5dfc420396d823b42e8bd30a2f94ab5b0f42f052357a68a67309b",
    "Created": "2022-07-17T17:26:53.611762541Z",
    "Config": {
        "Hostname": "3c4f916619a5",
        "Env": ["PATH=/usr/local/sbin:..."],
        "Cmd": ["/bin/bash"],
        ...
    }
}]

El campo Env es especialmente útil en debugging: te dice exactamente qué env vars recibió el container en creación.

IDs cortos y largos

3c4f916619a5 es el ID corto (12 caracteres del hash). Docker lo acepta igual que el ID completo de 64 caracteres. Acostúmbrate a usar el corto para los comandos diarios.

Entrar a un container corriendo

docker container exec corre un proceso nuevo dentro de un container ya corriendo:

# Inicia un container en background
docker container run -d --rm ubuntu:22.04 sleep 600

# Entra con shell
docker container exec -it <container_id> /bin/bash
# root@<container_id>:/#

docker container exec es la forma Docker-native de hacer “SSH al container”. En producción es un antipatrón entrar a un container en producción (similar a SSH a servers), pero para debugging activo es invaluable.

exec en background

Puedes correr docker container exec -d, pero pierdes la repeatability del image deployment. Si dependes de procesos lanzados con exec, otros devs necesitan saber qué pasar. Mejor rebuild-ear la imagen para lanzar ambos procesos de forma reproducible.

Para señalizar a un proceso (rotar logs, recargar config), usa docker container kill -s <SIGNAL> con el nombre del Unix signal.

Retornar resultados

Los containers son ligeros y rápidos de crear y destruir. Eso los hace ideales para correr comandos one-off y obtener resultados:

# Ejecuta /bin/false y captura el exit code
docker container run --rm ubuntu:22.04 /bin/false
echo $?
# 1

# Ejecuta /bin/true
docker container run --rm ubuntu:22.04 /bin/true
echo $?
# 0

# Ejecuta cat /etc/passwd en el container
docker container run --rm ubuntu:22.04 /bin/cat /etc/passwd
# root:x:0:0:root:/root:/bin/bash
# ...

# Pipe al local wc (NO al wc del container)
docker container run --rm ubuntu:22.04 /bin/cat /etc/passwd | wc -l
# 19
Los pipes son locales

El pipe | wc -l corre en tu local, no en el container. Si quieres que el pipe se ejecute dentro del container, usa bash -c "...":

Logging

Docker captura todo lo que el container escribe a stdout y stderr y lo streamea a un backend de logging configurable.

docker container logs

$ docker container run --rm -d --name nginx-test nginx:latest
$ docker container logs nginx-test
# …output del container…

# Tail en vivo
$ docker container logs -f nginx-test

# Solo las últimas N líneas o desde un timestamp
docker container logs --tail 100 nginx-test
docker container logs --since 5m nginx-test

Los logs se almacenan por defecto en /var/lib/docker/containers/<id>/<id>-json.log en formato JSON:

{"log":"2022/07/31 16:36:05 [notice] 1#1: nginx/1.23.1\n",
 "stream":"stderr","time":"2022-07-31T16:36:05.189234362Z"}
Habilita log rotation

El default no tiene log rotation. En producción, configura --log-opt max-size y --log-opt max-file en daemon.json:

Sin rotación, el archivo de log crece sin límite.

Backends alternativos

Para setups más serios, hay drivers de logging que envían a sistemas centralizados:

DriverDestino
syslogSyslog remoto (UDP recomendado, TCP puede bloquear)
fluentdFluentd / Fluent Bit
awslogsCloudWatch Logs (AWS)
gcplogsCloud Logging (GCP)
splunkSplunk
journaldsystemd journal
Solo un driver a la vez

Docker soporta un driver de logging simultáneamente. Si cambias de json-file a syslog, pierdes docker container logs. Algunos plug-ins terceros mantienen copia local para soportar ambos; verifica antes de cambiar.

UDP > TCP/TLS para syslog remoto

Con TCP, si el server remoto está caído, Docker bloquea el arranque del container. UDP es non-blocking; pierdes garantía de entrega pero ganas reliability.

Monitoring

Container statistics

$ docker container run --rm -d --name stress \
    spkane/train-os:latest \
    stress -v --cpu 2 --io 1 --vm 2 --vm-bytes 128M --timeout 60s

$ docker container stats stress
CONTAINER ID NAME   CPU %   MEM USAGE/LIMIT   MEM % NET I/O   BLOCK I/O PIDS
1a9f52f0855f stress 476.50% 36.09MiB/7.773GiB 0.45% 1.05kB/0B 0B/0B     6

CPU% es relativo a un core. 476% significa 4.76 cores. --no-stream da un snapshot único.

API stats endpoint (vía curl)

$ curl -s -XGET --unix-socket /var/run/docker.sock \
    http://docker/containers/stress/stats | head -n 1 | jq
{
  "pids_stats": { "current": 6, "limit": ... },
  "cpu_stats": { "cpu_usage": { "total_usage": 101883204000, ... } },
  "memory_stats": { "usage": 183717888, "limit": 8346021888 },
  "networks": { "eth0": { "rx_bytes": 1046, ... } }
  ...
}

Container health checks

HEALTHCHECK CMD ["docker-healthcheck"]

docker container ls muestra el estado de salud:

$ docker container ls
# STATUS: Up 1 second (health: starting) 27017/tcp
# STATUS: Up 32 seconds (healthy) 27017/tcp
# STATUS: Up 9 minutes (unhealthy) 27017/tcp

Flags útiles:

Health checks en todas tus imágenes

Es una de las mejores inversiones de tiempo que puedes hacer. Estandariza cómo se chequea la salud y úsalo en todos los containers.

docker system events

Stream de eventos del lifecycle de containers:

$ docker system events
# En otro terminal:
$ docker container run --rm --name sleeper debian:latest sleep 5
# En el primero verás:
# container create d6... (image=debian:latest, name=sleeper)
# container start  d6...
# container die    d6... (exitCode=0)
# container destroy d6...

Útil para monitoring y para detectar eventos de seguridad (container exec_create puede señalar que alguien entró a un container).

Eventos importantes a monitorizar:

cAdvisor (Google)

Container Advisor de Google: corre como container, expone métricas detalladas de containers y del host en una web UI y REST API.

$ docker container run \
  --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:ro \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --publish=8080:8080 \
  --detach=true \
  --name=cadvisor \
  --privileged \
  --rm \
  --device=/dev/kmsg \
  gcr.io/cadvisor/cadvisor:latest

Abre http://<docker-host>:8080/ para ver gráficos de CPU, memoria, network, I/O por container.

# API REST
curl http://<docker-host>:8080/api/v2.1/machine/

Prometheus

Docker tiene un endpoint de metrics para Prometheus (experimental, hay que activarlo en daemon.json):

{
  "experimental": true,
  "metrics-addr": "0.0.0.0:9323"
}
sudo systemctl restart docker
curl -s http://localhost:9323/metrics | head
# HELP builder_builds_failed_total Number of failed image builds
# TYPE builder_builds_failed_total counter
# builder_builds_failed_total{reason="build_canceled"} 0
# ...

Configurar Prometheus para scrapear este endpoint (/etc/prometheus/prometheus.yaml):

global:
  scrape_interval: 5s
  external_labels:
    monitor: 'stats-monitor'
scrape_configs:
  - job_name: 'DockerStats'
    static_configs:
    - targets: ['172.17.0.1:9323']

Levantar Prometheus como container:

docker container run --rm -d -p 9090:9090 \
  -v /tmp/prometheus/prometheus.yaml:/etc/prometheus.yaml \
  prom/prometheus --config.file=/etc/prometheus.yaml
dockprom para dashboards

Si quieres dashboards bonitos, échale un ojo a dockprom, que combina Prometheus + Grafana con queries preconfiguradas para Docker metrics.

Métricas en red

Cualquier servicio que expongas en red es un riesgo de seguridad. metrics-addr=0.0.0.0 lo expone a todo. En producción, considera bind a una red interna o usar autenticación.

Próximos pasos