Skip to content
GitHub

Docker

In many cases, we build our application with Docker to enable easy hosting on external servers.

One of the most efficient ways to do this is using a technique called Multi-stage builds, which consists of multiple stages that prepare the application and produce a final image containing only the production code. Here’s an example:

# Phase 1: Build the application
FROM node:22-alpine AS builder
WORKDIR /app

COPY package.json package-lock.json ./
RUN npm ci

COPY . .
RUN npm run build

# Phase 2: Prepare the production image
FROM node:22-alpine AS production
WORKDIR /app

ENV NODE_ENV=production

COPY package.json package-lock.json ./
RUN npm ci --include=prod

## Output from build step on builder stage
COPY --from=builder /app/dist ./dist
## Production server
COPY server.js ./

EXPOSE 5173

CMD ["node", "server.js"]

This strategy produces a much leaner image that includes only production dependencies and the bundled files.

If you are already using this approach and add layerfig, you may encounter an error like this:

Error: File "/app/config/base.json" does not exist
    at ConfigBuilder.addSource (file:///app/node_modules/@layerfig/config/dist/index.js:78:46)
    at file:///app/dist/server/entry-server.js:6:48
    at ModuleJob.run (node:internal/modules/esm/module_job:274:25)
    at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:644:26)
    at async file:///app/server.js:51:17

This error occurs because you need to include the configuration files in the final production stage:

# Phase 1: Build the application
FROM node:22-alpine AS builder
WORKDIR /app

COPY package.json package-lock.json ./
RUN npm ci

COPY . .
RUN npm run build

# Phase 2: Prepare the production image
FROM node:22-alpine AS production
WORKDIR /app

ENV NODE_ENV=production

COPY package.json package-lock.json ./
RUN npm ci --include=prod

## Output from build step on builder stage
COPY --from=builder /app/dist ./dist
## Production server
COPY server.js .

+## Include configuration files
+COPY ./config ./config

EXPOSE 5173

CMD ["node", "server.js"]

Now your application will include the configuration files and load them correctly.