From 649e2f0663cb1fd48ca9a6865c82c26ec0ca8182 Mon Sep 17 00:00:00 2001 From: openhands Date: Mon, 7 Sep 2026 11:44:52 +0200 Subject: [PATCH] feat(docker): self-contained runtime dirs, image healthcheck, spec-compliant Dockerfile - Create the runtime write targets (/app/storage, /app/public/nitro-assets, /app/public/swf, /var/www/Gamedata) owned by UID/GID 33 in the runner image so running without the bound volumes no longer hits ENOENT. - Bake a HEALTHCHECK into the image so `docker run` (ci-deploy.sh) also reports Docker-level health; compose can still override it with its own probe. - Add the dockerfile:1 syntax pragma and ignore non-pnpm lockfiles so a stray package-lock.json/yarn.lock can never taint the build context. --- .dockerignore | 6 ++++++ Dockerfile | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.dockerignore b/.dockerignore index e38d7e3c..82c21570 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,6 +7,12 @@ storage prod.log update.log .pm2 +# Only the pnpm lockfile is used. Ignore other lockfile formats and stray +# package managers so they never taint the build context by accident. +package-lock.json +yarn.lock +bun.lockb +.npmrc.bak # NOTE: .env is intentionally NOT ignored here — the build loads it (only inside # a build RUN layer) to produce NEXT_PUBLIC_* + validated build-time values. # It is not copied into the runtime image (the runner stage copies only diff --git a/Dockerfile b/Dockerfile index 4c9139a4..fca700b2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,4 @@ +# syntax=docker/dockerfile:1 # node:alpine = latest Node within the supported LTS major (tracks the newest # patch automatically; currently v26.x, which satisfies package.json's # engines ">=26.8.1 <27"). @@ -31,11 +32,17 @@ ENV NODE_ENV=production \ PORT=3002 \ HOSTNAME=0.0.0.0 RUN apk add --no-cache tini \ - && addgroup -g 33 -S nextjs && adduser -u 33 -S -G nextjs nextjs + && addgroup -g 33 -S nextjs && adduser -u 33 -S -G nextjs nextjs \ + && mkdir -p /app/storage /app/public/nitro-assets /app/public/swf /var/www/Gamedata \ + && chown -R 33:33 /app/storage /app/public /var/www/Gamedata COPY --from=builder --chown=nextjs:nextjs /app/public ./public COPY --from=builder --chown=nextjs:nextjs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nextjs /app/.next/static ./.next/static USER nextjs EXPOSE 3002 +# Self-contained healthcheck so `docker run` (ci-deploy) also gets Docker-level +# health; docker-compose overrides this with its own probe if needed. +HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \ + CMD ["node", "-e", "fetch('http://127.0.0.1:'+(process.env.PORT||'3002')+'/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"] ENTRYPOINT ["/sbin/tini", "--"] CMD ["node", "server.js"] \ No newline at end of file