Docker support v2
This commit is contained in:
+134
@@ -0,0 +1,134 @@
|
|||||||
|
############################################################
|
||||||
|
# Production-ready .dockerignore for a Next.js (Vercel-style) app
|
||||||
|
# Keeps Docker builds fast, lean, and free of development files.
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
# Dependencies (installed inside Docker, never copied)
|
||||||
|
node_modules/
|
||||||
|
.pnpm-store/
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# Next.js build outputs (always generated during `next build`)
|
||||||
|
.next/
|
||||||
|
out/
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
.vercel/
|
||||||
|
|
||||||
|
# Tests and testing output (not needed in production images)
|
||||||
|
coverage/
|
||||||
|
.nyc_output/
|
||||||
|
__tests__/
|
||||||
|
__mocks__/
|
||||||
|
jest/
|
||||||
|
cypress/
|
||||||
|
cypress/screenshots/
|
||||||
|
cypress/videos/
|
||||||
|
playwright-report/
|
||||||
|
test-results/
|
||||||
|
.vitest/
|
||||||
|
vitest.config.*
|
||||||
|
jest.config.*
|
||||||
|
cypress.config.*
|
||||||
|
playwright.config.*
|
||||||
|
*.test.*
|
||||||
|
*.spec.*
|
||||||
|
|
||||||
|
# Local development and editor files
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
.gitattributes
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Environment variables (only commit template files)
|
||||||
|
.env
|
||||||
|
.env*.local
|
||||||
|
.env.development
|
||||||
|
.env.test
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
# Docker configuration files (not needed inside build context)
|
||||||
|
Dockerfile*
|
||||||
|
.dockerignore
|
||||||
|
compose.yaml
|
||||||
|
compose.yml
|
||||||
|
docker-compose*.yaml
|
||||||
|
docker-compose*.yml
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
*.md
|
||||||
|
docs/
|
||||||
|
|
||||||
|
# CI/CD configuration files
|
||||||
|
.github/
|
||||||
|
.gitlab-ci.yml
|
||||||
|
.travis.yml
|
||||||
|
.circleci/
|
||||||
|
Jenkinsfile
|
||||||
|
|
||||||
|
# Cache directories and temporary data
|
||||||
|
.cache/
|
||||||
|
.parcel-cache/
|
||||||
|
.eslintcache
|
||||||
|
.stylelintcache
|
||||||
|
.swc/
|
||||||
|
.turbo/
|
||||||
|
.tmp/
|
||||||
|
.temp/
|
||||||
|
|
||||||
|
# TypeScript build metadata
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Sensitive or unnecessary configuration files
|
||||||
|
*.pem
|
||||||
|
.editorconfig
|
||||||
|
.prettierrc*
|
||||||
|
prettier.config.*
|
||||||
|
.eslintrc*
|
||||||
|
eslint.config.*
|
||||||
|
.stylelintrc*
|
||||||
|
stylelint.config.*
|
||||||
|
.babelrc*
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# OS-specific junk
|
||||||
|
.DS_Store
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
# AI/ML tool metadata and configs
|
||||||
|
.cursor/
|
||||||
|
.cursorrules
|
||||||
|
.copilot/
|
||||||
|
.copilotignore
|
||||||
|
.github/copilot/
|
||||||
|
.gemini/
|
||||||
|
.anthropic/
|
||||||
|
.kiro
|
||||||
|
.claude
|
||||||
|
AGENTS.md
|
||||||
|
.agents/
|
||||||
|
|
||||||
|
# AI-generated temp files
|
||||||
|
*.aider*
|
||||||
|
*.copilot*
|
||||||
|
*.chatgpt*
|
||||||
|
*.claude*
|
||||||
|
*.gemini*
|
||||||
|
*.openai*
|
||||||
|
*.anthropic*
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
name: Build and Push Docker Image
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- develop
|
|
||||||
tags:
|
|
||||||
- 'v*.*.*'
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- develop
|
|
||||||
|
|
||||||
env:
|
|
||||||
REGISTRY: ghcr.io
|
|
||||||
IMAGE_NAME: ${{ github.repository }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Convert image name to lowercase
|
|
||||||
id: image
|
|
||||||
run: echo "image=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}" | tr '[:upper:]' '[:lower:]' | xargs -I {} echo "name={}" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Log in to Container Registry
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ${{ env.REGISTRY }}
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Extract metadata
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
||||||
tags: |
|
|
||||||
type=ref,event=branch
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
|
||||||
type=sha
|
|
||||||
|
|
||||||
- name: Build and push Docker image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
cache-from: type=registry,ref=${{ steps.image.outputs.name }}:buildcache
|
|
||||||
cache-to: type=registry,ref=${{ steps.image.outputs.name }}:buildcache,mode=max
|
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
name: Docker
|
||||||
|
|
||||||
|
# This workflow uses actions that are not certified by GitHub.
|
||||||
|
# They are provided by a third-party and are governed by
|
||||||
|
# separate terms of service, privacy policy, and support
|
||||||
|
# documentation.
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '38 21 * * *'
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
# Publish semver tags as releases.
|
||||||
|
tags: [ 'v*.*.*' ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "master" ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
# Use docker.io for Docker Hub if empty
|
||||||
|
REGISTRY: ghcr.io
|
||||||
|
# github.repository as <account>/<repo>
|
||||||
|
IMAGE_NAME: ${{ github.repository }}
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
# This is used to complete the identity challenge
|
||||||
|
# with sigstore/fulcio when running outside of PRs.
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# Install the cosign tool except on PR
|
||||||
|
# https://github.com/sigstore/cosign-installer
|
||||||
|
- name: Install cosign
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 #v3.5.0
|
||||||
|
with:
|
||||||
|
cosign-release: 'v2.2.4'
|
||||||
|
|
||||||
|
# Set up BuildKit Docker container builder to be able to build
|
||||||
|
# multi-platform images and export cache
|
||||||
|
# https://github.com/docker/setup-buildx-action
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||||
|
|
||||||
|
# Login against a Docker registry except on PR
|
||||||
|
# https://github.com/docker/login-action
|
||||||
|
- name: Log into registry ${{ env.REGISTRY }}
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
# Extract metadata (tags, labels) for Docker
|
||||||
|
# https://github.com/docker/metadata-action
|
||||||
|
- name: Extract Docker metadata
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
|
|
||||||
|
# Build and push Docker image with Buildx (don't push on PR)
|
||||||
|
# https://github.com/docker/build-push-action
|
||||||
|
- name: Build and push Docker image
|
||||||
|
id: build-and-push
|
||||||
|
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|
||||||
|
# Sign the resulting Docker image digest except on PRs.
|
||||||
|
# This will only write to the public Rekor transparency log when the Docker
|
||||||
|
# repository is public to avoid leaking data. If you would like to publish
|
||||||
|
# transparency data even for private images, pass --force to cosign below.
|
||||||
|
# https://github.com/sigstore/cosign
|
||||||
|
- name: Sign the published Docker image
|
||||||
|
if: ${{ github.event_name != 'pull_request' }}
|
||||||
|
env:
|
||||||
|
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
|
||||||
|
TAGS: ${{ steps.meta.outputs.tags }}
|
||||||
|
DIGEST: ${{ steps.build-and-push.outputs.digest }}
|
||||||
|
# This step uses the identity token to provision an ephemeral certificate
|
||||||
|
# against the sigstore community Fulcio instance.
|
||||||
|
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
|
||||||
+97
-31
@@ -1,46 +1,112 @@
|
|||||||
# Build stage
|
# ============================================
|
||||||
FROM node:24-alpine AS builder
|
# Stage 1: Dependencies Installation Stage
|
||||||
|
# ============================================
|
||||||
|
|
||||||
|
# IMPORTANT: Node.js Version Maintenance
|
||||||
|
# This Dockerfile uses Node.js 24.13.0-slim, which was the latest LTS version at the time of writing.
|
||||||
|
# To ensure security and compatibility, regularly update the NODE_VERSION ARG to the latest LTS version.
|
||||||
|
ARG NODE_VERSION=24.13.0-slim
|
||||||
|
|
||||||
|
FROM node:${NODE_VERSION} AS dependencies
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install pnpm
|
# Copy package-related files first to leverage Docker's caching mechanism
|
||||||
RUN npm install -g pnpm
|
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./
|
||||||
|
|
||||||
# Copy package files
|
# Install project dependencies with frozen lockfile for reproducible builds
|
||||||
COPY pnpm-lock.yaml package.json ./
|
RUN --mount=type=cache,target=/root/.npm \
|
||||||
|
--mount=type=cache,target=/usr/local/share/.cache/yarn \
|
||||||
|
--mount=type=cache,target=/root/.local/share/pnpm/store \
|
||||||
|
if [ -f package-lock.json ]; then \
|
||||||
|
npm ci --no-audit --no-fund; \
|
||||||
|
elif [ -f yarn.lock ]; then \
|
||||||
|
corepack enable yarn && yarn install --frozen-lockfile --production=false; \
|
||||||
|
elif [ -f pnpm-lock.yaml ]; then \
|
||||||
|
corepack enable pnpm && pnpm install --frozen-lockfile; \
|
||||||
|
else \
|
||||||
|
echo "No lockfile found." && exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
# Install dependencies
|
# ============================================
|
||||||
RUN pnpm install --frozen-lockfile
|
# Stage 2: Build Next.js application in standalone mode
|
||||||
|
# ============================================
|
||||||
|
|
||||||
# Copy source code
|
FROM node:${NODE_VERSION} AS builder
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy project dependencies from dependencies stage
|
||||||
|
COPY --from=dependencies /app/node_modules ./node_modules
|
||||||
|
|
||||||
|
# Copy application source code
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Build application
|
|
||||||
RUN pnpm run build
|
|
||||||
|
|
||||||
# Production stage
|
|
||||||
FROM node:20-alpine
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Install pnpm
|
|
||||||
RUN npm install -g pnpm
|
|
||||||
|
|
||||||
# Set environment to production
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
# Copy package files from builder
|
# Next.js collects completely anonymous telemetry data about general usage.
|
||||||
COPY package.json pnpm-lock.yaml ./
|
# Learn more here: https://nextjs.org/telemetry
|
||||||
|
# Uncomment the following line in case you want to disable telemetry during the build.
|
||||||
|
# ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
# Install production dependencies only
|
# Build Next.js application
|
||||||
RUN pnpm install --prod --frozen-lockfile
|
# If you want to speed up Docker rebuilds, you can cache the build artifacts
|
||||||
|
# by adding: --mount=type=cache,target=/app/.next/cache
|
||||||
|
# This caches the .next/cache directory across builds, but it also prevents
|
||||||
|
# .next/cache/fetch-cache from being included in the final image, meaning
|
||||||
|
# cached fetch responses from the build won't be available at runtime.
|
||||||
|
RUN if [ -f package-lock.json ]; then \
|
||||||
|
npm run build; \
|
||||||
|
elif [ -f yarn.lock ]; then \
|
||||||
|
corepack enable yarn && yarn build; \
|
||||||
|
elif [ -f pnpm-lock.yaml ]; then \
|
||||||
|
corepack enable pnpm && pnpm build; \
|
||||||
|
else \
|
||||||
|
echo "No lockfile found." && exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
# Copy built application from builder stage
|
# ============================================
|
||||||
COPY --from=builder /app/.next ./.next
|
# Stage 3: Run Next.js application
|
||||||
COPY --from=builder /app/public ./public
|
# ============================================
|
||||||
|
|
||||||
# Expose port
|
FROM node:${NODE_VERSION} AS runner
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Set production environment variables
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV PORT=3000
|
||||||
|
ENV HOSTNAME="0.0.0.0"
|
||||||
|
|
||||||
|
# Next.js collects completely anonymous telemetry data about general usage.
|
||||||
|
# Learn more here: https://nextjs.org/telemetry
|
||||||
|
# Uncomment the following line in case you want to disable telemetry during the run time.
|
||||||
|
# ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
|
# Copy production assets
|
||||||
|
COPY --from=builder --chown=node:node /app/public ./public
|
||||||
|
|
||||||
|
# Set the correct permission for prerender cache
|
||||||
|
RUN mkdir .next
|
||||||
|
RUN chown node:node .next
|
||||||
|
|
||||||
|
# Automatically leverage output traces to reduce image size
|
||||||
|
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||||
|
COPY --from=builder --chown=node:node /app/.next/standalone ./
|
||||||
|
COPY --from=builder --chown=node:node /app/.next/static ./.next/static
|
||||||
|
|
||||||
|
# If you want to persist the fetch cache generated during the build so that
|
||||||
|
# cached responses are available immediately on startup, uncomment this line:
|
||||||
|
# COPY --from=builder --chown=node:node /app/.next/cache ./.next/cache
|
||||||
|
|
||||||
|
# Switch to non-root user for security best practices
|
||||||
|
USER node
|
||||||
|
|
||||||
|
# Expose port 3000 to allow HTTP traffic
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
# Start application
|
# Start Next.js standalone server
|
||||||
CMD ["pnpm", "start"]
|
CMD ["node", "server.js"]
|
||||||
+1
-6
@@ -1,11 +1,6 @@
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
typescript: {
|
output: "standalone",
|
||||||
ignoreBuildErrors: true,
|
|
||||||
},
|
|
||||||
images: {
|
|
||||||
unoptimized: true,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default nextConfig
|
export default nextConfig
|
||||||
|
|||||||
Reference in New Issue
Block a user