Skip to content

Commit 27b7017

Browse files
committed
Initial commit
1 parent 5e69b41 commit 27b7017

File tree

4 files changed

+535
-0
lines changed

4 files changed

+535
-0
lines changed

.github/workflows/build-docker.yml

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
name: Build & Push UT2004 Server (Docker Hub)
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
image_name:
7+
description: "Docker Hub image name (e.g., lancommander/ut2004)"
8+
required: true
9+
default: "lancommander/ut2004"
10+
version:
11+
description: "Version tag for the image"
12+
required: true
13+
default: "3339"
14+
push_latest:
15+
description: "Also push the :latest tag"
16+
required: true
17+
type: boolean
18+
default: false
19+
platforms:
20+
description: "Build platforms (comma-separated)"
21+
required: true
22+
default: "linux/amd64"
23+
24+
push:
25+
tags:
26+
- "v*"
27+
28+
permissions:
29+
contents: read
30+
31+
concurrency:
32+
group: dockerhub-${{ github.ref }}
33+
cancel-in-progress: true
34+
35+
jobs:
36+
build-and-push:
37+
runs-on: ubuntu-latest
38+
39+
steps:
40+
- name: Checkout
41+
uses: actions/checkout@v4
42+
43+
# Derive settings from either tag push or workflow_dispatch inputs
44+
- name: Resolve build variables
45+
id: vars
46+
shell: bash
47+
run: |
48+
set -euo pipefail
49+
50+
if [[ "${GITHUB_EVENT_NAME}" == "push" ]]; then
51+
# Tag push, e.g. refs/tags/v3339
52+
TAG_NAME="${GITHUB_REF_NAME}"
53+
VERSION="${TAG_NAME#v}"
54+
55+
# Default image name for tag builds:
56+
# Set this to your preferred repo, or replace with a repo secret if you prefer.
57+
IMAGE_NAME="${{ vars.DOCKERHUB_IMAGE_NAME }}"
58+
if [[ -z "${IMAGE_NAME}" ]]; then
59+
echo "DOCKERHUB_IMAGE_NAME variable is not set. Create it (e.g., 'lancommander/ut2004') or use workflow_dispatch."
60+
exit 1
61+
fi
62+
63+
PUSH_LATEST="false"
64+
PLATFORMS="linux/amd64"
65+
else
66+
IMAGE_NAME="${{ inputs.image_name }}"
67+
VERSION="${{ inputs.version }}"
68+
PUSH_LATEST="${{ inputs.push_latest }}"
69+
PLATFORMS="${{ inputs.platforms }}"
70+
fi
71+
72+
echo "image_name=${IMAGE_NAME}" >> "$GITHUB_OUTPUT"
73+
echo "push_latest=${PUSH_LATEST}" >> "$GITHUB_OUTPUT"
74+
echo "platforms=${PLATFORMS}" >> "$GITHUB_OUTPUT"
75+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
76+
77+
- name: Set up QEMU (multi-arch)
78+
uses: docker/setup-qemu-action@v3
79+
80+
- name: Set up Docker Buildx
81+
uses: docker/setup-buildx-action@v3
82+
83+
- name: Log in to Docker Hub
84+
uses: docker/login-action@v3
85+
with:
86+
username: ${{ secrets.DOCKERHUB_USERNAME }}
87+
password: ${{ secrets.DOCKERHUB_TOKEN }}
88+
89+
# Generates tags/labels. We’ll produce:
90+
# - :<version>
91+
# - :latest (optional)
92+
- name: Docker metadata
93+
id: meta
94+
uses: docker/metadata-action@v5
95+
with:
96+
images: ${{ steps.vars.outputs.image_name }}
97+
tags: |
98+
type=raw,value=${{ steps.vars.outputs.version }}
99+
type=raw,value=latest,enable=${{ steps.vars.outputs.push_latest == 'true' }}
100+
labels: |
101+
org.opencontainers.image.title=Unreal Tournament 2004 Server
102+
org.opencontainers.image.source=${{ github.repositoryUrl }}
103+
org.opencontainers.image.revision=${{ github.sha }}
104+
105+
- name: Build and push
106+
uses: docker/build-push-action@v6
107+
with:
108+
context: .
109+
file: ./Dockerfile
110+
platforms: ${{ steps.vars.outputs.platforms }}
111+
push: true
112+
tags: ${{ steps.meta.outputs.tags }}
113+
labels: ${{ steps.meta.outputs.labels }}
114+
115+
# Optional: provide a short summary in the GitHub Actions UI
116+
- name: Summary
117+
run: |
118+
echo "Pushed image: ${{ steps.vars.outputs.image_name }}" >> $GITHUB_STEP_SUMMARY
119+
echo "Tags: ${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
120+
echo "Version: ${{ steps.vars.outputs.version }}" >> $GITHUB_STEP_SUMMARY
121+
echo "Platforms: ${{ steps.vars.outputs.platforms }}" >> $GITHUB_STEP_SUMMARY

Dockerfile

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# syntax=docker/dockerfile:1.7
2+
3+
FROM debian:bookworm-slim
4+
5+
# Runtime directories (mount these as volumes)
6+
ENV CONFIG_DIR=/config
7+
8+
# Server settings
9+
ENV SERVER_PORT=7777
10+
ENV SERVER_ARGS=""
11+
12+
# ----------------------------
13+
# Dependencies
14+
# ----------------------------
15+
# Enable multiarch for 32-bit libraries
16+
RUN dpkg --add-architecture i386 && \
17+
apt-get update && apt-get install -y --no-install-recommends \
18+
ca-certificates \
19+
curl \
20+
tar \
21+
gzip \
22+
gosu \
23+
lib32gcc-s1 \
24+
lib32stdc++6 \
25+
libc6-i386 \
26+
&& rm -rf /var/lib/apt/lists/*
27+
28+
# Install libstdc++5 (32-bit) for UT2004 - download from Debian archive
29+
# Note: libstdc++5 is not available in bookworm, so we download from an older Debian release
30+
RUN set -eux; \
31+
apt-get update; \
32+
libstdc5_url="https://archive.debian.org/debian/pool/main/g/gcc-3.3/libstdc++5_3.3.6-20_i386.deb"; \
33+
curl -fsSL "${libstdc5_url}" -o /tmp/libstdc++5.deb; \
34+
dpkg -i /tmp/libstdc++5.deb || apt-get -f install -y --no-install-recommends; \
35+
rm -f /tmp/libstdc++5.deb; \
36+
rm -rf /var/lib/apt/lists/*; \
37+
# Verify the library is installed
38+
ls -la /usr/lib/i386-linux-gnu/libstdc++.so.5* || ls -la /usr/lib32/libstdc++.so.5* || true
39+
40+
# ----------------------------
41+
# Create a non-root user
42+
# ----------------------------
43+
RUN useradd -m -u 10001 -s /usr/sbin/nologin ut2004 \
44+
&& mkdir -p "${CONFIG_DIR}" \
45+
&& chown -R ut2004:ut2004 "${CONFIG_DIR}"
46+
47+
# ----------------------------
48+
# Entrypoint
49+
# ----------------------------
50+
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
51+
RUN chmod +x /usr/local/bin/entrypoint.sh
52+
53+
VOLUME ["/config"]
54+
55+
EXPOSE 7777/udp 7778/udp 7779/udp
56+
57+
WORKDIR /config
58+
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

README.md

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# Unreal Tournament 2004 Dedicated Server (Docker)
2+
3+
This repository provides a Dockerized **Unreal Tournament 2004 dedicated server** suitable for running multiplayer UT2004 servers in a clean, reproducible way.
4+
The image is designed for **headless operation**, automatically downloads game assets on first startup, and supports bind-mounted configuration files.
5+
6+
---
7+
8+
## Features
9+
10+
- Runs the **Unreal Tournament 2004 dedicated server** (`ucc-bin`)
11+
- Automatically downloads and extracts game assets on first startup
12+
- Tracks downloaded assets to prevent re-downloading on container restarts
13+
- Non-root runtime using `gosu`
14+
- Supports custom server configuration files
15+
16+
## Docker Compose Example
17+
```yaml
18+
services:
19+
ut2004:
20+
image: lancommander/ut2004:latest
21+
container_name: ut2004-server
22+
23+
# UT2004 uses UDP for game, query, and beacon ports
24+
ports:
25+
- "7777:7777/udp" # Game port
26+
- "7778:7778/udp" # Query port
27+
- "7779:7779/udp" # Beacon port
28+
29+
# Bind mounts so files appear on the host
30+
volumes:
31+
- ./config:/config
32+
33+
environment:
34+
# Optional overrides
35+
# SERVER_PORT: 7777
36+
# SERVER_ARGS: 'CTF-Face?Game=XGame.xCTFGame?MaxPlayers=16'
37+
38+
# Ensure container restarts if the server crashes or host reboots
39+
restart: unless-stopped
40+
```
41+
42+
---
43+
44+
## Directory Layout (Host)
45+
46+
```text
47+
.
48+
├── config/
49+
│ ├── ut-server/ # Game assets (auto-downloaded on first startup)
50+
│ │ ├── ucc-bin
51+
│ │ ├── System/
52+
│ │ └── ...
53+
│ ├── .assets-downloaded # Marker file to track downloads
54+
│ ├── UT2004.ini
55+
│ ├── Default.ini
56+
│ └── User.ini
57+
```
58+
59+
The `config` directory **must be writable** by Docker. The `ut-server` directory and its contents are automatically downloaded and extracted on first startup.
60+
61+
---
62+
63+
## Configuration
64+
65+
UT2004 server configuration files should be placed in `/config`:
66+
67+
- `UT2004.ini` - Main server configuration
68+
- `Default.ini` - Default game settings
69+
- `User.ini` - User-specific settings
70+
71+
The server will use these configuration files if they exist. You can customize server settings, game modes, maps, and other options in these files.
72+
73+
Example server configuration in `UT2004.ini`:
74+
```ini
75+
[Engine.GameInfo]
76+
ServerName=My UT2004 Server
77+
MaxPlayers=16
78+
GamePassword=
79+
AdminPassword=changeme
80+
```
81+
82+
---
83+
84+
## Environment Variables
85+
86+
| Variable | Description | Default |
87+
|--------|-------------|---------|
88+
| `SERVER_PORT` | UDP port the server listens on (game port) | `7777` |
89+
| `SERVER_ARGS` | Map and game type arguments (see below) | *(empty - uses default: DM-Rankin)* |
90+
| `UT2004_DOWNLOAD_URL` | URL to download game assets from | `https://s3.amazonaws.com/ut2004-files/dedicated-server-3339-bonuspack.tar.gz` |
91+
92+
### `SERVER_ARGS`
93+
94+
If `SERVER_ARGS` is not set, the server will use the default map `DM-Rankin` with DeathMatch game type.
95+
96+
To customize the map and game type, set `SERVER_ARGS` with the map name and options. The format is: `<MapName>?Game=<GameType>?<Options>`
97+
98+
Common examples:
99+
100+
```bash
101+
# Capture the Flag on Face map
102+
SERVER_ARGS="CTF-Face?Game=XGame.xCTFGame?MaxPlayers=16"
103+
104+
# DeathMatch on Rankin map (default)
105+
SERVER_ARGS="DM-Rankin?Game=XGame.xDeathMatch?MaxPlayers=8"
106+
107+
# Team DeathMatch
108+
SERVER_ARGS="DM-Rankin?Game=XGame.xTeamGame?MaxPlayers=16"
109+
110+
# Onslaught mode
111+
SERVER_ARGS="ONS-Torlan?Game=Onslaught.ONSOnslaughtGame?MaxPlayers=16"
112+
```
113+
114+
---
115+
116+
## Running the Server
117+
### Basic run (recommended)
118+
```bash
119+
mkdir -p config
120+
chmod -R 777 config
121+
122+
docker run --rm -it \
123+
-p 7777:7777/udp \
124+
-p 7778:7778/udp \
125+
-p 7779:7779/udp \
126+
-v "$(pwd)/config:/config" \
127+
lancommander/ut2004:latest
128+
```
129+
130+
### With custom server arguments
131+
```bash
132+
docker run --rm -it \
133+
-p 7777:7777/udp \
134+
-p 7778:7778/udp \
135+
-p 7779:7779/udp \
136+
-v "$(pwd)/config:/config" \
137+
-e SERVER_ARGS="CTF-Face?Game=XGame.xCTFGame?MaxPlayers=16" \
138+
lancommander/ut2004:latest
139+
```
140+
141+
## Ports
142+
- **UDP 7777** – Game port (default)
143+
- **UDP 7778** – Query port (for server browser)
144+
- **UDP 7779** – Beacon port (for server discovery)
145+
146+
## Asset Download
147+
148+
On first startup, the container will automatically download the UT2004 dedicated server assets from the configured URL. The download is tracked using a marker file, so subsequent container restarts will skip the download if the assets are already present.
149+
150+
## License
151+
Unreal Tournament 2004 is distributed under its own license.
152+
This repository contains only Docker build logic and helper scripts licensed under MIT.

0 commit comments

Comments
 (0)