SpaceCities / Dockerfile
Almaatla's picture
Claude Sonnet 5
T-006: Dockerfile for HF Docker Spaces
fdb0167 unverified
Raw History Blame Contribute Delete
2.22 kB
# syntax=docker/dockerfile:1
# SpaceCities on Hugging Face Docker Spaces.
# Docs: https://huggingface.co/docs/hub/spaces-sdks-docker
#
# Zero npm dependencies, ES modules, no build step β€” this Dockerfile has no
# `npm install` because there is nothing to install (see package.json).
#
# PHASE 0: the CMD below serves the existing single-player game through
# tools/serve.js, the zero-dependency static server already in this repo.
# Multiplayer (TASKS.md Phase 1+) replaces the CMD with the real match
# server once it exists; nothing else in this file needs to change for that β€”
# the port, the user, and the /data mount point are already right.
FROM node:22-slim
# HF requires the container to run as UID 1000. node:* images already ship a
# `node` user at UID/GID 1000 (verified against the upstream Dockerfile:
# https://github.com/nodejs/docker-node/blob/main/22/bookworm-slim/Dockerfile),
# so do NOT `RUN useradd -m -u 1000 user` here the way HF's own Python example
# does (https://huggingface.co/docs/hub/spaces-sdks-docker#permissions) β€” that
# fails with "UID 1000 is not unique". The built-in `node` user already
# satisfies the requirement; the constraint HF states is the UID, not the name.
ENV NODE_ENV=production \
PORT=7860 \
DATA_DIR=/data
# /data is the runtime mount point for an attached HF Storage Bucket. It is
# NOT available during build ("the /data volume is only available at
# runtime"), so this only creates the mount point and hands it to the runtime
# user. Never write here during build β€” it would land in the image layer and
# then be shadowed by the real mount at container start.
RUN mkdir -p /data && chown node:node /data
WORKDIR /home/node/app
# --chown avoids a separate recursive chown layer on the whole tree.
COPY --chown=node:node . .
USER node
# The Space's README.md `app_port` must match this β€” see the front matter
# there. EXPOSE itself is documentation only; HF routes by app_port.
EXPOSE 7860
# Phase 0: serve the existing single-player game as static ES modules.
# tools/serve.js already reads PORT from the environment and binds all
# interfaces, so no server change was needed to satisfy the HF contract.
CMD ["node", "tools/serve.js"]