# Build Shulker without modifying the submodule; run as non-root; persist config and read logs via volumes FROM node:22-alpine AS build WORKDIR /app # Enable corepack so yarn is available (Node 18+) RUN corepack enable # Copy only dependency manifests first for better layer caching COPY external/shulker/package.json external/shulker/yarn.lock ./external/shulker/ WORKDIR /app/external/shulker # Install dependencies RUN yarn install --frozen-lockfile || yarn install # Copy source and build COPY external/shulker/ /app/external/shulker/ RUN yarn build FROM node:22-alpine WORKDIR /app # Copy built app from builder COPY --from=build /app/external/shulker /app # Prepare runtime directories and non-root user RUN adduser -D -h /app -u 10001 shulker \ && mkdir -p /data /minecraft/logs \ && chown -R shulker:shulker /app /data /minecraft # Copy entrypoint COPY docker/shulker/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh # Install helpful runtime tools RUN apk add --no-cache jq su-exec # Start as root to allow entrypoint to chown mounted volumes, then drop to non-root USER root # Shulker default port EXPOSE 8000 # Volumes: /data holds config.json, /minecraft/logs maps to the server logs VOLUME ["/data", "/minecraft/logs"] ENTRYPOINT ["/entrypoint.sh"] CMD ["node", "build/index.js"]