#Qué problema estamos resolviendo
Tienes un programa que funciona en tu ordenador. Al moverlo a un servidor faltan bibliotecas, cambia la versión de Python o un archivo estaba en una ruta que solo existe en tu equipo. Puedes documentar cada instalación, pero necesitas que esa descripción se convierta en un entorno repetible.
Docker empaqueta los archivos y la configuración de arranque de una aplicación en una imagen. Un contenedor es una ejecución de esa imagen con sus propios procesos, red y zona de escritura. Si mantienes iguales imagen, configuración y datos de entrada, reduces las diferencias entre ordenadores. Todavía importan la arquitectura del procesador, el sistema anfitrión y los servicios externos: el contenedor no convierte una aplicación en independiente del mundo.
Este curso asume Python básico y terminal. Introduce redes, permisos y bases de datos cuando aparecen. Se trabaja con contenedores Linux y una terminal Bash —Linux, macOS o WSL—. Los ejemplos locales publican servicios en 127.0.0.1; más adelante aprenderás a publicarlos en un servidor.
#Cuatro piezas que no conviene mezclar
| Pieza | Qué contiene o hace | Qué ocurre si la eliminas |
|---|---|---|
| Imagen | Archivos y configuración de arranque, construidos por capas | Pierdes esa copia local; un registro puede conservar otra |
| Contenedor | Una instancia, sus procesos y su capa de escritura | Desaparece su escritura interna; los volúmenes tienen otro ciclo de vida |
| Motor de Docker | Crea y administra contenedores, redes e imágenes | Los programas dejan de estar supervisados por ese motor |
| Registro | Almacena y distribuye imágenes; Docker Hub es un ejemplo | No cambia los contenedores ya creados, pero afecta a futuras descargas |
La imagen es una plantilla compartida. La escritura y el estado de cada ejecución no se incorporan automáticamente a esa plantilla.
El cliente docker de tu terminal habla con el motor. El motor puede estar en tu máquina o en una remota. Un contexto guarda a qué motor se conectará el cliente: antes de borrar o recrear recursos, verifica dónde estás trabajando.
docker version
docker compose version
docker context show
El primer comando debe mostrar Client y Server. Si muestra solo el cliente y un error de conexión, la instalación del ejecutable no basta: el motor debe estar arrancado y tu usuario necesita acceso. Compose es el complemento que coordinará varios servicios. La instalación oficial distingue Docker Desktop de Docker Engine en Linux; sigue la opción de tu sistema.
#¿Es una máquina virtual?
En Linux, los contenedores comparten el kernel, el componente del sistema operativo que gestiona procesos, memoria y dispositivos. Docker pide al kernel vistas separadas de procesos y red, y límites de recursos. Una máquina virtual, en cambio, ejecuta su propio kernel encima de un hipervisor.
Docker Desktop puede proporcionar una máquina Linux virtual para ejecutar estos contenedores en macOS o Windows. La separación sigue existiendo: host físico → entorno Linux → contenedores. Por eso no debes buscar directamente un volumen de Desktop en una ruta Linux de tu Mac.
Dos consecuencias prácticas: una imagen Linux no ejecuta mágicamente programas exclusivos de Windows; y un contenedor no debe tratarse como una caja invulnerable para ejecutar cualquier código. Verás sus permisos en Seguridad y configuración.
#Primer recorrido: servir una página
Nginx es un servidor HTTP. HTTP es el protocolo que usa el navegador para pedir una página y recibir una respuesta. Su imagen oficial incluye una página de bienvenida: así comprobamos Docker sin escribir una aplicación a la vez.
docker run -d --name primera-web \
-p 127.0.0.1:8080:80 nginx:stable-alpine
docker ps
run crea y arranca un contenedor; descarga la imagen si no está disponible localmente. -d deja el proceso en segundo plano. --name permite referirse a él sin copiar su identificador. nginx:stable-alpine indica imagen y etiqueta, el nombre de una variante en el registro. alpine identifica una base Linux pequeña; no necesitas conocer sus paquetes para este ejemplo.
Un puerto es un número mediante el que un programa recibe conexiones en una máquina. -p 127.0.0.1:8080:80 publica el puerto 80 del contenedor en el 8080 de tu máquina, accesible desde tu propio ordenador. No hace falta que ambos números coincidan.
Abre http://127.0.0.1:8080 o ejecuta:
curl -i http://127.0.0.1:8080
curl es un cliente HTTP de terminal; -i muestra las cabeceras además del cuerpo. Espera un estado 200 OK y el HTML de bienvenida. No es suficiente que docker ps diga Up: esa información acredita que vive el proceso, mientras que esta petición prueba el camino de red y la respuesta del servidor.
Si aparece port is already allocated, otro proceso usa el 8080. Cambia solo el puerto del host, por ejemplo 127.0.0.1:8081:80, y visita el 8081. Si aparece un conflicto de nombre, consulta docker ps -a: ya existe primera-web, incluso si está parado.
#Observar sin convertir el contenedor en una mascota
docker logs --tail 20 primera-web
docker inspect primera-web --format '{{.State.Status}}'
docker exec primera-web nginx -v
logs muestra lo que los procesos escriben en sus salidas estándar. inspect muestra metadatos y estado; --format selecciona un campo usando la sintaxis de plantillas de Docker. exec ejecuta un proceso adicional dentro de un contenedor que ya está en marcha. Aquí pregunta por la versión de Nginx.
Puedes abrir un intérprete con docker exec -it primera-web sh. -i mantiene entrada estándar y -t asigna una terminal; sh es un intérprete de órdenes presente en esta imagen. No todas las imágenes incluyen bash, ni siquiera un shell. Sale con exit; no se detiene Nginx porque el shell era un proceso adicional.
Usa exec para observar y diagnosticar. Si instalas paquetes o corriges código manualmente dentro de un contenedor, el siguiente reemplazo perderá ese cambio. Una corrección reproducible se hace en los archivos fuente y en la imagen.
#Detener, arrancar y reemplazar son operaciones distintas
docker stop primera-web
docker ps -a
docker start primera-web
stop solicita al proceso que termine. El contenedor queda registrado en estado Exited; su capa de escritura sigue ahí. start ejecuta otra vez ese mismo contenedor, con la imagen y configuración con las que se creó. No descarga una nueva versión de la imagen.
docker stop primera-web
docker rm primera-web
docker run -d --name primera-web \
-p 127.0.0.1:8080:80 nginx:stable-alpine
Aquí sí hay una nueva instancia. Una actualización de aplicación sigue esta idea: construir o descargar una imagen, crear una nueva ejecución y comprobarla. No requiere entrar a editar archivos en la instancia anterior.
| Intención | Operación | Pregunta que responde |
|---|---|---|
| Descargar una imagen | docker pull nginx:stable-alpine |
¿Tengo los archivos de esa etiqueta? |
| Crear y ejecutar | docker run … |
¿Cómo arranca una instancia nueva? |
| Reanudar la misma instancia | docker start primera-web |
¿Qué pasa al arrancarla con la misma configuración? |
| Ver todo, incluso parado | docker ps -a |
¿Existe aunque no esté corriendo? |
| Eliminar una instancia parada | docker rm primera-web |
¿Puedo descartar su escritura interna? |
Una tarea corta puede terminar correctamente: docker run --rm python:3.13-slim python -c 'print(2 + 3)' muestra 5 y sale. --rm elimina automáticamente ese contenedor al acabar. Que un contenedor no aparezca en docker ps no demuestra un error: un servidor debe seguir activo, un cálculo puede haber acabado.
#Una etiqueta no es una versión inmutable
nginx:stable-alpine es una elección cómoda para explorar. El editor puede moverla a nuevos archivos. Tampoco una etiqueta miapp:1.0 es inmutable por obligación; depende de las reglas del registro. Un digest como sha256:… identifica un contenido exacto. Más adelante fijarás los despliegues al digest probado y actualizarás deliberadamente.
Docker descarga una imagen compatible con la plataforma cuando existe. amd64 y arm64 son arquitecturas distintas; una construcción en un portátil ARM puede necesitar otra plataforma para un servidor x86. No se arregla cambiando el nombre de la etiqueta: se construye para el destino o se publica una imagen multiplataforma.
#Prueba de comprensión
Imagina que modificas un archivo dentro de primera-web, haces stop y start, y después eliminas el contenedor y creas otro. ¿Cuándo desaparece el cambio?
Ver el razonamiento
Al parar no se borra la capa de escritura; al arrancar esa instancia la conservas. Al eliminarla sí desaparece. La nueva instancia parte de los archivos de la imagen, que no modificaste. Si quieres distribuir el cambio, necesitas construir otra imagen; si era un dato generado por usuarios, necesitas almacenamiento persistente. Son dos problemas distintos.
Para terminar el laboratorio, docker stop primera-web y docker rm primera-web eliminan solamente su contenedor. No uses una limpieza global para quitar un ejemplo: puedes tener otros proyectos en el mismo motor.
#Referencias para profundizar
- Conceptos de contenedor e imagen: qué ejecuta Docker y qué aporta el aislamiento.
- Referencia de
docker run: opciones de ejecución y publicación. - Contextos de Docker: comprobar y seleccionar el motor de destino.