El mayor portal de MU Online de Brasil — desde 2003
Tutorial Avanzado Infraestructura

Cómo orquestar los servicios de tu servidor de MU Online con Docker Compose

Contenedoriza y orquesta ConnectServer, JoinServer, GameServer, base de datos y web con Docker Compose, con ejemplos de docker-compose.yml, redes internas, volúmenes persistentes y buenas prácticas de producción.

RO Rodrigo · Actualizado el 11 jul 2020 · ⏱ 17 min de lectura
Respuesta rápida

Los servidores de MU Online tradicionalmente corren como una colección de procesos sueltos en una máquina Windows: ConnectServer, JoinServer, GameServer, base de datos y, a veces, un panel web aparte. Esto funciona, pero dificulta los backups consistentes, las actualizaciones sin downtime y la repli

Los servidores de MU Online tradicionalmente corren como una colección de procesos sueltos en una máquina Windows: ConnectServer, JoinServer, GameServer, base de datos y, a veces, un panel web aparte. Esto funciona, pero dificulta los backups consistentes, las actualizaciones sin downtime y la replicación del entorno en otra máquina. Docker Compose resuelve ese problema orquestando todos esos servicios como contenedores definidos en un único archivo declarativo, con redes internas aisladas y volúmenes persistentes. Este tutorial muestra cómo estructurar esa orquestación en la práctica, con ejemplos de configuración y cuidados específicos para el stack de un servidor de MU.

Por qué contenedorizar un servidor de MU Online

Contenedorizar trae tres beneficios concretos: (1) reproducibilidad — el entorno entero (versiones de base de datos, dependencias) queda descrito en un archivo, no en la memoria de quien configuró la máquina originalmente; (2) aislamiento — un problema en la base de datos no tumba al GameServer, y viceversa; (3) portabilidad — mover el servidor entero a otra máquina o proveedor se reduce a copiar los archivos de configuración y los volúmenes de datos.

Visión general de la arquitectura de servicios

ServicioFunciónDepende de
dbBase de datos (MSSQL/MySQL) con cuentas y personajes
connectserverPunto de entrada del cliente, lista de servidoresdb
joinserverAutenticación y enrutamiento hacia el GameServerdb, connectserver
gameserverLógica principal del juegodb, joinserver
webPanel/sitio (registro, ranking, tienda)db

Estructura de directorios recomendada

mu-infra/
├── docker-compose.yml
├── .env
├── db/
│   └── init/            # scripts de inicialización del esquema
├── connectserver/
│   └── Data/
├── gameserver/
│   └── Data/
└── web/
    └── (código del panel)

Mantener cada servicio en su propia carpeta con un volumen dedicado facilita tanto el backup individual como la sustitución aislada de un componente.

Ejemplo de docker-compose.yml

version: "3.9"

services:
  db:
    image: mysql:8.0
    container_name: mu_db
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: mu_online
    volumes:
      - db_data:/var/lib/mysql
      - ./db/init:/docker-entrypoint-initdb.d
    networks:
      - mu_internal

  connectserver:
    build: ./connectserver
    container_name: mu_connectserver
    restart: unless-stopped
    depends_on:
      - db
    ports:
      - "44405:44405"
    networks:
      - mu_internal

  gameserver:
    build: ./gameserver
    container_name: mu_gameserver
    restart: unless-stopped
    depends_on:
      - db
      - connectserver
    ports:
      - "55901:55901"
    volumes:
      - ./gameserver/Data:/app/Data
    networks:
      - mu_internal

  web:
    build: ./web
    container_name: mu_web
    restart: unless-stopped
    depends_on:
      - db
    ports:
      - "8080:80"
    networks:
      - mu_internal

networks:
  mu_internal:
    driver: bridge

volumes:
  db_data:

Variables de entorno y el archivo .env

Nunca dejes contraseñas de base de datos ni tokens hardcodeados en el docker-compose.yml. Centralízalos en un archivo .env en la raíz del proyecto:

DB_ROOT_PASSWORD=cambia-esta-contrasena
DB_USER=mu_app
DB_PASSWORD=otra-contrasena-fuerte
GAMESERVER_PORT=55901

Compose lee automáticamente el .env en la misma carpeta y sustituye las variables ${...} referenciadas en el YAML.

Redes internas y exposición de puertos

Todos los servicios comparten la red mu_internal, lo que les permite comunicarse entre sí por el nombre del servicio (por ejemplo, el GameServer accede a la base de datos vía el host db, no localhost). Solo los puertos realmente necesarios para el cliente del juego y el panel web deben mapearse al host con ports: — la base de datos no debe tener un puerto expuesto externamente en producción, solo accesible por la red interna de Compose.

Persistencia de datos con volúmenes

El volumen nombrado db_data garantiza que el contenido de la base de datos sobreviva a la recreación del contenedor (docker compose down seguido de up). Los volúmenes de bind mount (como ./gameserver/Data:/app/Data), en cambio, permiten editar archivos de configuración del GameServer directamente desde el host, sin necesidad de entrar al contenedor — esencial para ajustes rápidos de tasa de drop, experiencia y eventos.

Rutina de backup de la base de datos

Agrega un servicio auxiliar de backup programado, o ejecuta externamente vía cron un comando como:

docker exec mu_db mysqldump -u root -p"$DB_ROOT_PASSWORD" mu_online > backups/mu_online_$(date +%Y%m%d_%H%M).sql

Automatiza esto con un cron en el host (o un contenedor dedicado con cron más el mismo comando) y mantén una política de retención — por ejemplo, backups diarios de los últimos 14 días y semanales de los últimos 3 meses.

Actualizando servicios sin downtime total

Para actualizar solo el panel web, por ejemplo, sin afectar al GameServer:

docker compose build web
docker compose up -d --no-deps web

Esto reconstruye y reinicia solo el contenedor web, manteniendo gameserver, connectserver y db corriendo normalmente. Los cambios de esquema de la base de datos, sin embargo, exigen coordinación cuidadosa — prueba siempre en un entorno de staging con una copia de la base antes de aplicar en producción.

Monitoreo básico de los contenedores

Comandos esenciales para la operación del día a día:

ComandoFunción
docker compose psVer el estado de todos los servicios
docker compose logs -f gameserverSeguir los logs del GameServer en tiempo real
docker statsVer el consumo de CPU/memoria por contenedor
docker compose restart connectserverReiniciar un servicio específico
docker compose down && docker compose up -dRecrear todo el stack (los datos persisten vía volumen)

Errores comunes y soluciones

SíntomaCausa probableSolución
El GameServer no se conecta a la base de datosNombre de host incorrecto (usando localhost en vez del nombre del servicio)Usa el nombre del servicio (db) como host dentro de la red de Compose
Los datos desaparecen al recrear los contenedoresVolumen no declarado o eliminado con -vDeclara volúmenes nombrados y evita docker compose down -v sin necesidad
Puerto de la base de datos accesible externamenteMapeo de puerto innecesario en producciónElimina ports: del servicio db en el entorno de producción
Contraseña expuesta en el repositorioCredenciales hardcodeadas en el docker-compose.ymlMuévelas todas al .env y agrega .env al .gitignore
La actualización de un servicio tumba a los demásUso de docker compose down completo para cambiar un servicioUsa up -d --build <servicio> para actualizar de forma aislada

Lista de verificación de orquestación con Docker Compose

  • Arquitectura de servicios mapeada (db, connectserver, joinserver, gameserver, web).
  • docker-compose.yml con redes internas y solo los puertos necesarios expuestos.
  • Variables sensibles centralizadas en .env y fuera del control de versiones.
  • Volúmenes nombrados para los datos persistentes de la base de datos.
  • Rutina de backup automatizada y probada (restore validado al menos una vez).
  • Proceso de actualización aislada por servicio documentado.
  • Monitoreo básico de logs y uso de recursos configurado.

Con el stack orquestado y reproducible, el siguiente paso natural es aplicar ese mismo rigor de infraestructura al resto del proyecto — mira el tutorial de cómo crear un servidor de MU Online para revisar la configuración completa de los servicios que ahora están contenedorizados.

Preguntas frecuentes

¿Necesito correr el MU Server entero en Docker aunque esté basado en Windows?

Es posible usar contenedores Windows (Windows Server Core) para emuladores compilados para Windows, o correr vía Wine en contenedores Linux para algunos componentes. El enfoque más estable suele ser contenedorizar la base de datos y los servicios web en Linux, y evaluar caso por caso el binario del emulador.

¿Docker Compose reemplaza a un orquestador como Kubernetes para este caso?

Para un servidor de MU de tamaño pequeño a mediano, Docker Compose es suficiente y mucho más simple de mantener. Kubernetes solo se justifica en escenarios de múltiples instancias, alta disponibilidad real o escala que exija scheduling automático entre varios hosts.

¿Cómo hago backup de la base de datos que corre en contenedor?

Usa el volumen nombrado de la base (por ejemplo, mssql_data o mysql_data) y ejecuta dumps periódicos con un servicio adicional en el compose o un cron externo que ejecute docker exec con el comando de backup, guardando fuera del contenedor.

¿Es seguro exponer los puertos del GameServer directamente desde el contenedor?

Sí, siempre que mapees solo los puertos necesarios en el host y mantengas un firewall configurado. Evita exponer puertos de base de datos y administración fuera de la red interna de Docker Compose.

¿Cómo actualizar un servicio sin tumbar el servidor entero?

Con Docker Compose puedes reconstruir y reiniciar un servicio específico (por ejemplo, docker compose up -d --build web) sin afectar a los demás contenedores, siempre que no dependan de un cambio de esquema en la base de datos compartida.

RO
Fundador y editor jefe

Rodrigo mantiene ViciadosMU desde los inicios del portal. Especialista en creación y administración de servidores de MU Online, historia del juego y la evolución de las seasons — escribió buena parte del archivo antes de 2024.

Sigue leyendo

Artículos relacionados