Hosting Guides

Containerized Valheim Servers with Docker Compose

6 min readUbuntu 24.04Docker ComposeUnity
Once your server is online, jump to the Valheim command and config reference.

Valheim's world save format is small but unforgiving. A single bad shutdown during a write window can corrupt the .db file and force a partial rollback to the last in game autosave, which can wipe hours of building progress. Containerizing the server with Docker Compose solves the operational half of that problem: the world directory becomes a host mounted volume, scheduled backups are trivial to add as sidecar processes, and the entire deployment is reproducible from one YAML file.

The community standard image is lloesche/valheim-server. It runs the official Iron Gate dedicated binaries under supervised processes, exposes every relevant tunable as an environment variable, and ships with a built in backup scheduler that writes timestamped archives without ever stopping the server.

Prerequisites

  • Ubuntu 24.04 LTS with 4 GB of RAM minimum, 8 GB recommended for 10 player worlds.
  • Docker Engine and the Compose plugin installed (docker compose version resolves cleanly).
  • UDP ports 2456 and 2457 open at the firewall.
  • A non root user in the docker group for routine operations.

Step 1: Project Layout

Create the project directory and the two child folders the container will mount. Creating them up front (as your user, not root) keeps file ownership sane after the container writes into them.

user@host
sudo mkdir -p /opt/valheim/{config,data,backups}
sudo chown -R $USER:$USER /opt/valheim
cd /opt/valheim

Step 2: The Compose File

The image accepts every server parameter as an environment variable, which keeps the compose file declarative and free of post boot mutation. Pay attention to the volume mappings, because each one corresponds to a category of state the server writes: config for the world database, data for the server install, backups for the archived snapshots.

docker-compose.yml
services:
valheim:
image: lloesche/valheim-server:latest
container_name: valheim
restart: unless-stopped
cap_add:
- SYS_NICE
ports:
- "2456-2457:2456-2457/udp"
volumes:
- ./config:/config
- ./data:/opt/valheim
- ./backups:/config/backups
environment:
SERVER_NAME: "Yggdrasil"
WORLD_NAME: "yggdrasil"
SERVER_PASS: "REPLACE_WITH_LONG_PASSWORD"
SERVER_PUBLIC: "true"
UPDATE_CRON: "0 4 * * *"
BACKUPS: "true"
BACKUPS_CRON: "0 */3 * * *"
BACKUPS_DIRECTORY: "/config/backups"
BACKUPS_MAX_AGE: "14"
BACKUPS_MAX_COUNT: "50"
PERMISSIONS_UMASK: "022"
STATUS_HTTP: "true"
STATUS_HTTP_PORT: "9001"

UPDATE_CRON tells the supervisor to check Steam for a new Valheim binary every night at 04:00 and apply it during a brief restart window. BACKUPS_CRON runs the in process backup routine every three hours without stopping gameplay, and the retention pair caps storage growth.

Step 3: First Boot

user@host
docker compose up -d
docker compose logs -f valheim

First boot downloads roughly 1.5 GB of dedicated server binaries from Steam, generates the world seed, and produces a fresh yggdrasil.db under ./config/worlds_local. The server is reachable as soon as you see Game server connected in the logs, which usually takes 60 to 90 seconds on first boot and around 15 seconds on restarts.

Step 4: Backup Verification

Backups are the entire reason we picked this image. After the first cron interval elapses, you should see timestamped .tgz archives appearing in /opt/valheim/backups. Restore them by stopping the container, replacing config/worlds_local/yggdrasil.db and .fwl with the files from the archive, and starting the container again.

user@host
ls -lh /opt/valheim/backups | head
# Spot check the most recent archive
tar -tzf /opt/valheim/backups/$(ls -t /opt/valheim/backups | head -1) | head

Performance and Tuning

  • The Iron Gate binary is single threaded for world simulation. Give it a fast core, not a wide one. Server frametime is far more sensitive to clock speed than to core count.
  • Cap the server at 10 active players. The networking layer struggles to keep terrain streaming consistent above that, regardless of CPU headroom.
  • Mount ./backups on a separate disk if possible. If the world volume fails, you do not want the backups failing with it.
  • Wire the STATUS_HTTP endpoint into uptime monitoring. A healthy server responds with player count and uptime on http://host:9001/status.json.

Conclusion

With this compose file checked into source control, a fresh Valheim host is one docker compose up -d away, and the world is automatically archived every three hours into a directory you can ship offsite with rsync or any S3 client. The lloesche/valheim-server image handles the painful supervisor and update logic so you can focus on world design instead of restart scripts.