Docker en profundidad: quΓ© es, por quΓ© los contenedores importan y su arquitectura
Docker en profundidad: quΓ© es, por quΓ© los contenedores importan y su arquitectura
[!tip] Docker en una frase Docker es una plataforma para crear, distribuir y ejecutar aplicaciones dentro de contenedores ligeros: paquetes autΓ³nomos que incluyen todo lo que necesita un software para correr β cΓ³digo, runtime, herramientas del sistema, bibliotecas y configuraciones β garantizando que siempre funcione igual, sin importar dΓ³nde se ejecute.
ΒΏQuΓ© son los contenedores?
Los contenedores son una tecnologΓa de virtualizaciΓ³n a nivel de sistema operativo. A diferencia de las mΓ‘quinas virtuales tradicionales que emulan hardware completo y ejecutan un sistema operativo entero por cada instancia, los contenedores comparten el kernel del sistema operativo host pero ejecutan procesos aislados.
La analogΓa de los contenedores de envΓo
Antes de Docker, entregar software era como enviar mercancΓa sin estandarizar: cada empresa tenΓa cajas de tamaΓ±o diferente, mΓ©todos de apilamiento diferentes y reglas propias. Los contenedores de envΓo estandarizados (inventados en 1956 por Malcom McLean) resolvieron este problema:
Antes de los contenedores (cada app era diferente):
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
β App "X" β β App "Y" β β App "Z" β
β LibrerΓa A v1.2 β β LibrerΓa B v3.0 β β LibrerΓa C v0.9 β
β Runtime Java 8 β β Runtime Node 12 β β Runtime Python 3.7β
β Config especΓficoβ β Config especΓficoβ β Config especΓficoβ
β SO especΓfico β β SO especΓfico β β SO especΓfico β
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
β Cada uno necesita un servidor
DespuΓ©s de los contenedores (todos estandarizados):
βββββββββββββββ βββββββββββββββ βββββββββββββββ
β Container β β Container β β Container β
β "App X" β β "App Y" β β "App Z" β
β (estΓ‘ndar) β β (estΓ‘ndar) β β (estΓ‘ndar) β
βββββββββββββββ βββββββββββββββ βββββββββββββββ
β β β
ββββββββββββββββββΌβββββββββββββββββ
βΌ
βββββββββββββββββββ
β Contenedor de β
β envΓo ΓΊnico β
β (Docker) β
βββββββββββββββββββ
βΌ
Se puede mover a cualquier servidor
que tenga Docker instalado
Lo que un contenedor incluye
ββββββββββββββββββββββββββββββββββββββββββββ
β Imagen de Docker (Contenedor) β
β β
β ββββββββββββββββββββββββββββββββββββββ β
β β Tu aplicaciΓ³n (cΓ³digo fuente) β β
β ββββββββββββββββββββββββββββββββββββββ€ β
β β Runtime (Node, Python, Java...) β β
β ββββββββββββββββββββββββββββββββββββββ€ β
β β Dependencias (npm, pip, maven...) β β
β ββββββββββββββββββββββββββββββββββββββ€ β
β β Bibliotecas del sistema (libc...) β β
β ββββββββββββββββββββββββββββββββββββββ€ β
β β Configuraciones β β
β ββββββββββββββββββββββββββββββββββββββ€ β
β β Variables de entorno β β
β ββββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββ
ΒΏPor quΓ© los contenedores cambiaron la industria?
El problema: "En mi mΓ‘quina funciona"
Antes de Docker, este era uno de los problemas mΓ‘s comunes en desarrollo de software:
Desarrollador: "En mi mΓ‘quina funciona perfectamente"
β Linux con Node 18, base de datos local,
configuraciones en /etc/
Tester: "AquΓ no funciona, da error de mΓ³dulo faltante"
β Su mΓ‘quina tiene Node 16, diferente SO,
diferentes dependencias del sistema
ProducciΓ³n: "Β‘ERROR EN PRODUCCIΓN!"
β El servidor de producciΓ³n tiene una versiΓ³n
distinta de todas las bibliotecas
Este problema se llama "incompatibilidad de entornos", y costaba a las empresas billones de dΓ³lares en productividad perdida.
La soluciΓ³n: contenedores = entornos reproducibles
Contenedor creado en desarrollo β Se envΓa a testing β Se ejecuta en producciΓ³n
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
MISMO ENTORNOS SIEMPRE
Los tres pilares de la revoluciΓ³n Docker
| Problema anterior | SoluciΓ³n con Docker | Impacto |
|---|---|---|
| Incompatibilidad de entornos | Contenedores con todo incluido | "Funciona en cualquier parte" |
| Servidores sobrecargados | MΓΊltiples contenedores en un solo servidor | ReducciΓ³n de 5-10x en infraestructura |
| Despliegues lentos y riesgosos | ImΓ‘genes versionadas, despliegue en segundos | Despliegues mΓΊltiples veces al dΓa |
Docker: historia rΓ‘pida
| AΓ±o | Evento |
|---|---|
| 2008 | Docker Inc. (entonces dotCloud) es fundada por Solomon Hykes |
| 2013 | Docker 0.1 lanzado como proyecto open source |
| 2014 | Docker 1.0 β primer lanzamiento estable |
| 2015 | Docker Swarm (orquestaciΓ³n nativa), Docker Compose |
| 2016 | Google, Microsoft y otros forman el OCI (Open Container Initiative) |
| 2017 | Kubernetes gana como estΓ‘ndar de orquestaciΓ³n |
| 2020 | Docker Desktop cambia licencia (empresas grandes pagan) |
| 2021+ | Podman, Buildah, Kaniko ganan popularidad como alternativas |
[!note] Docker no es el ΓΊnico Docker popularizΓ³ los contenedores, pero no los inventΓ³. TecnologΓas anteriores como LXC (Linux Containers) ya existΓan. Docker mejorΓ³ la experiencia de usuario, el ecosistema de registros y la herramienta
docker CLIque todos conocemos.
Arquitectura de Docker
Docker se basa en una arquitectura cliente-servidor. Esta es la clave para entender cΓ³mo funciona:
Docker Architecture
ββββββββββββββββ
βββββββββββββββ ββββββββββββββββββββββββββββββββββββββββ
β Docker CLI ββββββΆβ Docker Daemon β
β (docker) β β (dockerd) β
β β β β
β docker run β β βββββββββββ ββββββββββββββββββββ β
β docker build β β β Images β β Container Engine β β
β docker ps β β β (cache) β β (runc) β β
β docker exec β β βββββββββββ ββββββββββββββββββββ β
β β β β
β docker push β β βββββββββββββββββββββββββββββββββββ β
β docker pull β β β Containers (procesos aislados) β β
β β β βββββββββββββββββββββββββββββββββββ β
βββββββββββββββ ββββββββββββββββββββββββββββββββββββββββ
β
βΌ
Sistema Operativo Host
(Kernel Linux, cgroups,
namespaces, overlay fs)
Los componentes principales
1. Docker CLI (el cliente)
Es la herramienta que usas desde la terminal. Todo lo que escribes con el prefijo docker va aquΓ:
docker run nginx # Iniciar un contenedor
docker build -t mi-app . # Construir una imagen
docker ps # Listar contenedores
docker images # Listar imΓ‘genes
docker-compose up # Levantar aplicaciones multi-containerΒΏQuΓ© hace internamente?
- Parsea tu comando
- Lo convierte en una solicitud API (HTTP/Unix socket)
- La envΓa al Docker Daemon
- Muestra la respuesta en la terminal
# Los comandos CLI se comunican con el daemon asΓ:
docker CLI ββββ HTTP API / Unix Socket βββββΆ Docker Daemon (dockerd)
# En Linux: /var/run/docker.sock
# En Windows/Mac: Docker Desktop expone un socket Unix virtualizado2. Docker Daemon (dockerd)
Es el cerebro de Docker. Se ejecuta como un servicio en segundo plano y es responsable de:
| Responsabilidad | DescripciΓ³n |
|---|---|
| Construir imΓ‘genes | Procesa el Dockerfile y crea capas |
| Ejecutar contenedores | Crea y gestiona contenedores a partir de imΓ‘genes |
| Redes | Configura redes bridge, overlay, etc. |
| VolΓΊmenes | Gestiona almacenamiento persistente |
| ComunicaciΓ³n | Escucha solicitudes de la CLI y de otros Docker daemons |
| OrquestaciΓ³n | Si usas Docker Swarm, gestiona el cluster |
# Verificar que el daemon estΓ‘ corriendo
sudo systemctl status docker
# β docker.service - Docker Application Container Engine
# Active: active (running) since Lun 2024-01-15 10:30:00 UTC
# Verificar la versiΓ³n del daemon
docker info
# Client:
# Version: 25.0.3
# Context: default
# Server:
# Engine:
# Version: 25.0.3
# Architecture: x86_64
# Operating System: Ubuntu 22.04.3 LTS
# CPUs: 8
# Total Memory: 15.6GiB3. Registros de Docker (Docker Registries)
Un registro es un almacΓ©n de imΓ‘genes Docker. El mΓ‘s conocido es Docker Hub (hub.docker.com), pero puedes usar cualquier registro:
Registros de Docker populares:
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
β Docker Hub β β GitHub GHCR β β Google GCR β
β hub.docker.com β β ghcr.io β β gcr.io β
β - MΓ‘s grande β β - Integrado con β β - Nativo de GCP β
β - PΓΊblico/priv. β β repos β β - IAM integrado β
β - Comunidades β β - Acceso con GH β β - Cloud NATI β
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
β AWS ECR β β GitLab Registry β β Registry propio β β Quay.io β
β amazonaws.com β β registry.gitlab β β (Harbor, β β - OCI comp. β
β - Nativo de AWS β β - GitLab CI/CD β β Docker Reg.) β β - CNCF project β
β - IAM β β integrado β β - Open source β β β
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
4. ImΓ‘genes Docker
Una imagen es una plantilla de solo lectura que contiene todo lo necesario para ejecutar una aplicaciΓ³n. Piensa en ella como la plantilla para crear contenedores:
RelaciΓ³n Imagen β Contenedor:
Imagen Contenedores
(solo lectura) ββββββ (ejecutables, mΓΊltiples)
ββββββββββββββ βββββββββββββββββββββββ
Plantilla de cocina Platos servidos a clientes
(receta, ingredientes) (cada uno puede modificarse)
nginx:latest ββββΆ Contenedor1 (nginx) β puerto 80
nginx:latest ββββΆ Contenedor2 (nginx) β puerto 81
nginx:latest ββββΆ Contenedor3 (nginx) β puerto 82
mi-app:v1.2 ββββΆ Contenedor4 (mi-app)
postgres:16 ββββΆ Contenedor5 (postgres)
5. Contenedores
Un contenedor es una instancia ejecutable de una imagen. Es donde tu aplicaciΓ³n realmente corre:
Ciclo de vida de un contenedor:
βββββββββββββββββββββββββββββ
ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ
β creado ββββββΆβ ejecut. ββββββΆβ detenidoββββββΆβ elimin. β β elimin. β
β created β β running β β stopped β β removed β β exited β
ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ
β β β β
β docker create β docker start β docker stop β docker rm
β β β β
Estado: Estado: Estado: Estado:
No corre Corre No corre, Borrado
nada datos existe en completamente
persisten disco
ΒΏCΓ³mo funciona Docker internamente?
Docker no usa mΓ‘quinas virtuales. Usa funciones nativas de Linux para crear el aislamiento. Esta es la magia:
Namespaces: aislamiento de procesos
Linux tiene namespaces que permiten que grupos de procesos se vean a sΓ mismos como si fueran los ΓΊnicos en el sistema:
Namespaces que usa Docker:
βββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β Namespace β ΒΏQuΓ© aΓsla? β
βββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββ€
β PID β Procesos (cada contenedor ve solo β
β β sus procesos) β
β Network β Interfaces de red, puertos, routes β
β Mount β Sistema de archivos β
β UTS β Nombre de host y dominio β
β IPC β ComunicaciΓ³n entre procesos (semΓ‘foros) β
β User β Mapeo de usuarios (UID/GID) β
βββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββ
Ejemplo: Namespace PID
En el host:
PID 1 β Init (systemd)
PID 100 β docker container A
PID 200 β docker container B
PID 300 β docker container C
Dentro del container A:
PID 1 β Tu proceso principal (ej. nginx)
PID 2 β nginx worker process
(PID 100 del host NO se ve desde dentro del container)
Dentro del container B:
PID 1 β Tu proceso principal (ej. postgres)
(PID 100 y 200 del host NO se ven desde dentro del container)
cgroups: lΓmite de recursos
Los control groups (cgroups) permiten limitar, contar y aislar el uso de recursos (CPU, memoria, disco, red):
cgroups en acciΓ³n:
βββββββββββββββββββββββββββββββββββββββββββββββ
β Host Server: 16 GB RAM, 8 CPU Cores β
β β
β cgroup docker β
β βββ container-db (limitado a: β
β β 4 GB RAM, 2 CPU cores) β
β βββ container-web (limitado a: β
β β 2 GB RAM, 1 CPU core) β
β βββ container-worker (limitado a: β
β 2 GB RAM, 1 CPU core) β
β β
β Total asignado: 8 GB, 4 cores β
β Restante: 8 GB, 4 cores β para otros usos β
βββββββββββββββββββββββββββββββββββββββββββββββ
Overlay2: sistema de archivos en capas
Docker usa overlay2 como su driver de almacenamiento por defecto. Las imΓ‘genes se construyen en capas de solo lectura y los contenedores aΓ±aden una capa de escritura:
Estructura de capas de una imagen:
Imagen: node:20-alpine
ββββββββββββββββββββββββ β Capa superior (solo lectura)
β Capa: node bin β (ΓΊltimo comando del Dockerfile)
ββββββββββββββββββββββββ€
β Capa: npm + yarn β
ββββββββββββββββββββββββ€
β Capa: Python β
ββββββββββββββββββββββββ€
β Capa: Alpine base β β Capa inferior
β (alpine:3.19) β (~5 MB, sistema base mΓnimo)
ββββββββββββββββββββββββ
Contenedor creado a partir de esta imagen:
ββββββββββββββββββββββββ β Capa de escritura (rw) β solo existe en este contenedor
β Contenedor rw β
ββββββββββββββββββββββββ€ β Capas de solo lectura (compartidas con otros contenedores)
β Capa: node bin β
ββββββββββββββββββββββββ€
β Capa: npm + yarn β
ββββββββββββββββββββββββ€
β Capa: Python β
ββββββββββββββββββββββββ€
β Capa: Alpine base β
ββββββββββββββββββββββββ
β‘ Ventaja de capas: Si dos contenedores usan node:20-alpine, las 4 capas
de solo lectura se comparten en disco. Solo la capa de escritura es
ΓΊnica por contenedor.
runc: el motor de contenedores
Por debajo, Docker usa runc (del runtime de Docker) para crear y gestionar contenedores. runc sigue el OCI (Open Container Initiative):
Flujo completo de un "docker run":
1. docker CLI envΓa "docker run nginx" a dockerd
2. dockerd busca la imagen "nginx" localmente
3. Si no estΓ‘, dockerd la descarga de Docker Hub
4. dockerd le dice a runc: "crea un contenedor con esta imagen"
5. runc:
a. Crea un nuevo namespace PID
b. Crea un nuevo namespace Network
c. Configura cgroups (lΓmites de recursos)
d. Monta el sistema de archivos overlay
e. Ejecuta el proceso principal (CMD del Dockerfile)
6. El contenedor estΓ‘ corriendo β
Docker vs MΓ‘quinas Virtuales
Esta es la comparaciΓ³n mΓ‘s importante para entender por quΓ© Docker es diferente:
MΓQUINAS VIRTUALES (VM) vs CONTENEDORES (Docker)
ββββββββββββββββββββββ¬βββββββββββββββββββββββ¬βββββββββββββββββββββββ
β CaracterΓstica β MΓ‘quina Virtual β Contenedor Docker β
ββββββββββββββββββββββΌβββββββββββββββββββββββΌβββββββββββββββββββββββ€
β QuΓ© virtualiza β Hardware completo β Sistema operativo β
β Guest OS β SΓ (SO completo) β No (comparte host) β
β TamaΓ±o β GBs (5-40 GB) β MBs (10-500 MB) β
β Inicio β Minutos β Milisegundos β
β Overhead β Alto (Hipervisor) β Muy bajo β
β Aislamiento β Fuerte (SO diferente)β Bueno (mismo SO) β
β ImΓ‘genes β ISOs de SO β Capas de imagen β
β Rendimiento β Ligera penalizaciΓ³n β Nativo casi 1:1 β
β Ejemplo β VirtualBox, KVM, β Docker, Podman β
β β VMware β β
ββββββββββββββββββββββ΄βββββββββββββββββββββββ΄βββββββββββββββββββββββ
Diagrama comparativo
MΓQUINA VIRTUAL:
βββββββββββββββββββββββββββββββββββββββββββ Host OS (Linux)
β βββββββββββββββββββββββββββββββββββββ β
β β Hypervisor (KVM/VMware) β β
β β ββββββββββββββββββββββββββββββββββ β
β β β Guest OS (Ubuntu) ββ β
β β β βββββββββββββββββββββββββββ ββ β
β β β β Node.js + App β ββ β
β β β βββββββββββββββββββββββββββ ββ β
β β ββββββββββββββββββββββββββββββββββ β
β βββββββββββββββββββββββββββββββββββββ β
β βββββββββββββββββββββββββββββββββββββ β
β β Hypervisor (KVM/VMware) β β
β β ββββββββββββββββββββββββββββββββββ β
β β β Guest OS (Windows) ββ β
β β β βββββββββββββββββββββββββββ ββ β
β β β β .NET + App β ββ β
β β β βββββββββββββββββββββββββββ ββ β
β β ββββββββββββββββββββββββββββββββββ β
β βββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββ
β β
4 GB RAM 4 GB RAM
2 cores 2 cores
Inicio: 2 min Inicio: 2 min
CONTENEDOR (Docker):
βββββββββββββββββββββββββββββββββββββββββββ Host OS (Linux)
β Kernel Linux (compartido) β
β βββββββββββββββββββββββββββββββββββββ β
β β Container 1 (node:20) β β
β β Node.js + App β β
β β ~150 MB RAM β β
β β Inicio: 0.5 seg β β
β βββββββββββββββββββββββββββββββββββββ β
β βββββββββββββββββββββββββββββββββββββ β
β β Container 2 (postgres:16) β β
β β PostgreSQL β β
β β ~50 MB RAM β β
β β Inicio: 0.3 seg β β
β βββββββββββββββββββββββββββββββββββββ β
β βββββββββββββββββββββββββββββββββββββ β
β β Container 3 (nginx:latest) β β
β β Nginx β β
β β ~10 MB RAM β β
β β Inicio: 0.2 seg β β
β βββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββ
β
~215 MB total
Inicio: < 1 seg total
Comandos esenciales de Docker
GestiΓ³n de contenedores
# Descargar una imagen
docker pull nginx:latest
# Ejecutar un contenedor en segundo plano (-d = detached)
docker run -d --nombre web-server -p 8080:80 nginx:latest
# Listar contenedores en ejecuciΓ³n
docker ps
# Listar TODOS los contenedores (incluidos los detenidos)
docker ps -a
# Ver logs de un contenedor
docker logs web-server
# Ver logs en tiempo real (follow mode)
docker logs -f web-server
# Entrar a un contenedor en ejecuciΓ³n
docker exec -it web-server sh
# Detener un contenedor
docker stop web-server
# Iniciar un contenedor detenido
docker start web-server
# Eliminar un contenedor
docker rm web-server
# Eliminar un contenedor y sus volΓΊmenes
docker rm -v web-serverGestiΓ³n de imΓ‘genes
# Listar imΓ‘genes locales
docker images
# Construir una imagen desde un Dockerfile
docker build -t mi-app:1.0 .
# Etiqueta una imagen con una versiΓ³n
docker tag mi-app:1.0 mi-app:latest
# Eliminar una imagen
docker rmi mi-app:1.0
# Limpiar imΓ‘genes no usadas
docker image prune
# Limpiar TODO lo no usado (imΓ‘genes, contenedores, volΓΊmenes)
docker system prune -aGestiΓ³n de redes
# Listar redes
docker network ls
# Crear una red personalizada
docker network create mi-red
# Conectar un contenedor a una red
docker network connect mi-red web-server
# Ver informaciΓ³n de una red
docker network inspect mi-redGestiΓ³n de volΓΊmenes
# Listar volΓΊmenes
docker volume ls
# Crear un volumen
docker volume create mi-volumen
# Montar un volumen en un contenedor
docker run -d -v mi-volumen:/data nginx:latest
# Mount directo de carpeta (bind mount)
docker run -d -v $(pwd)/datos:/data nginx:latestConceptos clave para dominar Docker
ImΓ‘genes vs Contenedores
ββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β Imagen β Contenedor β
ββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββ€
β Plantilla estΓ‘ticaβ Instancia en ejecuciΓ³n β
β Solo lectura β Lectura/escritura (capa extra) β
β En disco β En memoria (RAM) β
β Nombre:tag β Nombre ΓΊnico + ID β
β Ejemplo β Ejemplo β
β node:20-alpine β "confused_swanson" (node:20-alpine) β
β nginx:latest β "jolly_brown" (nginx:latest) β
ββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββ
Puertos: mapeo de puertos
Docker expone puertos usando el flag -p:
# Sintaxis: -p [host-puerto]:[contenedor-puerto]
docker run -d -p 8080:80 nginx:latest
# β β
# β βββ Puertopuerto interno del contenedor (nginx escucha en 80)
# βββ Puerto en tu mΓ‘quina (accesible en http://localhost:8080)Variables de entorno
# Pasar variables de entorno a un contenedor
docker run -d \
--name mi-app \
-e DATABASE_HOST=postgres \
-e DATABASE_PORT=5432 \
-e DATABASE_NAME=mibase \
-e DATABASE_USER=usuario \
-e DATABASE_PASSWORD=secreto123 \
mi-app:latest
# Dentro de la app, se accede como variables normales:
# Python: os.environ['DATABASE_HOST']
# Node: process.env.DATABASE_HOST
# Java: System.getenv("DATABASE_HOST")Health checks
Docker puede verificar si un contenedor estΓ‘ funcionando:
docker run -d \
--name mi-app \
--health-cmd="curl -f http://localhost:3000/health || exit 1" \
--health-interval=30s \
--health-timeout=10s \
--health-retries=3 \
mi-app:latest
# Ver estado de health
docker inspect --format='{{.State.Health.Status}}' mi-app
# healthcheck β healthy | unhealthy | startingDocker: buenas prΓ‘cticas iniciales
1. Usa imΓ‘genes oficiales
# β
Buena: imΓ‘genes oficiales verificadas
docker pull nginx:latest
docker pull node:20-alpine
docker pull postgres:16
# β Mala: imΓ‘genes de usuarios no verificados
docker pull someuser/nginx2. Nunca ejecutes como root dentro del contenedor
# β Malo
FROM node:20-alpine
RUN npm install
CMD ["node", "server.js"]
# β
Bueno: crear un usuario no root
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
CMD ["node", "server.js"]3. Usa .dockerignore
# .dockerignore
node_modules
.git
*.md
.env
dist/
.next/4. Usa versiones especΓficas (no solo latest)
# β Malo: "latest" puede cambiar sin avisar
docker pull node:latest
# β
Bueno: versiΓ³n especΓfica, reproducible
docker pull node:20.11.0-alpine
# En Dockerfile:
# β FROM node:latest
# β
FROM node:20.11.0-alpineErrores comunes de principiantes
| Error | Causa | SoluciΓ³n |
|---|---|---|
permission denied while trying to connect to the Docker daemon socket |
Usuario no estΓ‘ en el grupo docker |
sudo usermod -aG docker $USER y reiniciar sesiΓ³n |
port is already allocated |
Otro proceso usando ese puerto | lsof -i :8080 para encontrar quΓ© lo usa |
image does not have a sha256digest |
Imagen corrupta o descarga incompleta | docker system prune y docker pull de nuevo |
| Contenedor se detiene inmediatamente | El CMD/CMD no estΓ‘ corriendo o falla | docker logs nombre-contenedor para ver el error |
| No se puede acceder a la app por puerto 80 | Puerto no mapeado | Agregar -p 80:80 al docker run |
| Datos se pierden al borrar contenedor | No se usaron volΓΊmenes | Usar docker volume o bind mounts |
Resumen
- Docker es una plataforma de contenedores que permite empaquetar aplicaciones con todo su entorno
- Los contenedores comparten el kernel del host pero estΓ‘n aislados (namespaces, cgroups)
- Arquitectura: CLI (cliente) β Daemon (dockerd) β runc (motor) β Kernel Linux
- ImΓ‘genes son plantillas de solo lectura; contenedores son instancias ejecutables
- Registros (Docker Hub, GHCR, GCR, ECR) almacenan imΓ‘genes para distribuir
- Docker vs VM: contenedores son mΓ‘s ligeros, mΓ‘s rΓ‘pidos, y comparten el SO
- Capas de imagen: se comparten entre contenedores, ahorrando espacio en disco
- Buenas prΓ‘cticas: imΓ‘genes oficiales, versiΓ³n fija, .dockerignore, no root, health checks
[!quote] La clave Docker no es magia: es una forma estandarizada de empaquetar software usando funciones nativas de Linux. Una imagen es la receta (Dockerfile), el contenedor es el plato cocinado, y un registro es el restaurante que sirve el plato a otros. Entender esta metΓ‘fora te ayuda a dominar Docker: imagenes = plantillas, contenedores = instancias, registros = distribuciΓ³n.
ConexiΓ³n con el resto de la wiki
| Concepto tocado | ArtΓculo en profundidad |
|---|---|
| Redes (puertos, TCP/IP) | [[01-redes-internet/01-que-es-internet]] |
| Servidores y procesos | [[01-redes-internet/014-servidores-procesos]] |
| Firewalls | [[01-redes-internet/017-firewalls-proxies-loadbalancers]] |
| VPS | [[01-redes-internet/020-vps]] (donde correrΓ‘s tus contenedores) |