I try to figure out why drizzle can not connect to the database file. When I ssh
into the container I can see that the file is in place. Drizzle migrations found it with the same env variable and migrations have no issues. I tried also file:/litefs/sqlite.db
. The environment variable is set with secrets.
INFO Starting clean up
INFO Umounting /dev/vdc from /data
WARN could not unmount /rootfs: EINVAL: Invalid argument
[92.989536] reboot: Restarting system
Firecracker v1.12.1 starting
Listening on API socket "/fc.sock"
INFO Starting init (commit: a570442)...
INFO Checking filesystem on /data
/dev/vdc: clean, 19/64512 files, 8817/258048 blocks
INFO Mounting /dev/vdc at /data (uid=0, gid=0, chmod=0755)
INFO Resized /data to 1056964608 bytes
INFO Preparing to run: `litefs mount` as root
INFO [fly api proxy] listening at /.fly/api
LiteFS v0.5.14, commit=a51e72d...
config file read from /etc/litefs.yml
INFO host environment detected (fly.io)
INFO no backup client configured, skipping
INFO Using Consul to determine primary
INFO initializing consul
INFO wal-sync: no wal file exists on "sqlite.db", skipping sync
INFO using existing cluster id: LFSC38943094791DD683
INFO LiteFS mounted to: /litefs
INFO http server listening on: http://localhost:20202
INFO waiting to connect to cluster
INFO primary lease acquired, advertising as http://6839146a7d9008.vm.leihzeit.internal:20202
INFO connected to cluster, ready
INFO node is a candidate, automatically promoting to primary
INFO node is already primary, skipping promotion
INFO proxy server listening on: http://localhost:3000
INFO executing command: npx drizzle-kit migrate
INFO SSH listening on [fdaa:a:2efc:a7b:479:50ad:c758:2]:22
INFO Reading config file '/app/drizzle.config.ts'
INFO No config path provided, using default
[✓] migrations applied successfully
INFO starting background subprocess: npm [start]
waiting for signal or subprocess to exit
> start
> react-router-serve ./build/server/index.js
DATABASE_URL file:///litefs/sqlite.db
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
/app/node_modules/better-sqlite3/lib/database.js:65
throw new TypeError('Cannot open database because the directory does not exist');
TypeError: Cannot open database because the directory does not exist
at new Database (/app/node_modules/better-sqlite3/lib/database.js:65:9)
at drizzle (file:///app/node_modules/src/better-sqlite3/driver.ts:94:61)
at file:///app/build/server/assets/server-build-CcpnzTgH.js:220:12
at ModuleJob.run (node:internal/modules/esm/module_job:274:25)
at onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:644:26)
at run (/app/node_modules/@react-router/serve/dist/cli.js:80:15)
subprocess exited with error code 1, litefs shutting down
INFO exiting primary, destroying lease
litefs shut down complete
INFO Main child exited normally with code: 1
I also logged DATABASE_URL in the server side file and the file path looks good.
My Dockerfile:
FROM node:22-alpine AS development-dependencies-env
WORKDIR /app
COPY . .
RUN npm ci
FROM node:22-alpine AS production-dependencies-env
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
FROM node:22-alpine AS build-env
WORKDIR /app
COPY . .
COPY --from=development-dependencies-env /app/node_modules /app/node_modules
RUN npm run build
COPY drizzle ./drizzle
COPY drizzle.config.ts ./drizzle.config.ts
# Stage 4: Final runtime with LiteFS
FROM alpine AS runtime
WORKDIR /app
ARG LITEFS_CONFIG=litefs.yml
# Install runtime dependencies
RUN apk add --no-cache nodejs npm bash fuse3 sqlite ca-certificates curl
# Copy LiteFS binary
COPY --from=flyio/litefs:0.5 /usr/local/bin/litefs /usr/local/bin/litefs
# Copy production node_modules + built app + generated Drizzle client
COPY package.json package-lock.json ./
COPY drizzle.config.ts ./drizzle.config.ts
COPY --from=production-dependencies-env /app/node_modules /app/node_modules
COPY --from=build-env /app/build /app/build
COPY --from=build-env /app/drizzle /app/drizzle
# Copy LiteFS config
COPY litefs.yml /etc/litefs.yml
# Set LiteFS as the entrypoint
# It will mount the filesystem, then exec ["npm","run","start"] as defined in litefs.yml
ENTRYPOINT ["litefs", "mount"]
My litefs.yml
fuse:
# Required. This is the mount directory that applications will
# use to access their SQLite databases.
dir: "/litefs"
data:
# Path to internal data storage.
dir: "/data/litefs"
proxy:
# matches the internal_port in fly.toml
addr: ":3000"
target: "localhost:3001"
db: "sqlite.db"
# The lease section specifies how the cluster will be managed. We're using the
# "consul" lease type so that our application can dynamically change the primary.
#
# These environment variables will be available in your Fly.io application.
lease:
type: "consul"
candidate: ${FLY_REGION == PRIMARY_REGION}
promote: true
advertise-url: "http://${HOSTNAME}.vm.${FLY_APP_NAME}.internal:20202"
consul:
url: "${FLY_CONSUL_URL}"
key: "litefs/${FLY_APP_NAME}"
exec:
- cmd: npx drizzle-kit migrate
if-candidate: true
- cmd: npm start