Skip to content

ci: build and publish Docker image to GHCR#19

Open
rafaelreis-r wants to merge 1 commit intoviperrcrypto:mainfrom
rafaelreis-r:pr/docker-ghcr-upstream
Open

ci: build and publish Docker image to GHCR#19
rafaelreis-r wants to merge 1 commit intoviperrcrypto:mainfrom
rafaelreis-r:pr/docker-ghcr-upstream

Conversation

@rafaelreis-r
Copy link

Adds a GitHub Actions workflow to build multi-arch Docker images using the existing docker/Dockerfile.

  • PRs: build only (no publish)
  • main/tags: build + publish to GHCR (ghcr.io//) using GITHUB_TOKEN
  • Produces linux/amd64 + linux/arm64

No secrets required; uses GitHub Packages + GITHUB_TOKEN.

@xiaoyao9184
Copy link

There is already a published image in #19, but the current Dockerfile still has several issues:

  • prisma is in devDependencies but is not installed in the production image, which leads to missing Prisma CLI at runtime.

    Siftly/docker/Dockerfile

    Lines 28 to 31 in 61e7bde

    RUN npm ci --omit=dev
    # Re-generate Prisma client in runner stage
    RUN node_modules/.bin/prisma generate

  • better-sqlite3 does not need to be built from source. npm ci will not build it from source in this case, so that step is unnecessary.

    # Native module build deps (required by better-sqlite3)
    RUN apk add --no-cache python3 make g++

  • this is a very dangerous operation:

    COPY . .

    It may copy existing node_modules from the host into the image.

    I tried to fix the missing Prisma CLI by using:

    COPY --from=builder /app/node_modules ./node_modules

    but this caused environment pollution.

    A better approach is to add a .dockerignore file to exclude node_modules. This will also speed up the build process.

Here is a complete working example of a Dockerfile:

dockerfile

# ── builder ───────────────────────────────────────────────────────────────────
FROM node:22-alpine AS builder
WORKDIR /app

COPY package*.json ./
COPY prisma ./prisma
RUN npm ci

# Generate Prisma client
RUN node_modules/.bin/prisma generate

COPY . .
RUN npm run build

# ── runner ────────────────────────────────────────────────────────────────────
FROM node:22-alpine
WORKDIR /app

RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# Install production deps (includes prisma + better-sqlite3, rebuilt for this image)
COPY package*.json ./
COPY prisma ./prisma
RUN npm ci --omit=dev

# Re-generate Prisma client in runner stage
RUN npm install prisma@$(node -p "require('./package.json').devDependencies.prisma") --no-save
RUN node_modules/.bin/prisma generate

# Copy built Next.js output
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
COPY --from=builder /app/next.config.ts ./next.config.ts
COPY --from=builder /app/prisma.config.ts ./prisma.config.ts

# Entrypoint
COPY docker/docker-entrypoint.sh ./docker-entrypoint.sh
RUN chmod +x ./docker-entrypoint.sh

RUN mkdir -p /data && chown -R appuser:appgroup /app /data
USER appuser

EXPOSE 3000

# /data is the volume mount point for the SQLite database
VOLUME ["/data"]

CMD ["./docker-entrypoint.sh"]

.dockerignore

.git
.github
.next
app/generated
docker/*
!docker/docker-entrypoint.sh
node_modules
.dockerignore
.env
.env.example
.gitignore
*.log
*.db

Finally, prisma still needs to be moved from devDependencies to dependencies.

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.

2 participants