chore: optimize docker image size < 500MB with multi-stage build
This commit is contained in:
parent
7bb58693dd
commit
94f046f0d6
3 changed files with 62 additions and 29 deletions
29
.dockerignore
Normal file
29
.dockerignore
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Git
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# Node
|
||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
|
||||||
|
# Python
|
||||||
|
venv
|
||||||
|
__pycache__
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*.pyd
|
||||||
|
|
||||||
|
# Next.js
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
Dockerfile
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
*.log
|
||||||
60
Dockerfile
60
Dockerfile
|
|
@ -1,58 +1,60 @@
|
||||||
|
# --- Stage 1: Frontend Builder ---
|
||||||
|
FROM node:18-alpine AS builder
|
||||||
|
WORKDIR /app/frontend
|
||||||
|
COPY frontend/package*.json ./
|
||||||
|
# Install dependencies including devDependencies for build
|
||||||
|
RUN npm install --legacy-peer-deps
|
||||||
|
COPY frontend/ ./
|
||||||
|
# Build with standalone output
|
||||||
|
ENV NEXT_PUBLIC_API_URL="http://localhost:8000"
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# --- Stage 2: Final Runtime Image ---
|
||||||
FROM python:3.11-slim
|
FROM python:3.11-slim
|
||||||
|
|
||||||
# Install Node.js and dependencies
|
# Install system dependencies
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
curl \
|
curl \
|
||||||
gnupg \
|
gnupg \
|
||||||
ffmpeg \
|
ffmpeg \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
|
nodejs \
|
||||||
|
npm \
|
||||||
&& update-ca-certificates \
|
&& update-ca-certificates \
|
||||||
&& curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
|
|
||||||
&& apt-get install -y nodejs \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# --- Backend Setup ---
|
# Backend Setup
|
||||||
COPY backend/requirements.txt ./backend/requirements.txt
|
COPY backend/requirements.txt ./backend/requirements.txt
|
||||||
RUN pip install --no-cache-dir -r backend/requirements.txt
|
RUN pip install --no-cache-dir -r backend/requirements.txt
|
||||||
|
|
||||||
# --- Frontend Setup ---
|
# Frontend Setup (Copy from Builder)
|
||||||
COPY frontend/package*.json ./frontend/
|
# Copy the standalone server
|
||||||
WORKDIR /app/frontend
|
COPY --from=builder /app/frontend/.next/standalone /app/frontend
|
||||||
# Install dependencies (ignoring peer deps conflicts)
|
# Copy static files (required for standalone)
|
||||||
RUN npm install --legacy-peer-deps
|
COPY --from=builder /app/frontend/.next/static /app/frontend/.next/static
|
||||||
|
COPY --from=builder /app/frontend/public /app/frontend/public
|
||||||
|
|
||||||
COPY frontend/ .
|
# Copy Backend Code
|
||||||
# Build Next.js (with ignore-lint already set in next.config.mjs)
|
|
||||||
# We set API URL to http://localhost:8000 because in this container strategy,
|
|
||||||
# the browser will access the backend directly.
|
|
||||||
# Wait, for client-side fetches, "localhost" refers to the user's machine.
|
|
||||||
# If we run this container on port 3000 and 8000, localhost:8000 works internally via Rewrites.
|
|
||||||
# ENV NEXT_PUBLIC_API_URL="http://localhost:8000" Removed to use relative path proxying
|
|
||||||
# Build Next.js
|
|
||||||
ENV NEXTAUTH_URL=http://localhost:3000
|
|
||||||
# Secret should be provided at runtime via docker run -e or docker-compose
|
|
||||||
ARG NEXTAUTH_SECRET_ARG=default_dev_secret_change_in_production
|
|
||||||
ENV NEXTAUTH_SECRET=${NEXTAUTH_SECRET_ARG}
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
# --- Final Setup ---
|
|
||||||
WORKDIR /app
|
|
||||||
COPY backend/ ./backend/
|
COPY backend/ ./backend/
|
||||||
|
|
||||||
# Create a start script
|
# Create start script
|
||||||
# We also implement a "seed data" check.
|
|
||||||
# If the volume mount is empty (missing data.json), we copy from our backup.
|
|
||||||
RUN mkdir -p backend/data_seed && cp -r backend/data/* backend/data_seed/ || true
|
RUN mkdir -p backend/data_seed && cp -r backend/data/* backend/data_seed/ || true
|
||||||
|
|
||||||
|
# Set Environment Variables
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV PORT=3000
|
||||||
|
ENV HOSTNAME="0.0.0.0"
|
||||||
|
|
||||||
|
# Note: Standalone mode runs with 'node server.js'
|
||||||
RUN echo '#!/bin/bash\n\
|
RUN echo '#!/bin/bash\n\
|
||||||
if [ ! -f backend/data/data.json ]; then\n\
|
if [ ! -f backend/data/data.json ]; then\n\
|
||||||
echo "Data volume appears empty. Seeding with bundled data..."\n\
|
echo "Data volume appears empty. Seeding with bundled data..."\n\
|
||||||
cp -r backend/data_seed/* backend/data/\n\
|
cp -r backend/data_seed/* backend/data/\n\
|
||||||
fi\n\
|
fi\n\
|
||||||
uvicorn backend.main:app --host 0.0.0.0 --port 8000 &\n\
|
uvicorn backend.main:app --host 0.0.0.0 --port 8000 &\n\
|
||||||
cd frontend && npm start -- -p 3000\n\
|
cd frontend && node server.js\n\
|
||||||
' > start.sh && chmod +x start.sh
|
' > start.sh && chmod +x start.sh
|
||||||
|
|
||||||
EXPOSE 3000 8000
|
EXPOSE 3000 8000
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
|
// strict mode true is default but good to be explicit
|
||||||
// strict mode true is default but good to be explicit
|
// strict mode true is default but good to be explicit
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
|
output: "standalone",
|
||||||
eslint: {
|
eslint: {
|
||||||
ignoreDuringBuilds: true,
|
ignoreDuringBuilds: true,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue