Docker container for running Cubyz headless server with multi-architecture support (amd64/arm64).
docker run -d \
-p 47649:47649/udp \
-v ./saves:/cubyz/saves \
-e CUBYZ_WORLD_NAME=world \
ghcr.io/amerkuri/cubyz-server-docker:latestNote: Make sure mapped directory or volume
./savesalready contains existing world dataworld!
Create a compose.yml file:
services:
cubyz:
image: ghcr.io/amerkuri/cubyz-server-docker:latest
ports:
- "47649:47649/udp"
volumes:
- ./saves:/cubyz/saves
environment:
- CUBYZ_WORLD_NAME=world
restart: unless-stoppedNote: For a full
compose.ymlexample with auto-heal and health checks, seecompose.yml.
Then run:
# Start server
docker compose up -d
# View logs
docker compose logs -f
# Stop server
docker compose downDocker image tags track upstream Cubyz releases published at https://github.com/PixelGuys/Cubyz/tags. Upstream tags use plain semantic versioning (0.1.0). For any upstream release, a multi-architecture image (linux/amd64, linux/arm64) is built and pushed:
X.Y.Z– Exact version (e.g.,0.1.0), built with-Drelease=true.latest– Most recent upstream release, built with-Drelease=true.dev– Latest upstreammasterbranch, built without-Drelease=true(latest dev changes, syncs with upstream branch every hour).main– Built from this repository'smainbranch (internal, for CI/testing purposes only).
| Trigger | Upstream Ref | Release Build | Image Tags |
|---|---|---|---|
Push to main branch |
master |
✅ | main |
Pull request to main |
master |
✅ | pr-X |
Tag push (e.g., v1.0.0) |
v1.0.0 |
✅ | 1.0.0, latest |
| Upstream tag detected (polling) | v1.0.0 |
✅ | 1.0.0, latest |
| Upstream master changes (polling) | master |
❌ | dev |
A GitHub Actions workflow runs every hour to check for upstream changes:
-
New tags – Compares upstream Cubyz tags against existing GHCR image tags. Any missing version triggers a release build.
-
Master branch commits – Compares the latest upstream
mastercommit SHA against the last built SHA. If different, triggers adevbuild. The SHA is tracked via a.last-dev-shafile committed to this repository.
This ensures Docker images stay in sync with upstream.
For stable deployments, pin an exact version (X.Y.Z). Use latest only when you intentionally want automatic upgrades. Use dev to test latest changes from upstream master (not recommended for production).
# Exact version (recommended for production)
docker run ghcr.io/amerkuri/cubyz-server-docker:0.1.0
# Latest released version
docker run ghcr.io/amerkuri/cubyz-server-docker:latest
# Development build (latest upstream master)
docker run ghcr.io/amerkuri/cubyz-server-docker:devCompose example with a pinned version:
services:
cubyz:
image: ghcr.io/amerkuri/cubyz-server-docker:0.1.0
network_mode: host
volumes:
- ./saves:/cubyz/saves
environment:
- CUBYZ_WORLD_NAME=world
restart: unless-stopped- Review available tags (GitHub packages UI or:
crane ls ghcr.io/amerkuri/cubyz-server-docker). - Update the tag in your deployment (e.g. bump
0.1.0to0.1.1). - Pull & recreate containers:
docker pull ghcr.io/amerkuri/cubyz-server-docker:0.0.2
docker compose up -d --pull always --force-recreate# Build for your architecture
npm run build
# Or with Docker Compose
docker compose build --no-cache
# Build multi-arch manually
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t cubyz-server:local \
.CUBYZ_WORLD_NAME- World name (default:world)
You can customize the build process using these arguments:
GIT_REPO- Cubyz repository URL (default:https://github.com/PixelGuys/Cubyz)GIT_REF- Git reference to build from: branch, tag, or commit SHA (default:master)USER_UID- User ID for the cubyz user (default:1000)USER_GID- Group ID for the cubyz group (default:1000)
Example with custom build args:
docker build \
--build-arg GIT_REPO=https://github.com/your-fork/Cubyz.git \
--build-arg GIT_REF=v0.1.0 \
--build-arg USER_UID=100 \
--build-arg USER_GID=101 \
-t cubyz-server:custom \
.Or in compose.yml:
services:
cubyz:
build:
context: .
args:
- GIT_REPO=https://github.com/your-fork/Cubyz.git
- GIT_REF=v0.1.0
- USER_UID=1001
- USER_GID=1001/cubyz/saves- Persistent world data
47649/udp- Game server port
-
Container exited with code 137
This may indicate insufficient memory. Monitor memory usage and consider allocating more resources. -
Failed to create world: FileNotFound
Ensure the volume for saves is correctly mounted, existing world is present atsaves/worldand has appropriate permissions. -
Unknown connection from address: 192.168.x.x:30287 Use host networking mode
--network hostin Docker to avoid NAT issues -
GLFW Error(65544): X11: Failed to load Xlib
For < 0.1.0 versions headless server is not supported. Uselatesttag instead.