Why is pnpm build
used in Docker with-docker-multi-env
example but not in with-docker-compose
example for Development Mode?
#62943
-
Summary
but https://github.com/vercel/next.js/blob/canary/examples/with-docker-compose/next-app/dev.Dockerfile Why? Shouldn't the development Dockerfile use I would like to know what can be removed from the development Dockerfile if I'm sure this can be reduced: FROM node:18-alpine AS base
# 1. Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i; \
else echo "Lockfile not found." && exit 1; \
fi
# 2. Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# This will do the trick, use the corresponding env file for each environment.
COPY .env.development.sample .env.production
RUN npm run build
# 3. Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
COPY --from=builder /app/public ./public
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
ENV HOSTNAME localhost
CMD ["node", "server.js"] Additional informationNo response ExampleNo response |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
Yeah, so the example above needs to be updated because I wanted to try development mode with Docker. I couldn't just do Now I could've just used Redis on WSL2 but that wouldn't be fun so I did the dumb thing & built separate Dockerfiles for development, staging, & production. docker/development/DockerfileFROM node:20-alpine AS base
# mostly inspired from https://github.com/BretFisher/node-docker-good-defaults/blob/main/Dockerfile & https://github.com/remix-run/example-trellix/blob/main/Dockerfile
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
RUN corepack enable && corepack prepare pnpm@8.15.4 --activate
# set the store dir to a folder that is not in the project
RUN pnpm config set store-dir ~/.pnpm-store
RUN pnpm fetch
# 1. Install all dependencies including dev dependencies
FROM base AS deps
# Root user is implicit so you don't have to actually specify it. From https://stackoverflow.com/a/45553149/6141587
# USER root
USER node
# WORKDIR now sets correct permissions if you set USER first so `USER node` has permissions on `/app` directory
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY --chown=node:node package.json pnpm-lock.yaml* ./
COPY --chown=node:node /src/app/db/migrations ./migrations
USER root
RUN pnpm install --frozen-lockfile --prefer-offline
RUN pnpm install sharp@0.32.6
# 2. Start the development server
USER node
# Inspired by https://github.com/vercel/next.js/discussions/36935
RUN mkdir -p /app/.next/cache && chown -R node:node /app/.next/cache
# Persist the next cache in a volume
VOLUME ["/app/.next/cache"]
# COPY --from=deps --chown=node:node /app/node_modules ./node_modules
COPY --chown=node:node . .
# This will do the trick, use the corresponding env file for each environment.
COPY --chown=node:node .env.development .env.development
# Copied from https://stackoverflow.com/a/69867550/6141587
USER root
# Give /data directory correct permissions otherwise WAL mode won't work. It means you can't have 2 users writing to the database at the same time without this line as *.sqlite-wal & *.sqlite-shm are automatically created & deleted when *.sqlite is busy.
RUN mkdir -p /data && chown -R node:node /data
USER node
EXPOSE 3000
ENV PORT 3000
ENV HOSTNAME 0.0.0.0
ENV NODE_ENV development
ENV NEXT_TELEMETRY_DISABLED 1
COPY --chown=node:node public ./public
# Move the drizzle directory to the runtime image
COPY --chown=node:node src/app/db/migrations ./migrations
COPY --chown=node:node scripts/drizzle-migrate.mjs ./scripts/drizzle-migrate.mjs
COPY --chown=node:node scripts/package.json ./scripts/package.json
COPY --chown=node:node scripts/pnpm-lock.yaml ./scripts/pnpm-lock.yaml
COPY --chown=node:node scripts/run.dev.sh ./run.dev.sh
RUN chmod +x run.dev.sh
CMD ["sh", "run.dev.sh"] run.dev.sh#!/bin/bash
set -e
# Set the directory of the database in a variable
DB_PATH=/data/users.dev.sqlite
# Set to true only when you want to run the migrate script, i.e, when changing database schema
# Automate it by only setting it to true by tracking `entries.idx` in `migrations/meta/_journal.json`
MIGRATE_DATABASE=false
# Inspired by https://pranavmalvawala.com/run-script-only-on-first-start-up & https://serverfault.com/a/1134812/1078165
FIRST_TIME_MIGRATION_DEV="FIRST_TIME_MIGRATION_DEV"
if [[ ! -e /data/$FIRST_TIME_MIGRATION_DEV ]] || [[ $MIGRATE_DATABASE = true ]]; then
# Place your script that you only want to run on first startup.
echo 'Initialize database first time only'
touch /data/$FIRST_TIME_MIGRATION_DEV
echo "Migrating database '/data/users.dev.sqlite'"
pnpm db:migrate:dev & PID=$!
# Wait for migration to finish
wait $PID
fi
echo "Starting development server..."
pnpm dev This is for I'll probably make https://github.com/deadcoder0904/easypanel-nextjs-sqlite use these 3 environments Next.js guys should improve their development file in example though. This is how it should be. Would've taken me less time if I could copy-pasta. |
Beta Was this translation helpful? Give feedback.
Yeah, so the example above needs to be updated because I wanted to try development mode with Docker. I couldn't just do
pnpm dev
because my Redis server needed to be on & I am on Windows where Redis doesn't work.Now I could've just used Redis on WSL2 but that wouldn't be fun so I did the dumb thing & built separate Dockerfiles for development, staging, & production.
docker/development/Dockerfile