3.5.-Virtualización, nube y contenedores
3.5. Virtualización, nube y contenedores¶
Idea principal
La virtualización permite preparar un entorno aislado para ejecutar una aplicación web. Una máquina virtual, una instancia cloud y un contenedor ofrecen niveles de aislamiento y responsabilidades diferentes; elegir uno no consiste en usar la tecnología más compleja, sino la que se pueda instalar, configurar y mantener con garantías.
Después de identificar los requisitos de la aplicación, hay que decidir dónde se ejecutarán sus componentes. En este tema se comparan las máquinas virtuales, los servicios de nube y los contenedores, y se prepara un entorno pequeño para la aplicación de ejemplo. La comparación se centra en la instalación y la configuración básica; la publicación de Nginx y Tomcat se aborda en los puntos posteriores.
Este contenido desarrolla exclusivamente el criterio siguiente de la normativa del módulo:
| Código | Descripción |
|---|---|
| RA1 | Implanta arquitecturas web analizando y aplicando criterios de funcionalidad. |
| CE e | Se ha realizado la instalación y configuración básica de tecnologías de virtualización de servidores en la nube y en contenedores. |
Qué deberías saber al terminar
Al acabar este tema deberías poder:
- distinguir una máquina virtual, una instancia cloud y un contenedor;
- preparar una plataforma de contenedores con red, puertos y almacenamiento básicos;
- justificar la opción elegida y registrar sus límites, costes y riesgos.
Mapa del tema
Seguiremos esta secuencia:
- virtualización y niveles de aislamiento;
- nube como infraestructura bajo demanda;
- imágenes y ciclo de vida de los contenedores;
- redes, persistencia y configuración declarativa;
- preparación de un entorno reproducible para una aplicación web.
1. Virtualizar un servidor¶
En un servidor físico se pueden ejecutar varios entornos aislados mediante un hipervisor. Un hipervisor es el programa que crea y administra máquinas virtuales: reparte entre ellas CPU, memoria, almacenamiento y dispositivos de red. Cada máquina virtual incluye su propio sistema operativo, por lo que el aislamiento es amplio, aunque también aumenta el consumo de recursos y el tiempo de arranque.
Hay dos formas habituales de encontrar un hipervisor:
- Tipo 1 o nativo: se ejecuta directamente sobre el hardware. Es habitual en centros de datos y proveedores cloud.
- Tipo 2 o alojado: se ejecuta como una aplicación sobre un sistema operativo, como ocurre en muchos laboratorios con VirtualBox o VMware Workstation.
La diferencia es útil para interpretar la responsabilidad de cada entorno: en una máquina virtual local administras el hipervisor y el sistema invitado; en una instancia cloud el proveedor suele administrar la capa física y el hipervisor, mientras tú administras lo que el servicio contratado te entrega.
Un contenedor utiliza el núcleo del sistema anfitrión, es decir, del sistema operativo de la máquina que lo ejecuta. Aísla procesos, sistema de archivos, red y límites de recursos. Arranca normalmente más rápido y ocupa menos que una máquina virtual, pero no es un sistema operativo completo y no debe tratarse como una frontera de seguridad absoluta.
Virtualización
Es la creación de una representación aislada de recursos informáticos para ejecutar sistemas o procesos independientes sobre una infraestructura física compartida.
| Tecnología | Qué aísla principalmente | Ventaja | Coste o límite |
|---|---|---|---|
| Máquina virtual | Un sistema operativo completo | Aislamiento amplio y flexibilidad | Más consumo y administración |
| Contenedor | Procesos y sus dependencias | Arranque rápido y empaquetado reproducible | Comparte el núcleo del anfitrión |
| Servidor físico | La máquina completa | Rendimiento y control directos | Menor aprovechamiento y elasticidad |
La elección también depende del riesgo. Un contenedor es apropiado para empaquetar una aplicación y sus dependencias, pero la organización debe aplicar actualizaciones, límites, separación de redes y un usuario no privilegiado. No es correcto afirmar que un contenedor sea una máquina virtual pequeña: comparte el núcleo del anfitrión y una vulnerabilidad del motor o una configuración privilegiada puede afectar al aislamiento.
flowchart TB
P["Servidor físico o instancia cloud"] --> H["Hipervisor opcional"]
H --> VM["Máquina virtual<br/>sistema operativo propio"]
P --> OS["Sistema operativo anfitrión"]
OS --> E["Motor de contenedores"]
E --> C["Contenedor<br/>proceso aislado"]
El esquema representa dos recorridos posibles, no una obligación de utilizar todos los niveles. En un laboratorio puede existir una máquina virtual sobre el ordenador; en Docker Desktop el motor puede ejecutarse dentro de una máquina virtual gestionada por la herramienta sin que la administres directamente.
Cómo elegir
Utiliza una máquina virtual cuando necesites otro núcleo o sistema operativo, un aislamiento más amplio o una aplicación heredada difícil de adaptar. Utiliza contenedores cuando quieras empaquetar servicios reproducibles que compartan el núcleo del anfitrión y necesites arrancarlos y recrearlos con rapidez.
2. Nube e infraestructura bajo demanda¶
Una plataforma cloud o nube permite solicitar recursos de un proveedor sin comprar ni mantener físicamente todo el hardware. En un modelo IaaS (Infrastructure as a Service, infraestructura como servicio) se recibe una máquina virtual o instancia con CPU, memoria, disco y red configurables. El equipo sigue siendo responsable del sistema operativo, los servicios instalados, las cuentas, los datos y buena parte de la seguridad.
La nube es un modelo de provisión y administración de recursos, no una tecnología concreta. Puede apoyarse en máquinas virtuales, contenedores o servicios gestionados. Por eso conviene separar estas ideas:
| Modelo | Qué entrega el proveedor | Qué suele administrar el equipo |
|---|---|---|
| IaaS | Infraestructura virtual, red y almacenamiento | Sistema operativo, runtime, servicios, datos y configuración |
| PaaS | Plataforma preparada para ejecutar la aplicación | Código, configuración, datos y permisos de la aplicación |
| CaaS | Plataforma gestionada para ejecutar contenedores | Imágenes, servicios, redes lógicas y datos, según el proveedor |
Los límites exactos dependen del contrato. Un servicio gestionado reduce tareas de administración, pero no elimina la necesidad de proteger credenciales, revisar permisos, controlar datos y comprobar copias de seguridad.
Antes de crear una instancia hay que fijar al menos:
- región o ubicación de los recursos;
- imagen y arquitectura del sistema operativo;
- tamaño de CPU, memoria y disco;
- claves o mecanismo de acceso administrativo;
- reglas de firewall y puertos publicados;
- presupuesto, cuotas y política de apagado;
- copias de seguridad y procedimiento de eliminación.
Una cuenta educativa también puede generar costes
Una instancia, una dirección IP pública, un disco o una transferencia pueden tener un coste aunque la aplicación sea pequeña. Utiliza cuentas de aula y límites definidos, no publiques credenciales y elimina los recursos cuando termine la actividad.
Antes de crear recursos en la nube, comprueba también:
- la región y la arquitectura disponibles, especialmente si las imágenes solo
soportan
amd64oarm64; - las cuotas de CPU, memoria, disco, IP y transferencia;
- quién puede acceder a la instancia y con qué mecanismo de autenticación;
- el procedimiento para apagar, eliminar y recuperar los datos;
- qué controles de seguridad aplica el proveedor y cuáles debe aplicar el equipo.
Una instancia cloud puede alojar Docker y, dentro de él, los servicios de la aplicación. En ese caso hay dos niveles que documentar: la instancia y los contenedores. Un fallo o una regla de firewall del primer nivel puede impedir que funcionen los servicios del segundo.
3. Imágenes, contenedores y ciclo de vida¶
En Docker, una imagen es una plantilla formada por capas. Decimos que es inmutable porque no se modifica mientras un contenedor está funcionando; si necesitamos cambiarla, construimos una nueva versión. Un contenedor es una ejecución de esa imagen con su propia configuración. La imagen no debería guardar los datos de trabajo: los datos que deben sobrevivir a la recreación del contenedor se colocan en un volumen o en un servicio externo.
El Docker Engine sigue un modelo cliente-servidor. La orden docker es el
cliente; el demonio dockerd recibe la petición a través de la API y gestiona
imágenes, contenedores, redes y volúmenes. Un registro, como Docker Hub, sirve
para distribuir imágenes, pero no ejecuta por sí mismo los contenedores.
| Recurso | Función | Ejemplo en una aplicación web |
|---|---|---|
| Imagen | Empaquetar sistema, runtime y aplicación | nginx:1.27-alpine |
| Contenedor | Ejecutar una imagen con límites y variables | Servidor web en ejecución |
| Red | Permitir la comunicación entre servicios | Red interna entre Nginx y Tomcat |
| Puerto publicado | Conectar el host con un puerto del contenedor | 8080:80 para una prueba local |
| Volumen | Conservar datos fuera del ciclo del contenedor | Datos de MariaDB |
Una etiqueta identifica una variante, por ejemplo nginx:1.27-alpine, pero no
garantiza por sí sola que el contenido sea inmutable: una etiqueta puede
actualizarse en el registro. Para una entrega reproducible conviene registrar
la etiqueta probada y el digest (sha256:...) que devolvió el registro.
Un recorrido mínimo para comprobar la plataforma puede ser:
docker version
docker info --format '{{.Architecture}}'
docker pull nginx:1.27-alpine
docker run --name web-prueba --detach --publish 127.0.0.1:8080:80 nginx:1.27-alpine
docker ps
curl --fail http://127.0.0.1:8080
docker logs --tail 20 web-prueba
docker inspect web-prueba
docker stop web-prueba
docker rm web-prueba
--publish 127.0.0.1:8080:80 publica el puerto 80 del contenedor en el 8080
del host, pero solo para conexiones desde el propio equipo. Omitir la dirección
(8080:80) suele hacer que Docker escuche en todas las interfaces del host.
Ninguna de las dos formas convierte automáticamente un puerto interno en un
servicio seguro para Internet: el firewall y la configuración del proveedor
siguen siendo relevantes.
docker info permite comprobar la arquitectura del motor. Si el host es
arm64 y la imagen solo ofrece amd64, Docker puede necesitar emulación y el
resultado puede ser más lento o incompatible. Esta comprobación evita atribuir
al código un fallo causado por la plataforma.
El grupo docker no es un usuario sin privilegios
Añadir una cuenta al grupo docker evita escribir sudo, pero normalmente
permite controlar el motor con privilegios equivalentes a root. En equipos
compartidos valora Docker rootless, limita el acceso al socket y aplica la
política de cuentas del centro o de la empresa.
4. Redes y persistencia: dos decisiones distintas¶
La red decide quién puede comunicarse con cada servicio; el almacenamiento decide qué datos sobreviven cuando se recrea un contenedor. No son intercambiables.
| Mecanismo | Uso habitual | Riesgo o límite principal |
|---|---|---|
| Volumen nombrado | Datos de bases de datos y ficheros de la aplicación | Sigue ligado al host si no se copia o replica |
| Bind mount | Código y configuración durante el desarrollo | Depende de rutas y permisos del host |
tmpfs |
Datos temporales que no deben persistir en disco | Se pierde al detener el contenedor |
También hay que distinguir tres conceptos de red:
- Puerto interno: donde escucha el proceso dentro de su contenedor.
- Puerto publicado (
ports): conecta el host con el contenedor y puede hacerlo accesible desde fuera. - Puerto declarado (
expose): documenta o facilita el acceso interno, pero no sustituye a un firewall ni publica por sí solo el servicio.
En una red definida por la persona administradora o por Compose, los servicios
se localizan por nombre DNS. Por ejemplo, la aplicación debe conectarse a
db:3306, no a una IP que pueda cambiar al recrear el contenedor. Una base de
datos solo debe tener ports si existe un motivo concreto para acceder a ella
desde el host; para la comunicación interna basta con compartir la red.
5. Preparar un entorno con Docker Compose¶
Cuando hay varios servicios, un archivo Compose permite describir la red, las imágenes, los puertos y los volúmenes en un documento versionable. Este ejemplo prepara un servidor web y una base de datos sin publicar el puerto interno de MariaDB:
services:
web:
image: nginx:1.27-alpine
ports:
- "127.0.0.1:8080:80"
networks:
- aplicacion
db:
image: mariadb:11.4
env_file:
- .env
volumes:
- datos-db:/var/lib/mysql
networks:
- aplicacion
healthcheck:
test: ["CMD-SHELL", "healthcheck.sh --connect --innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
networks:
aplicacion:
volumes:
datos-db:
El archivo .env puede partir de una plantilla sin secretos:
MARIADB_DATABASE=catalogo
MARIADB_USER=catalogo_app
MARIADB_PASSWORD=rellenar-en-el-entorno
MARIADB_ROOT_PASSWORD=rellenar-en-el-entorno
El .env real no debe subirse al repositorio. En producción se preferirá un
gestor de secretos o el mecanismo equivalente del proveedor. La configuración
del ejemplo es para un entorno de aprendizaje: no convierte automáticamente
una instalación local en un despliegue preparado para Internet.
docker compose config --quiet
docker compose up --detach
docker compose ps
docker compose logs --tail 50 db
docker compose down
docker compose config permite revisar el resultado que Compose ha interpretado
antes de crear recursos. down elimina los contenedores y la red del proyecto,
pero no elimina los volúmenes salvo que se indique expresamente. healthcheck
indica si MariaDB está preparada para aceptar conexiones; depends_on, por sí
solo, solo ordena el arranque y no garantiza esa disponibilidad.
6. Aplicación al entorno de la unidad¶
Para la aplicación de ejemplo se puede utilizar una instancia cloud pequeña o un equipo local con Docker. En ambos casos se documentan las mismas evidencias:
-
Preparar el anfitrión: anota sistema operativo, arquitectura, versión de Docker o hipervisor y recursos asignados.
-
Aislar la red: crea una red para los servicios y publica solo el puerto que utilizará el cliente durante la práctica.
-
Separar datos: asigna un volumen a la base de datos y define quién puede leer o escribir en él.
-
Comprobar el ciclo de vida: crea, detén, recrea y elimina un contenedor de prueba para comprobar qué recursos son efímeros y cuáles persisten.
-
Registrar la decisión: indica por qué el entorno elegido satisface los requisitos y qué cambiaría para pasar a producción.
flowchart LR
F["Servidor físico o proveedor cloud"] --> V["Hipervisor o sistema anfitrión"]
V --> VM["Máquina virtual opcional"]
VM --> D["Motor de contenedores"]
D --> N["Red interna"]
N --> W["Servidor web"]
N --> A["Servidor de aplicaciones"]
A --> DB["Base de datos"]
DB --> Vol["Volumen persistente"]
Este esquema no afirma que siempre sean necesarios todos los niveles. En local puede no existir una máquina virtual; en un proveedor cloud la instancia puede ser la capa visible; y en una plataforma gestionada el equipo puede no administrar el hipervisor. Lo importante es identificar qué nivel se configura y quién es responsable de él.
7. Buenas prácticas¶
- Fijar versiones: utiliza etiquetas y versiones compatibles, y registra la imagen exacta que se ha probado.
- Publicar poco: deja las bases de datos en redes internas y expón solo los puertos necesarios para el acceso de las personas usuarias.
- Separar código y datos: recrea los contenedores sin perder la información que deba conservarse.
- No guardar secretos en Git: utiliza variables protegidas, secretos del
proveedor o un gestor específico;
.env.examplesolo debe contener nombres y valores ficticios. - Comprobar la disponibilidad real: añade healthchecks y reintentos de la
aplicación; que un contenedor esté en estado
Upno demuestra que el servicio acepte peticiones. - Probar la recuperación: la persistencia de un volumen no es una copia de seguridad. Realiza una copia y una restauración de prueba.
- Aplicar mínimo privilegio: evita
--privileged, usa usuarios sin privilegios y monta configuraciones en modo solo lectura cuando sea posible. - Aplicar límites: asigna CPU y memoria razonables para evitar que un servicio monopolice el anfitrión.
- Controlar el coste cloud: usa cuotas, alertas y una política de apagado o eliminación al terminar la actividad.
8. Errores frecuentes¶
| Error frecuente | Por qué ocurre | Cómo evitarlo |
|---|---|---|
| Confundir contenedor con máquina virtual | Se supone que ambos incluyen un sistema operativo completo | Explica qué comparte cada uno con el anfitrión |
| Publicar todos los puertos | Se utiliza -p por comodidad |
Publica solo la entrada necesaria y revisa el firewall |
| Guardar datos dentro del contenedor | Se olvida que el contenedor se puede recrear | Usa volúmenes o almacenamiento externo |
Usar latest sin registrar la versión |
La etiqueta puede cambiar con el tiempo | Fija una versión probada y documenta la actualización |
| Dejar una instancia cloud encendida | Se olvida el ciclo de vida del recurso | Configura alertas y elimina los recursos de la práctica |
Confundir Up con servicio disponible |
El proceso existe, pero aún no acepta conexiones | Usa un healthcheck, logs y una prueba funcional |
Ejecutar down --volumes sin comprobarlo |
Se confunde eliminar contenedores con eliminar datos | Haz copia y utiliza down sin --volumes durante las pruebas normales |
| Depender de la IP de un contenedor | La IP puede cambiar al recrearlo | Usa el nombre del servicio en la red interna |
Tratar la pertenencia al grupo docker como inocua |
Se confunde comodidad con menor privilegio | Protege el socket y valora rootless o una cuenta controlada |
| Considerar el volumen como una copia | Persistencia y backup se mezclan | Programa y prueba una restauración independiente |
9. Resumen¶
En este tema has aprendido que:
- una máquina virtual y un contenedor ofrecen niveles de aislamiento y costes diferentes;
- una instancia cloud añade responsabilidades de red, acceso, coste y seguridad que también deben documentarse;
- imágenes, contenedores, redes, puertos y volúmenes cumplen funciones distintas;
- Docker Compose permite describir un entorno de varios servicios de forma reproducible.
Idea clave
Preparar la infraestructura no es solo instalar Docker o crear una máquina: es definir el aislamiento, los recursos, las redes, la persistencia y las responsabilidades que permiten ejecutar la aplicación con seguridad.
10. Para seguir practicando¶
- Prepara un entorno con la introducción a Docker de la unidad publicada.
- Compara volúmenes, redes y variables en la práctica de WordPress con Docker Compose.
- Observa una arquitectura de dos capas en la práctica de Tomcat detrás de Nginx, fijándote en qué servicio se publica y cuál queda en la red interna.
- Revisa los conceptos de instalación de Docker en la guía de Raúl Profesor.
Bibliografía y fuentes¶
- Normativa del módulo 0614.
- Docker: Get started.
- Docker Compose.
- Docker: volúmenes.
- Docker: redes.
- Docker: modo rootless.
- Docker Compose: orden de arranque y healthchecks.
- Introducción al despliegue de aplicaciones.
- AWS: tipos de computación en la nube.