With a lot of recent news Coolify has gained some traction. Coolify is like your own Netlify or Vercel. It handles a lot of (not all) devOps for you.
I have set up my own server and begun deploying with their UI using a private repo with Github Apps. During deployment, I had to choose between nixpack, dockerfile or docker compose. I created my own nixpack.toml but when deploying with it, I encountered ‘Bad Gateway’ and function issues on my deployed site.
So I made the change to Dockerfile, since at least there is some documentation on this experimental feature. Of note is that this project uses the server file. So here’s where I’m at and I think close to deploying successfully with Coolify.
- Run yarn rw experimental setup-docker
- Not using the compose files for deployment, but rather choose the Dockerfile build option in Coolify
- Edit the Dockerfile (path changes and adding .yarn/releases as well as the the server.js command)
# base
# ----
FROM node:20-bookworm-slim as base
RUN corepack enable
# We tried to make the Dockerfile as lean as possible. In some cases, that means we excluded a dependency your project needs.
# By far the most common is Python. If you're running into build errors because `python3` isn't available,
# uncomment the line below here and in other stages as necessary:
RUN apt-get update && apt-get install -y \
openssl \
# python3 make gcc \
&& rm -rf /var/lib/apt/lists/*
USER node
WORKDIR /app
COPY --chown=node:node .yarn/releases .yarn/releases
COPY --chown=node:node .yarnrc.yml .
COPY --chown=node:node package.json .
COPY --chown=node:node api/package.json api/
COPY --chown=node:node web/package.json web/
COPY --chown=node:node yarn.lock .
RUN mkdir -p /app/.yarn/berry/index
RUN mkdir -p /app/.cache
RUN --mount=type=cache,target=/app/.yarn/berry/cache,uid=1000 \
--mount=type=cache,target=/app/.cache,uid=1000 \
CI=1 yarn install
COPY --chown=node:node redwood.toml .
COPY --chown=node:node graphql.config.js .
# api build
# ---------
FROM base as api_build
# If your api side build relies on build-time environment variables,
# specify them here as ARGs. (But don't put secrets in your Dockerfile!)
#
# ARG MY_BUILD_TIME_ENV_VAR
COPY --chown=node:node api api
RUN yarn rw build api
# web prerender build
# -------------------
FROM api_build as web_build_with_prerender
COPY --chown=node:node web web
RUN yarn rw build web
# web build
# ---------
FROM base as web_build
COPY --chown=node:node web web
RUN yarn rw build web --no-prerender
# api serve
# ---------
FROM node:20-bookworm-slim as api_serve
RUN corepack enable
RUN apt-get update && apt-get install -y \
openssl \
# python3 make gcc \
&& rm -rf /var/lib/apt/lists/*
USER node
WORKDIR /app
COPY --chown=node:node .yarnrc.yml .
COPY --chown=node:node package.json .
COPY --chown=node:node api/package.json api/
COPY --chown=node:node yarn.lock .
RUN mkdir -p /app/.yarn/berry/index
RUN mkdir -p /app/.cache
RUN --mount=type=cache,target=/app/.yarn/berry/cache,uid=1000 \
--mount=type=cache,target=/app/.cache,uid=1000 \
CI=1 yarn workspaces focus api --production
COPY --chown=node:node redwood.toml .
COPY --chown=node:node graphql.config.js .
COPY --chown=node:node --from=api_build /app/api/dist /app/api/dist
COPY --chown=node:node --from=api_build /app/api/db /app/api/db
COPY --chown=node:node --from=api_build /app/node_modules/.prisma /app/node_modules/.prisma
ENV NODE_ENV=production
# default api serve command
# ---------
# If you are using a custom server file, you must use the following
# command to launch your server instead of the default api-server below.
# This is important if you intend to configure GraphQL to use Realtime.
#
CMD [ "./api/dist/server.js" ]
# CMD [ "node_modules/.bin/rw-server", "api" ]
# web serve
# ---------
FROM node:20-bookworm-slim as web_serve
RUN corepack enable
USER node
WORKDIR /app
COPY --chown=node:node .yarnrc.yml .
COPY --chown=node:node package.json .
COPY --chown=node:node web/package.json web/
COPY --chown=node:node yarn.lock .
RUN mkdir -p /app/.yarn/berry/index
RUN mkdir -p /app/.cache
RUN --mount=type=cache,target=/app/.yarn/berry/cache,uid=1000 \
--mount=type=cache,target=/app/.cache,uid=1000 \
CI=1 yarn workspaces focus web --production
COPY --chown=node:node redwood.toml .
COPY --chown=node:node graphql.config.js .
COPY --chown=node:node --from=web_build /app/web/dist /app/web/dist
ENV NODE_ENV=production \
API_PROXY_TARGET=http://api:8911
# We use the shell form here for variable expansion.
CMD "node_modules/.bin/rw-web-server" "--api-proxy-target" "$API_PROXY_TARGET"
# console
# -------
FROM base as console
# To add more packages:
#
# ```
# USER node
#
# RUN apt-get update && apt-get install -y \
# curl
#
# USER node
# ```
COPY --chown=node:node api api
COPY --chown=node:node web web
COPY --chown=node:node scripts scripts
- Disable the healthcheck in Coolify, since we’re using Docker (apparently you’d need to use curl/wget to make it work but I’m not bothering with that just yet, it’s not necessary for deployment to work)
- Add 8911, 8910 under Ports exposed for the app in Coolify
- Hit deploy in Coolify
Here is where I encountered some issues with the standard Dockerfile. I had to change the path to /app because when Coolify deploys a project it does not create it under /home. That seemed to fix it and it didn’t throw errors. Then I had issues with yarn install, so I had to copy the /releases folder. Now the deploy logs show everything building but it hangs up on this step (Coolify deploy log output):
[COMMAND] docker exec r8084wk bash -c 'bash /artifacts/build.sh'
[OUTPUT]
#18 59.69 ➤ YN0007: │ @prisma/engines@npm:5.2.0 must be built because it never has been before or the last one failed
[COMMAND] docker exec r8084wk bash -c 'bash /artifacts/build.sh'
[OUTPUT]
#18 59.69 ➤ YN0007: │ core-js@npm:3.37.1 must be built because it never has been before or the last one failed
#18 59.69 ➤ YN0007: │ esbuild@npm:0.21.3 must be built because it never has been before or the last one failed
#18 59.69 ➤ YN0007: │ core-js-pure@npm:3.37.1 must be built because it never has been before or the last one failed
#18 59.70 ➤ YN0007: │ better-sqlite3@npm:8.6.0 must be built because it never has been before or the last one failed
#18 59.70 ➤ YN0007: │ @prisma/engines@npm:4.16.2 must be built because it never has been before or the last one failed
#18 59.70 ➤ YN0007: │ msw@npm:1.3.3 [1ea41] must be built because it never has been before or the last one failed
#18 59.70 ➤ YN0007: │ @prisma/client@npm:5.14.0 [dc82c] must be built because it never has been before or the last one failed
#18 59.70 ➤ YN0007: │ esbuild@npm:0.18.20 must be built because it never has been before or the last one failed
#18 59.70 ➤ YN0007: │ @swc/core@npm:1.6.3 [6b6bb] must be built because it never has been before or the last one failed
#18 59.70 ➤ YN0007: │ @prisma/engines@npm:5.14.0 must be built because it never has been before or the last one failed
[COMMAND] docker exec r8084wk bash -c 'bash /artifacts/build.sh'
[OUTPUT]
#18 67.53 ➤ YN0000: │ @prisma/client@npm:5.14.0 [dc82c] STDERR prisma:warn We could not find your Prisma schema in the default locations (see: https://pris.ly/d/prisma-schema-location.
#18 67.53 ➤ YN0000: │ @prisma/client@npm:5.14.0 [dc82c] STDERR If you have a Prisma schema file in a custom path, you will need to run
#18 67.53 ➤ YN0000: │ @prisma/client@npm:5.14.0 [dc82c] STDERR `prisma generate --schema=./path/to/your/schema.prisma` to generate Prisma Client.
[COMMAND] docker exec r8084wk bash -c 'bash /artifacts/build.sh'
[OUTPUT]
#18 67.53 ➤ YN0000: │ @prisma/client@npm:5.14.0 [dc82c] STDERR If you do not have a Prisma schema file yet, you can ignore this message.
#18 67.53 ➤ YN0000: │ @prisma/client@npm:5.14.0 [dc82c] STDOUT
[COMMAND] docker exec r8084wk bash -c 'bash /artifacts/build.sh'
[OUTPUT]
#18 69.49 ➤ YN0007: │ prisma@npm:5.14.0 must be built because it never has been before or the last one failed
[COMMAND] docker exec r8084wk bash -c 'bash /artifacts/build.sh'
[OUTPUT]
#18 70.03 ➤ YN0000: └ Completed in 37s 493ms
[COMMAND] docker exec r8084wk bash -c 'bash /artifacts/build.sh'
[OUTPUT]
#18 71.04 ➤ YN0000: · Done with warnings in 1m 10s
I looked at the Dockerfile and it’s clearly copying the db folder:
COPY --chown=node:node --from=api_build /app/api/db /app/api/db
I have not deleted my migrations folder prior to deployment or ran migrate dev as a post-deployment task. I think the issue first is why the schema can’t be found? This ultimately breaks my deployment. Also I’m running Coolify as root, but I see the Dockerfile uses the node user. I don’t see an error regarding this but would I need to create this user first?
Any ideas would be highly appreciated.