Skip to content

Commit 50742c4

Browse files
committed
feat: add Docker configuration and build workflow for Next.js application
1 parent 2310ef3 commit 50742c4

File tree

4 files changed

+233
-0
lines changed

4 files changed

+233
-0
lines changed

.dockerignore

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Dependencies
2+
node_modules
3+
npm-debug.log*
4+
yarn-debug.log*
5+
yarn-error.log*
6+
7+
# Next.js
8+
.next/
9+
out/
10+
build/
11+
dist/
12+
13+
# Environment files
14+
.env
15+
.env.local
16+
.env.development.local
17+
.env.test.local
18+
.env.production.local
19+
20+
# Git
21+
.git
22+
.gitignore
23+
24+
# Docker
25+
Dockerfile
26+
.dockerignore
27+
docker-compose*.yml
28+
29+
# IDE and editors
30+
.vscode/
31+
.idea/
32+
*.swp
33+
*.swo
34+
*~
35+
36+
# OS generated files
37+
.DS_Store
38+
.DS_Store?
39+
._*
40+
.Spotlight-V100
41+
.Trashes
42+
ehthumbs.db
43+
Thumbs.db
44+
45+
# Logs
46+
logs
47+
*.log
48+
49+
# Runtime data
50+
pids
51+
*.pid
52+
*.seed
53+
*.pid.lock
54+
55+
# Coverage directory used by tools like istanbul
56+
coverage/
57+
.nyc_output
58+
59+
# Dependency directories
60+
jspm_packages/
61+
62+
# Optional npm cache directory
63+
.npm
64+
65+
# Optional eslint cache
66+
.eslintcache
67+
68+
# Output of 'npm pack'
69+
*.tgz
70+
71+
# Yarn Integrity file
72+
.yarn-integrity
73+
74+
# dotenv environment variables file
75+
.env.test
76+
77+
# parcel-bundler cache (https://parceljs.org/)
78+
.cache
79+
.parcel-cache
80+
81+
# next.js build output
82+
.next
83+
84+
# nuxt.js build output
85+
.nuxt
86+
87+
# vuepress build output
88+
.vuepress/dist
89+
90+
# Serverless directories
91+
.serverless
92+
93+
# FuseBox cache
94+
.fusebox/
95+
96+
# DynamoDB Local files
97+
.dynamodb/
98+
99+
# TernJS port file
100+
.tern-port
101+
102+
# README
103+
README.md
104+
105+
# Documentation
106+
docs/
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: Build and Push Docker Image
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- "Dockerfile"
9+
- "src/**"
10+
env:
11+
REGISTRY: ghcr.io
12+
IMAGE_NAME: ${{ github.repository }}
13+
14+
jobs:
15+
build-and-push:
16+
runs-on: ubuntu-latest
17+
permissions:
18+
contents: read
19+
packages: write
20+
21+
steps:
22+
- name: Checkout repository
23+
uses: actions/checkout@v4
24+
25+
- name: Set up Docker Buildx
26+
uses: docker/setup-buildx-action@v3
27+
28+
- name: Log in to Container Registry
29+
uses: docker/login-action@v3
30+
with:
31+
registry: ${{ env.REGISTRY }}
32+
username: ${{ github.actor }}
33+
password: ${{ secrets.GITHUB_TOKEN }}
34+
35+
- name: Extract metadata
36+
id: meta
37+
uses: docker/metadata-action@v5
38+
with:
39+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
40+
tags: |
41+
# Branch name (sanitized)
42+
type=ref,event=branch
43+
# Short SHA
44+
type=sha,prefix={{branch}}-,format=short
45+
# Latest tag for main branch
46+
type=raw,value=latest,enable={{is_default_branch}}
47+
# PR number for pull requests
48+
type=ref,event=pr,prefix=pr-
49+
50+
- name: Build and push Docker image
51+
id: build
52+
uses: docker/build-push-action@v5
53+
with:
54+
context: .
55+
file: ./Dockerfile
56+
push: true
57+
tags: ${{ steps.meta.outputs.tags }}
58+
labels: ${{ steps.meta.outputs.labels }}
59+
cache-from: type=gha
60+
cache-to: type=gha,mode=max
61+
platforms: linux/amd64,linux/arm64
62+
63+
- name: Generate artifact attestation
64+
uses: actions/attest-build-provenance@v1
65+
with:
66+
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
67+
subject-digest: ${{ steps.build.outputs.digest }}
68+
push-to-registry: true

Dockerfile

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Use Node.js 22 Alpine as base image for smaller size
2+
FROM node:22-alpine AS base
3+
4+
# Install dependencies only when needed
5+
FROM base AS deps
6+
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
7+
RUN apk add --no-cache libc6-compat
8+
WORKDIR /app
9+
10+
# Install dependencies based on the preferred package manager
11+
COPY package.json package-lock.json* ./
12+
RUN npm ci --only=production && npm cache clean --force
13+
14+
# Rebuild the source code only when needed
15+
FROM base AS builder
16+
WORKDIR /app
17+
COPY --from=deps /app/node_modules ./node_modules
18+
COPY . .
19+
20+
# Environment variables for build
21+
ENV NEXT_TELEMETRY_DISABLED=1
22+
23+
# Build the application
24+
RUN npm run build
25+
26+
# Production image, copy all the files and run next
27+
FROM base AS runner
28+
WORKDIR /app
29+
30+
ENV NODE_ENV=production
31+
ENV NEXT_TELEMETRY_DISABLED=1
32+
33+
# Create a non-root user
34+
RUN addgroup --system --gid 1001 nodejs
35+
RUN adduser --system --uid 1001 nextjs
36+
37+
# Copy the public folder
38+
COPY --from=builder /app/public ./public
39+
40+
# Set the correct permission for prerender cache
41+
RUN mkdir .next
42+
RUN chown nextjs:nodejs .next
43+
44+
# Automatically leverage output traces to reduce image size
45+
# https://nextjs.org/docs/advanced-features/output-file-tracing
46+
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
47+
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
48+
49+
USER nextjs
50+
51+
EXPOSE 3000
52+
53+
ENV PORT=3000
54+
ENV HOSTNAME="0.0.0.0"
55+
56+
# server.js is created by next build from the standalone output
57+
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
58+
CMD ["node", "server.js"]

next.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { NextConfig } from "next";
22

33
const nextConfig: NextConfig = {
4+
output: "standalone",
45
/* config options here */
56
};
67

0 commit comments

Comments
 (0)