Containerized Valheim Servers with Docker Compose
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 versionresolves cleanly). - UDP ports 2456 and 2457 open at the firewall.
- A non root user in the
dockergroup 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.
sudo mkdir -p /opt/valheim/{config,data,backups}sudo chown -R $USER:$USER /opt/valheimcd /opt/valheimStep 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.
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
docker compose up -ddocker compose logs -f valheimFirst 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.
ls -lh /opt/valheim/backups | head# Spot check the most recent archivetar -tzf /opt/valheim/backups/$(ls -t /opt/valheim/backups | head -1) | headPerformance 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
./backupson a separate disk if possible. If the world volume fails, you do not want the backups failing with it. - Wire the
STATUS_HTTPendpoint into uptime monitoring. A healthy server responds with player count and uptime onhttp://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.