Brazil's biggest MU Online portal — since 2003
Tutorial Advanced Infrastructure

How to Containerize Your MU Online Server with Docker

Package MySQL, GameServer, ConnectServer, JoinServer, and DataServer into isolated Docker containers, with docker-compose, persistent volumes, and an internal network, making deployment, backup, and migration of your MU Online server easier.

BR Bruno · Updated on Mar 31, 2026 · ⏱ 17 min read
Quick answer

Running a MU Online server directly on the operating system works, but it creates a recurring problem: MySQL, .NET/VC++ redistributable, and emulator binary dependencies end up scattered and hard to reproduce on another machine. Containerizing the server with Docker solves this — each component (dat

Running a MU Online server directly on the operating system works, but it creates a recurring problem: MySQL, .NET/VC++ redistributable, and emulator binary dependencies end up scattered and hard to reproduce on another machine. Containerizing the server with Docker solves this — each component (database, ConnectServer, JoinServer, GameServer, DataServer) runs isolated, with its own dependencies, and the whole environment can be recreated in minutes with a single command. This tutorial shows how to structure a complete docker-compose setup for a MU server, from individual Dockerfiles to data persistence and the internal network between services.

Why containerize a MU Online server

A traditional MU server (based on emulators like MuEmu or IGCN) is made up of several processes that need to run simultaneously and communicate with each other: MySQL, DataServer, JoinServer, ConnectServer, and GameServer. Without containers, migrating this whole set to another machine means manually reinstalling every dependency, reconfiguring paths, and hoping the versions match. With Docker, each piece becomes a versioned image with its dependencies declared in a Dockerfile — the entire environment becomes reproducible, testable on a development machine, and migratable to a new server with docker-compose up.

Prerequisites

  • Docker Engine and Docker Compose installed (native Linux, or Docker Desktop with WSL2 on Windows).
  • MU emulator binaries (GameServer, ConnectServer, JoinServer, DataServer) already working outside a container, to serve as the base for the Dockerfiles.
  • A complete backup of the current database before migrating to the containerized environment.
  • Basic knowledge of Docker networking (bridge networks, port exposure).

Overview of the container architecture

ServiceBase imageExposed portsPersistent volume
mu-mysqlmysql:5.7 or mariadb:10.63306mu-db-data
mu-dataservermcr.microsoft.com/windows/servercore or Wine/Linux55757 (internal)mu-data-files
mu-joinserverWindows/Wine44405
mu-connectserverWindows/Wine44405 (client)
mu-gameserverWindows/Wine55901+mu-game-logs

All services share an internal Docker network (mu-network), which lets them communicate by service name instead of a fixed IP — essential for portability between development and production environments.

Structuring the docker-compose.yml

version: "3.8"

services:
  mu-mysql:
    image: mysql:5.7
    container_name: mu-mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: "strong_password_here"
      MYSQL_DATABASE: "MuOnline"
    volumes:
      - mu-db-data:/var/lib/mysql
      - ./sql/init:/docker-entrypoint-initdb.d
    networks:
      - mu-network
    ports:
      - "3306:3306"

  mu-gameserver:
    build: ./gameserver
    container_name: mu-gameserver
    restart: unless-stopped
    depends_on:
      - mu-mysql
    environment:
      DB_HOST: mu-mysql
      DB_USER: root
      DB_PASS: "strong_password_here"
    volumes:
      - mu-game-logs:/app/logs
    networks:
      - mu-network
    ports:
      - "55901:55901"

networks:
  mu-network:
    driver: bridge

volumes:
  mu-db-data:
  mu-game-logs:
  mu-data-files:

This file is the central piece: it describes every service, their dependencies (depends_on), environment variables, and the shared network.

Writing the GameServer Dockerfile

FROM mcr.microsoft.com/windows/servercore:ltsc2022

WORKDIR /app
COPY ./bin/GameServer.exe .
COPY ./bin/Data/ ./Data/
COPY ./bin/Config/ ./Config/

EXPOSE 55901

CMD ["GameServer.exe"]

For emulators compiled in C++/Delphi for Windows, this is the simplest route: use a Windows Server Core base image and copy the already-compiled binaries. In Linux environments, many admins choose to run the Windows binaries under Wine inside a Linux container, which reduces resource usage compared to a full Windows image.

Data persistence with volumes

Never leave the database or configuration files inside the container's "ephemeral" filesystem. A docker-compose down without named volumes wipes out all player progress. Always declare named volumes (mu-db-data, mu-game-logs) and, when possible, mount host folders directly for configuration files you edit frequently:

volumes:
  - ./config/GameServerInfo.dat:/app/Config/GameServerInfo.dat

This lets you edit the configuration on the host without needing to rebuild the image for every small tweak.

Configuring the internal network between services

Inside the mu-network, each container sees the others by the service name defined in Compose. This means that, in the GameServer's connection string to the database, instead of 127.0.0.1 you use mu-mysql:

[Database]
Host = mu-mysql
Port = 3306
User = root
Password = strong_password_here

This is the most common adjustment when migrating an existing configuration to Docker: any reference to localhost for the database needs to become the corresponding service name.

Backing up and restoring the containerized database

# Backup
docker exec mu-mysql mysqldump -u root -pstrong_password_here MuOnline > backup_$(date +%F).sql

# Restore
docker exec -i mu-mysql mysql -u root -pstrong_password_here MuOnline < backup_2026-07-30.sql

Automate this command with a cron job on the host, writing the .sql files outside the container — that way, even if you destroy and recreate the MySQL container, the backup stays safe on the host.

Logs and container monitoring

Use docker logs -f mu-gameserver to follow the GameServer's behavior in real time, and docker stats to monitor CPU/memory usage of each service. For production, it's worth integrating an observability stack (Prometheus + Grafana) collecting container metrics, especially GameServer CPU usage during peak hours, which tends to be the bottleneck on servers with many simultaneous players.

Updating the server without long downtime

When releasing a new emulator version or a configuration fix, the recommended flow is: rebuild only the changed service's image (docker-compose build mu-gameserver), then recreate only that container (docker-compose up -d --no-deps mu-gameserver), keeping MySQL and the other services running. This reduces downtime to seconds, instead of taking down the whole stack for a single fix.

Common errors and fixes

SymptomLikely causeFix
GameServer can't connect to the databaseConnection string still points to localhostSwitch to the Docker service name (mu-mysql)
Data disappears after docker-compose downVolume not declared or removed with -vUse named volumes and avoid down -v in production
Container keeps restarting in a loopInvalid configuration or dependency not readyAdd depends_on with a healthcheck on MySQL
Poor performance on Windows containersOverhead of a full Windows Server Core imageConsider Wine in a Linux container to reduce resource usage
Ports not reachable externallyMissing port mapping in composeConfirm ports: mapping the host port to the container

Containerization checklist

  • Docker and Docker Compose installed and tested.
  • Dockerfiles created for each service (MySQL, GameServer, ConnectServer, JoinServer).
  • docker-compose.yml with internal network and named volumes defined.
  • Connection strings updated to service names.
  • Automated and tested database backup routine.
  • Logs and metrics for each container being monitored.
  • Zero-downtime update process documented and tested.

With the server running in containers, the natural next step is standardizing this environment as the base for new deployments — even for those setting up the project from scratch. See the MU Online server creation tutorial to align this containerized infrastructure with the emulator fundamentals.

Frequently asked questions

Does Docker on Windows work well for MuServer, which normally runs on Windows Server?

Yes, via Docker Desktop with Windows containers, but it's much less common and heavier than Linux containers. The approach most used in the community is running MySQL in a Linux container and keeping the GameServer/ConnectServer binaries (which depend on Windows) running natively or in a Windows VM, containerizing only the part that supports Linux.

Does containerizing the server make it slower?

The overhead of a Docker container is minimal compared to running directly on the host, typically under a 5% difference. The gain in portability, isolation, and ease of deployment more than makes up for that marginal performance loss for most private MU servers.

How do I back up the database when it's inside a container?

Use a named Docker volume for MySQL's data directory, and run docker exec with mysqldump, pointing the output to a file on the host, outside the container. This ensures the backup survives even if the container is recreated or destroyed.

Do I need to rewrite MuServer's configuration to run in Docker?

No rewriting needed, just adjust connection strings. Instead of pointing the GameServer to localhost for the database, you point it to the service name defined in docker-compose (for example, mu-mysql), since containers communicate by service name within the Compose internal network.

Does Docker Compose replace a real production server?

For production with many simultaneous players, the ideal path is evolving to more robust orchestration (Docker Swarm, Kubernetes) or at least well-configured monitoring and automatic restarts. Docker Compose alone is excellent for development, testing, and small/medium servers, but serious production demands extra layers of resilience.

BR
Events, maps & items editor

Bruno specializes in MU Online events, maps, bosses and item economy. He documents every detail based on real gameplay.

Keep reading

Related articles