aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Game Server

Docker Game Server: Run It in a Portable Container

Setting up a Docker game server frees your server from being tied to one operating system or a single machine: every dependency, version and configuration is packaged inside an image, so the server runs the same way wherever you move it. You'll never say "it worked on my box but wouldn't start on the VPS" again. In this article we'll look at the logic of containerizing a game server, how to protect persistent save data, port mapping, automatic restarts, and how to back up and move everything to another machine — all with practical examples.

Why containerize a game server?

In a classic setup you drop the server onto a bare machine, manually install the right runtime (Java, .NET, a specific glibc version, etc.) and write service files. The problem is that this setup is specific to that machine. Docker flips this around:

  • Portability: the same image runs identically on your dev machine, on a VPS and on a backup server.
  • Isolation: the server runs in its own container; it doesn't pollute the host system or clash with other services over versions.
  • Reproducibility: your configuration lives in a Dockerfile and a compose.yaml; you can rebuild the whole setup with one command.
  • Easy version management: image tags (:1.20, :latest) pin the server version and let you roll back when needed.

A ready-made image, or your own Dockerfile?

For most popular games there are community images. For Minecraft, for example, itzg/minecraft-server is a mature and widely used image that handles EULA, version and memory settings through environment variables. If a ready image exists, using it is the fastest path. But for a custom or self-written server you need to build your own image. For a simple Linux server binary, a typical Dockerfile looks like this:

FROM debian:12-slim

# Runtime dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
        ca-certificates libstdc++6 \
    && rm -rf /var/lib/apt/lists/*

# A dedicated user instead of root
RUN useradd --system --create-home --uid 1000 gameserver
USER gameserver
WORKDIR /home/gameserver

# Copy the server files
COPY --chown=gameserver:gameserver ./server/ ./

# Game port (example: UDP 27015)
EXPOSE 27015/udp

CMD ["./game_server", "--config", "server.cfg"]

There are a few good habits here: building from a -slim base keeps the image small, --no-install-recommends drops unnecessary packages, and running the server as a non-root user matters for security. Root inside a container increases risk on the host.

Persistent data: saves must live in a volume

This is the most critical point. A container is ephemeral; when it's removed with docker rm, its filesystem goes with it. If the world save, player data and configuration stay inside the container, you'll lose everything on an update. The solution is to bind those folders to a volume or a host directory:

docker run -d \
  --name game-server \
  -p 27015:27015/udp \
  -v /srv/game/data:/home/gameserver/data \
  --restart unless-stopped \
  my-server:1.0

The -v /srv/game/data:/home/gameserver/data clause binds a persistent folder on the host to the container's data directory. Now even if you delete, update or move the container to another machine, the saves stay on the host side. When you configure your server, make sure the save path actually writes to this bound directory.

Port mapping: TCP or UDP?

Game servers mostly use UDP, because in real-time play low latency matters more than retransmitting lost packets. Some servers also open a TCP query/RCON port. In the -p flag you must specify the protocol correctly:

  • -p 27015:27015/udp — the UDP port for game traffic.
  • -p 27015:27015/tcp — the TCP port for RCON / queries (if needed).

The number on the left is the host port, the one on the right the container port. If the server can't be reached from outside, this is the first place to look: either the protocol is wrong (TCP/UDP mixed up) or the VPS firewall (for example ufw) is blocking the port.

A tidy setup with Compose

Instead of writing long docker run lines on the command line, moving the configuration into a compose.yaml file is far more sustainable. The server's entire definition lives in one file and comes up with docker compose up -d:

services:
  game:
    build: .
    container_name: game-server
    ports:
      - "27015:27015/udp"
    volumes:
      - ./data:/home/gameserver/data
    environment:
      MAX_PLAYERS: "32"
      SERVER_NAME: "Aslain Server"
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 2g
          cpus: "2.0"

The restart: unless-stopped here makes the container come back up automatically even if the server crashes or the machine reboots — a critical setting for a game server. The deploy.resources.limits block keeps a single game server from eating all the CPU and RAM and locking up the host.

Backups and moving to another server

The nicest part of the container approach is that migration boils down to little more than copying the data folder. Because the image is the same everywhere, on the new server all you have to do is pull/build the image and restore the data directory:

# Snapshot of the data folder (safest taken while the server is stopped)
docker compose stop game
tar czf backup-$(date +%F).tar.gz ./data
docker compose start game

# On the new server:
tar xzf backup-2026-06-28.tar.gz
docker compose up -d

For less downtime on a live server, you can trigger the in-game "save" command first so everything is flushed to disk, then take the backup. You can also wire this backup step into a cron job to produce automatic daily backups.

Frequently Asked Questions

Is there a performance hit with a Docker game server?

On Linux, Docker is not a virtual machine; it uses a lightweight isolation layer that shares the kernel with the host. The measurable overhead for CPU and memory is very low and causes no latency that players would feel. On the network side, the default bridge network adds a small NAT overhead; if you don't want that, you can expose ports directly on the host with network_mode: host.

Will my world save disappear when the container is deleted?

No, if you bound the data to a volume or a host directory. Folders mounted out with -v are independent of the container's lifecycle; even if you delete and recreate the container, the saves stay in place. Keeping the data outside the container is the single most important rule.

Can I containerize a Windows game server too?

Docker is at its strongest on Linux servers. A server binary that only runs on Windows requires Windows containers, which is a more limited and awkward path. In most cases, preferring servers that have a Linux build lets you get the most out of Docker.

Want to move your game server into a container? To plan the whole setup together — from writing the Dockerfile to persistent data, backups and VPS deployment — get in touch with me.

Bu kategorideki tüm yazılar →

Devamı için