Fix: HLDS Docker Container Exits Immediately

August 13, 2025 Daemon666 8 min read 239 Aufrufe

You run docker compose up for your CS 1.6 server and the container immediately exits — docker ps shows nothing, docker ps -a shows it Exited (1) or Exited (0) seconds after start. A container lives only as long as its foreground process, so an HLDS container that dies instantly means hlds_run either crashed on startup or ran, printed, and returned. Here is how to find which and fix it.

1. Read the actual exit reason first

Do not guess — get the container's own output:

docker compose logs --tail=50 hlds
docker ps -a

The last lines before exit are the real error. An Exited (0) usually means the process ran to completion (missing map, backgrounded); a non-zero code means a crash or a failed exec. Everything below is about interpreting those lines.

2. Provide the 32-bit runtime

HLDS and ReHLDS binaries are 32-bit. On a 64-bit base image without i386 libraries, the loader cannot even start the binary and the container dies instantly with something like:

./hlds_linux: No such file or directory

— a misleading message that actually means the 32-bit loader is missing. In your Dockerfile (Debian/Ubuntu base) enable i386 and install the libs:

RUN dpkg --add-architecture i386 \
 && apt-get update \
 && apt-get install -y libc6:i386 libstdc++6:i386 lib32gcc-s1

If it then complains specifically about libstdc++.so.6 or libm.so.6, see the shared-library fix — same root cause, missing 32-bit dependency.

3. Run in the foreground, not the launcher's background mode

The default hlds_run wrapper monitors and restarts the real binary, which can confuse Docker's single-process model. Point the container's command at a start that stays in the foreground and does not detach. A working compose command line is explicit:

command: >-
  ./hlds_run -game cstrike -console -nomaster
  +ip 0.0.0.0 +port 27015
  +map de_dust2 +maxplayers 20

Two flags matter for containers: -console keeps output on stdout (so docker logs sees it and the process does not expect a tty), and a valid +map is mandatory. Without +map, HLDS prints Host_Error: Couldn't spawn server or exits cleanly having nothing to run.

4. Give it a real map and maxplayers

A container that exits 0 with no crash almost always lacks a startup map, or was told to run a launcher that forks and returns. The engine needs +map <name> pointing at a BSP that exists in cstrike/maps/, plus a sane +maxplayers. Confirm the map is actually in the image:

docker compose run --rm hlds ls cstrike/maps/de_dust2.bsp

If that path is missing, your volume mount or COPY left the game files out — the binary starts, finds no map, and returns.

5. Keep it attached with tty when needed

Some builds of the launcher expect an interactive terminal and exit when they do not get one. In compose, grant a pseudo-TTY and keep stdin open:

tty: true
stdin_open: true
restart: unless-stopped

restart: unless-stopped also stops a transient failure from leaving the container dead, but do not use it to paper over a real crash — fix the underlying error first or you get a container that restart-loops forever.

A useful debugging trick is to bypass the entrypoint entirely and get a shell inside the image, so you can run the binary by hand and read its raw output:

docker compose run --rm --entrypoint bash hlds
# then, inside:
./hlds_run -game cstrike -console +map de_dust2 +maxplayers 20

Running it interactively shows the crash line the daemon would otherwise swallow, which is far faster than reading exit codes and guessing.

Common errors

  • ./hlds_linux: No such file or directory on a file that exists — missing 32-bit loader. Install libc6:i386 and friends.
  • Exited (0) immediately — no +map, or the map BSP is not in the image. Add a valid startup map.
  • Host_Error: Couldn't spawn server — bad or missing map name.
  • Container runs but nothing in logs — missing -console; output is going to a tty the daemon cannot read.
  • Restart-loops foreverrestart: unless-stopped masking a startup crash. Read docker compose logs and fix the real error.

Verification

Start it and confirm the process stays up:

docker compose up -d hlds
docker ps
docker compose logs --tail=20 hlds

docker ps should list the container as Up, and the logs should end with the server reaching a map and printing its ready banner rather than a Host_Error. Query the port from the host to confirm it answers, then connect a client. If it stays up but no one can join, that is a networking/port-forward issue, not a startup crash — a different problem from the one this fixes.

Mitwirkende: Daemon666 ✦
Teilen: