Rootless, tested Project Zomboid Dedicated Server wrapper with SteamCMD and graceful shutdown.
542
A rootless Docker wrapper for the official Project Zomboid Dedicated Server distributed through Steam app 380870.
The image is built on a SteamCMD base with the runtime packages required by the wrapper. Project Zomboid server files are downloaded from Steam into a persistent volume on first startup and are not redistributed in the image.
Only
linux/amd64is published. The official Linux server, bundled JRE, and native libraries are x86-64. FEX and Box64 emulation are not included.
This project is not affiliated with Valve or The Indie Stone.
1000:1000Create compose.yaml:
services:
zomboid-dedicated-server:
image: docker.io/criogaid/zomboid-dedicated-server:latest
platform: linux/amd64
container_name: zomboid-dedicated-server
restart: unless-stopped
stop_grace_period: 90s
environment:
ADMIN_PASSWORD: "replace-with-a-strong-password"
SERVER_NAME: "ZomboidServer"
MAX_RAM: "4096m"
UPDATE_ON_START: "true"
ports:
- "16261:16261/udp"
- "16262:16262/udp"
volumes:
- zomboid-server:/home/steam/ZomboidDedicatedServer
- zomboid-config:/home/steam/Zomboid
volumes:
zomboid-server:
zomboid-config:
Start the server and follow its logs:
docker compose up -d
docker compose logs -f
docker volume create zomboid-server
docker volume create zomboid-config
docker run -d \
--name zomboid-dedicated-server \
--platform linux/amd64 \
--restart unless-stopped \
--stop-timeout 90 \
-e ADMIN_PASSWORD='replace-with-a-strong-password' \
-p 16261:16261/udp \
-p 16262:16262/udp \
-v zomboid-server:/home/steam/ZomboidDedicatedServer \
-v zomboid-config:/home/steam/Zomboid \
docker.io/criogaid/zomboid-dedicated-server:latest
The first installation downloads roughly 7 GiB and needs about 15 GiB of free disk space while SteamCMD downloads and stages the server.
The container becomes healthy after the game log reports *** SERVER STARTED ****.
docker ps --filter name=zomboid-dedicated-server
docker logs -f zomboid-dedicated-server
| Container path | Contents |
|---|---|
/home/steam/ZomboidDedicatedServer | Steam app files, Workshop content, appmanifest, and tested-version marker |
/home/steam/Zomboid | Server INI files, saves, logs, database, and sandbox settings |
Both paths must be writable by UID/GID 1000:1000. Docker named volumes inherit the required ownership from the image. Bind-mounted host directories must be prepared manually:
mkdir -p ZomboidConfig ZomboidDedicatedServer
sudo chown -R 1000:1000 ZomboidConfig ZomboidDedicatedServer
Never mount the same /home/steam/Zomboid directory into two running containers. The wrapper takes an exclusive lock and fails instead of allowing concurrent writes.
ADMIN_PASSWORD is required and has no insecure fallback. Defaults are written only when a new server INI is created. Existing INI files retain comments, ordering, and unknown keys; afterward, only explicitly supplied environment variables override managed values.
| Variable | Default | Purpose |
|---|---|---|
ADMIN_PASSWORD | required | Administrator account password |
ADMIN_USERNAME | admin | Administrator account name |
SERVER_NAME | ZomboidServer | Config/save prefix and initial public name |
SERVER_PASSWORD | empty | Player join password |
GAME_VERSION | public | Steam branch, for example legacy41 |
UPDATE_ON_START | true | Run SteamCMD before starting |
VALIDATE_FILES | true | Validate installed files through SteamCMD |
MAX_RAM | 4096m | JVM maximum heap, for example 4g or 6144m |
GC_CONFIG | ZGC | ZGC, G1GC, ParallelGC, or SerialGC |
DEFAULT_PORT | 16261 | Main UDP game port |
UDP_PORT | 16262 | Additional UDP client port |
MAX_PLAYERS | 16 | Maximum player count, from 1 to 100 |
AUTOSAVE_INTERVAL | 15 | Autosave interval in minutes |
MAP_NAMES | Muldraugh, KY | Semicolon-separated map names |
MOD_NAMES | empty | Semicolon-separated mod IDs |
MOD_WORKSHOP_IDS | empty | Semicolon-separated Workshop item IDs |
PAUSE_ON_EMPTY | true | Pause game time when no players are connected |
PUBLIC_SERVER | true | Allow players without a pre-created whitelist account (Open) |
PUBLIC_LISTED | false | List the server publicly (Public) |
STEAM_VAC | true | Enable Steam VAC integration |
USE_STEAM | true | Set false for -nosteam mode |
RCON_PASSWORD | empty | Optional RCON password; empty disables RCON |
RCON_PORT | 27015 | Optional RCON TCP port |
BIND_IP | container IP | Explicit server bind address |
SHUTDOWN_TIMEOUT | 60 | Seconds allowed for console save and quit |
RCON is disabled by default. If enabled, publish TCP port 27015 deliberately and use a strong password.
With UPDATE_ON_START=true, the wrapper runs SteamCMD against GAME_VERSION=public on every start. Set UPDATE_ON_START=false only after an installation exists when updates must happen during a controlled maintenance window.
| Tag | Meaning |
|---|---|
latest | Latest wrapper revision that passed the complete release test |
<version> | Wrapper tested against that stable Project Zomboid version |
<version>-b<build>-m<manifest>-g<revision> | Exact tested game version, Steam build, Linux manifest, and wrapper revision |
A version tag records what passed publication testing; it does not freeze Steam's moving public branch. A later startup with updates enabled may download a newer public build. For a reproducible running instance, retain both the Docker image digest and the installed persistent volume.
Before publishing, the release workflow binds:
108600380870380873 manifest IDThe workflow then performs a fresh-volume installation, checks the appmanifest, starts the real server on native amd64, verifies readiness and version, issues console save and quit, rechecks upstream metadata, and publishes the trace, version, and latest tags from one immutable digest.
Build 41 and Build 42 saves are not compatible. The wrapper never deletes or migrates saves automatically. If saves exist but their recorded major version does not match the image's tested target, startup fails before SteamCMD changes the installation.
The guard compares saves with metadata baked into the image; it cannot predict a later major-version change on Steam's moving public branch. Check the current branch before starting an older image with updates enabled. Use GAME_VERSION=legacy41 to stay on the preserved Build 41 branch.
After making an external backup and deciding that the target migration is intended, acknowledge the target major for the first startup:
environment:
ACKNOWLEDGE_MAJOR_UPDATE: "42"
Remove the variable after the first successful start.
Use a container stop timeout of at least 90 seconds:
docker stop --time 90 zomboid-dedicated-server
After readiness, the wrapper sends save and quit through a private console FIFO, waits up to SHUTDOWN_TIMEOUT, then falls back to bounded TERM and KILL handling. SteamCMD and early server startup also use bounded shutdown handling. Expected operator-requested termination exits as 0; timeouts and unexpected child failures remain non-zero.
Wrapper code is licensed under GPL-3.0-or-later. Project Zomboid and SteamCMD are not covered by this repository's GPL license and remain subject to their respective owners' terms. The image does not contain or redistribute Project Zomboid server files.
Content type
Image
Digest
sha256:cfeee5447…
Size
166.9 MB
Last updated
4 days ago
docker pull criogaid/zomboid-dedicated-server