Skip to content

fix(docker): make deploy/docker/Dockerfile actually build and run#8

Open
prenansantana wants to merge 2 commits into
tinykit-studio:mainfrom
prenansantana:fix/dockerfile-postinstall-missing-scripts
Open

fix(docker): make deploy/docker/Dockerfile actually build and run#8
prenansantana wants to merge 2 commits into
tinykit-studio:mainfrom
prenansantana:fix/dockerfile-postinstall-missing-scripts

Conversation

@prenansantana
Copy link
Copy Markdown

@prenansantana prenansantana commented May 12, 2026

Summary

Two independent bugs in deploy/docker/Dockerfile block every Docker deploy from this file (and any PaaS that builds from it — Coolify, Railway-via-Dockerfile, etc). Both fixes together are needed to get a usable image.

Bug 1 — npm ci fails because postinstall can't find its script

The Dockerfile copies only package*.json before running npm ci, but the postinstall hook executes node scripts/download-pocketbase.js. At that point scripts/ is not in the image, so npm aborts:

```

tinykit@0.1.0 postinstall
svelte-kit sync && node scripts/download-pocketbase.js

Missing Svelte config file in /app — skipping
Error: Cannot find module '/app/scripts/download-pocketbase.js'
```

Fix: copy scripts/ before npm ci.

Bug 2 — container crash-loops with ./start.sh: not found

deploy/railway/start.sh has a #!/bin/bash shebang and uses bash-specific syntax ({1..30} brace expansion, wait -n), plus calls curl to wait for PocketBase to become healthy. node:20-alpine ships neither bash nor curl, so the container fails immediately at runtime:

```
/usr/local/bin/docker-entrypoint.sh: exec: line 11: ./start.sh: not found
```

This message is misleading — the file exists and is executable. The error is ENOENT on the shebang interpreter (/bin/bash).

Switching the shebang to #!/bin/sh is not viable because BusyBox sh doesn't support the bash features the script uses.

Fix: install bash and curl via apk.

Diff

```diff
FROM node:20-alpine

+RUN apk add --no-cache bash curl
+
WORKDIR /app

Install dependencies

COPY package*.json ./
+COPY scripts ./scripts
RUN npm ci --production=false
```

Verified

Built and ran the image locally on linux/arm64. Container starts cleanly:

```
Starting tinykit...
Starting Pocketbase...
Pocketbase is ready!
Superuser ready!
Starting SvelteKit server...
Listening on http://0.0.0.0:3000
```

GET /tinykit → HTTP 200.

Test plan

  • docker build -f deploy/docker/Dockerfile -t tinykit . completes
  • Container starts without entering a restart loop
  • GET /tinykit returns 200

The Dockerfile copies only package*.json before running `npm ci`, but
the postinstall hook executes `node scripts/download-pocketbase.js`.
Since scripts/ has not been copied yet, npm ci fails with
MODULE_NOT_FOUND and the build aborts.

Copy scripts/ before npm ci so postinstall succeeds. The rest of the
source is still copied afterward to preserve layer caching for the
dependency install step.
start.sh has a #!/bin/bash shebang and uses bash-specific syntax
({1..30} brace expansion and `wait -n`), plus calls curl to wait
for PocketBase health. The node:20-alpine base image ships neither
bash nor curl, so the container fails immediately at runtime with
"./start.sh: not found" (ENOENT on the shebang interpreter).

Install bash and curl via apk so start.sh runs as authored.
@prenansantana prenansantana changed the title fix(docker): copy scripts/ before npm ci so postinstall can run fix(docker): make deploy/docker/Dockerfile actually build and run May 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant