Tutorial 5: Red Docker macvlan y Portainer con Docker Compose

Guía práctica basada en una Raspberry Pi 5 para inspeccionar una red Docker macvlan existente, reutilizarla con Docker Compose y verificar Portainer, con ejemplos de IP ficticias y recomendaciones de seguridad.

Con una red Docker macvlan, los contenedores pueden tener su propia dirección IP dentro de una VLAN de la red local. Así, otros equipos de esa VLAN pueden acceder a los servicios directamente por su IP, sin depender de publicar cada puerto en la dirección del servidor Docker. En esta guía veremos cómo inspeccionar una macvlan existente, reutilizarla desde Docker Compose y comprobar una instalación de Portainer.

Los pasos se basan en mi Raspberry Pi 5, pero las direcciones IP que aparecen en el artículo y el diagrama se han sustituido por valores ficticios para proteger la configuración de mi red. Adapta la subred, la puerta de enlace, la interfaz padre y las IP disponibles antes de ejecutar los comandos. Si estás preparando el servidor desde cero, consulta también la guía para preparar una Raspberry Pi para Docker Compose.

Diagrama de una red Docker macvlan de ejemplo en una Raspberry Pi 5, conectada mediante un firewall SonicWall TZ670 y un switch UniFi USW Pro 48 PoE; las IP son ficticias.
Arquitectura didáctica con SonicWall TZ670, switch UniFi USW Pro 48 PoE y direcciones IP ficticias para ilustrar una red macvlan en una VLAN de servicios.

1. Qué hace macvlan y cuándo utilizarla

El driver macvlan asigna a cada contenedor una identidad de red propia, incluida una dirección MAC y una IP de la VLAN. Es útil para servicios de un homelab que quieres tratar como equipos independientes de la LAN, por ejemplo paneles de administración, monitorización o automatización.

  • Ventaja: acceso directo a cada servicio por su propia IP.
  • Planificación necesaria: las IP estáticas deben estar reservadas y no coincidir con DHCP ni con otros dispositivos.
  • Limitación: por defecto, el host Docker no puede comunicarse directamente con sus interfaces macvlan como lo haría con una interfaz bridge normal.
  • Seguridad: tener una IP propia no protege por sí solo el servicio; aplica autenticación, actualizaciones y reglas de firewall.

2. Inspecciona la red existente antes de cambiar nada

Antes de crear una red nueva, comprueba si ya existe una macvlan que puedas reutilizar. En el servidor de este ejemplo, la red se llama vlan20_net (no docker_macvlan) y ya está en uso por varios contenedores.

docker network inspect vlan20_net

Estos son los valores ficticios utilizados en los ejemplos de esta guía; no son una configuración que debas copiar sin adaptarla:

Parámetro Valor comprobado
Nombre de la red Docker vlan20_net
Driver macvlan
Interfaz padre (parent) eth0.20
Subred 192.168.50.0/24
Puerta de enlace 192.168.50.1
Portainer 192.168.50.10
UniFi Network Application 192.168.50.11
Home Assistant 192.168.50.12
Node-RED 192.168.50.13

La interfaz eth0.20 es una subinterfaz VLAN sobre eth0. No la sustituyas por eth0 en este servidor: la opción parent debe coincidir con la interfaz que entrega el tráfico a la VLAN deseada. Puedes listar las interfaces con:

ip -br link

Importante: como vlan20_net ya funciona, no ejecutes un segundo docker network create para recrearla ni cambies su configuración por seguir un ejemplo. Crear una red nueva con otra interfaz, subred o nombre puede causar conflictos o dejar los stacks desconectados.

3. Reutiliza la macvlan desde Docker Compose

En un archivo Compose, declara la red existente como externa. El nombre de la clave puede ser el que prefieras, pero el valor de name debe coincidir con el nombre real de la red Docker. Este ejemplo utiliza vlan20_net:

services:
  mi-servicio:
    image: nginx:alpine
    restart: unless-stopped
    networks:
      - vlan20_net

networks:
  vlan20_net:
    external: true
    name: vlan20_net

Es un ejemplo mínimo de sintaxis, no una orden para desplegar Nginx en tu servidor. Sustituye mi-servicio y la imagen por el servicio que realmente quieras instalar. Sin una IP estática declarada, Docker asigna una dirección de la subred a ese endpoint; para servicios que necesiten una IP fija, planifícala y verifica que esté libre antes de configurarla.

Al conectar un servicio directamente a macvlan, normalmente accedes a él mediante la IP y el puerto en el que escucha dentro del contenedor. No añadas automáticamente ports: para publicar esos mismos puertos en el host: la publicación de puertos y el acceso directo a la IP macvlan son mecanismos distintos.

4. Portainer en la VLAN 20

Portainer CE ya está conectado a vlan20_net en la configuración real de este ejemplo. La inspección del contenedor confirmó la IP 192.168.50.10/24, con gateway 192.168.50.1, y la imagen portainer/portainer-ce:latest.

docker inspect portainer --format '{{json .NetworkSettings.Networks}}'
docker inspect portainer --format 'Imagen={{.Config.Image}} Puertos={{json .HostConfig.PortBindings}}'

En esta instalación, el contenedor tiene una IP propia en macvlan y además aparece una publicación del puerto HTTPS 9443 en la configuración de Docker. La dirección siguiente utiliza una IP ficticia; en tu red debes usar la IP real que hayas reservado para Portainer:

https://192.168.50.10:9443

La configuración de ejemplo conserva el uso de una red externa existente y una IP estática. Si estás instalando Portainer desde cero, consulta la documentación oficial de Portainer para la versión y el método de despliegue que vayas a utilizar. No copies una plantilla con la IP 192.168.50.10 sobre una instalación existente: esa dirección ya está asignada a Portainer en este homelab. Reutilizarla en otro contenedor produciría un conflicto de IP.

5. Verificaciones después de desplegar un servicio

Después de añadir un servicio a una red existente, comprueba el estado y la dirección asignada antes de darlo por terminado:

docker compose ps
docker network inspect vlan20_net
docker inspect NOMBRE_CONTENEDOR --format '{{json .NetworkSettings.Networks}}'

Sustituye NOMBRE_CONTENEDOR por el nombre real del contenedor. Comprueba después la conectividad desde otro dispositivo de la VLAN y abre el puerto correcto del servicio. Si no responde, revisa primero la IP asignada, el puerto de escucha, el firewall y la configuración del switch/router; no recrees la red como primera medida.

6. Limitaciones y seguridad

  • Host y contenedores: macvlan suele aislar la comunicación directa entre el host y los endpoints macvlan. Si necesitas esa comunicación, diseña y prueba una interfaz macvlan auxiliar en el host o utiliza una red bridge para ese flujo; no añadas interfaces o rutas sin planificar una IP libre.
  • Socket Docker: montar /var/run/docker.sock en Portainer otorga un control muy amplio sobre Docker y, en la práctica, sobre el host. Protégelo como acceso administrativo.
  • Panel de administración: no expongas Portainer directamente a Internet. Prioriza acceso por LAN o VPN, contraseñas únicas, actualizaciones y reglas de firewall.
  • Versiones: latest facilita obtener la versión más reciente, pero no fija una versión reproducible. En entornos estables, registra la versión probada y planifica las actualizaciones.
  • IP estáticas: excluye las direcciones reservadas del rango DHCP o gestiona las reservas de forma coherente, y documenta qué servicio utiliza cada IP.

7. Sigue con la configuración del homelab

Una red segmentada funciona mejor cuando las reglas de acceso están bien documentadas. Puedes continuar con la guía para configurar un firewall con VLANs desde cero en un homelab o aprender a instalar UniFi Network Application con Docker Compose.

La idea clave es sencilla: inspecciona primero, reutiliza la red que ya funciona y asigna IPs únicamente cuando estén planificadas. Así puedes añadir servicios a tu homelab sin recrear la macvlan ni poner en riesgo los contenedores que ya están en producción.

Siguiente tutorial: Instalar y organizar servicios esenciales del homelab

En el tutorial 6 continuaremos la ruta de Docker y servicios paso a paso.

Pasa al siguiente tutorial →

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *