I’m developing a remix app with litefs support on the backend. During heavy development prior to full-fledged launch, I prefer to be able to modify my db migrations at will and blow away the database on each deploy. But with the new support for litefs, I’m having a bit more trouble figuring out how to reset the db during deploy. I tried modifying my Dockerfile as follows:
# remove this line after launch
RUN npx prisma db push --force-reset && npx prisma db push
# replace it with this line after launch
# RUN npx prisma generate
But when I deploy, I get the following error:
migrate found failed migrations in the target database, new migrations will not be applied. Read more about how to resolve migration issues in a production database: https://pris.ly/d/migrate-resolve
Thanks. Any chance you could help me to adapt that to my CI/CD pipeline? Here is my Dockerfile:
# base node image
FROM node:18-bullseye-slim as base
# set for base and all layer that inherit from it
ENV NODE_ENV production
# Install openssl for Prisma
RUN apt-get update && apt-get install -y fuse3 openssl sqlite3 ca-certificates
# Install all node_modules, including dev dependencies
FROM base as deps
WORKDIR /myapp
ADD package.json package-lock.json .npmrc ./
RUN npm install --include=dev
# Setup production node_modules
FROM base as production-deps
WORKDIR /myapp
COPY --from=deps /myapp/node_modules /myapp/node_modules
ADD package.json package-lock.json .npmrc ./
RUN npm prune --omit=dev
# Build the app
FROM base as build
WORKDIR /myapp
COPY --from=deps /myapp/node_modules /myapp/node_modules
ADD prisma .
RUN npx prisma generate
ADD . .
RUN npm run build
# Finally, build the production image with minimal footprint
FROM base
ENV FLY="true"
ENV LITEFS_DIR="/litefs/data"
ENV DATABASE_FILENAME="sqlite.db"
ENV DATABASE_PATH="$LITEFS_DIR/$DATABASE_FILENAME"
ENV DATABASE_URL="file:$DATABASE_PATH"
ENV CACHE_DATABASE_FILENAME="cache.db"
ENV CACHE_DATABASE_PATH="/$LITEFS_DIR/$CACHE_DATABASE_FILENAME"
ENV INTERNAL_PORT="8080"
ENV PORT="8081"
ENV NODE_ENV="production"
# add shortcut for connecting to database CLI
RUN echo "#!/bin/sh\nset -x\nsqlite3 \$DATABASE_URL" > /usr/local/bin/database-cli && chmod +x /usr/local/bin/database-cli
WORKDIR /myapp
COPY --from=production-deps /myapp/node_modules /myapp/node_modules
COPY --from=build /myapp/node_modules/.prisma /myapp/node_modules/.prisma
COPY --from=build /myapp/server-build /myapp/server-build
COPY --from=build /myapp/build /myapp/build
COPY --from=build /myapp/public /myapp/public
COPY --from=build /myapp/package.json /myapp/package.json
COPY --from=build /myapp/prisma /myapp/prisma
# prepare for litefs
COPY --from=flyio/litefs:0.4.0 /usr/local/bin/litefs /usr/local/bin/litefs
ADD other/litefs.yml /etc/litefs.yml
RUN mkdir -p /data ${LITEFS_DIR}
ADD . .
CMD ["litefs", "mount"]
It seems like litefs is only mounted long after the migrations are run, so I’m not exactly sure how to implement your advice.
Are you using litefs’ built-in supervision to launch your app? If so, have you tried incorporating the rm into your startup sequence/script? Assuming so, but could you please include your litefs configuration so we can take a look?
Alternately, maybe you can work the rm into your CMD and remove the local database before litefs mount?
Disclosure: I know next to nothing about litefs–mainly spitballing ideas in hopes that something helps you out.
Thanks, @nolan-fly. The command that starts with npx prisma generate will fail if there is already a database with stale migrations in it, so I think something needs to be done earlier on. Not sure what though.
The npx prisma generate command is run while building the image so there’s no LiteFS running. Is it building the schema against a regular SQLite file on the image instead?
That is my assumption, but I’m not that familiar with this project. It is a set of sensible defaults built by Kent C Dodds. I’m still trying to figure it out.
Yeah, I don’t know a whole lot about Prisma (or Litefs for that matter so take this all with a grain of salt) but I suspect something’s generating a database in your image, and that database is out of sync with what you get on the volume, which is only available when the image is launched.
If indeed the generate command will fail if there’s no database, then my advice above still likely holds. You may be generating the schema based on a database shipped in the image, then migrating that against an older database in the volume. In this case I’d assume removing the database in the entrypoint or litefs supervision stage should still be fine since that database wasn’t available during the build to begin with.