feat: add Docker support with Dockerfile and docker-compose configuration
This commit is contained in:
+21
-1
@@ -1,13 +1,33 @@
|
|||||||
.git
|
.git
|
||||||
|
.github
|
||||||
|
.next
|
||||||
.next-dev
|
.next-dev
|
||||||
|
.next/cache
|
||||||
node_modules
|
node_modules
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
.env
|
.env
|
||||||
.env.*
|
.env.*
|
||||||
deploy-packages
|
deploy-packages
|
||||||
output
|
output
|
||||||
|
data
|
||||||
|
media
|
||||||
|
files
|
||||||
|
videos
|
||||||
|
public
|
||||||
|
docs
|
||||||
|
*.md
|
||||||
*.dump
|
*.dump
|
||||||
*.tgz
|
*.tgz
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
cloudflare/.wrangler
|
cloudflare
|
||||||
.wrangler
|
.wrangler
|
||||||
|
.claude
|
||||||
|
.playwright-cli
|
||||||
|
.tmp
|
||||||
|
.turbo
|
||||||
|
tsconfig.tsbuildinfo
|
||||||
|
tmp-*
|
||||||
|
**/.DS_Store
|
||||||
|
**/._*
|
||||||
|
__MACOSX
|
||||||
|
src/seed/raw
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ videos
|
|||||||
deploy-packages
|
deploy-packages
|
||||||
output
|
output
|
||||||
|
|
||||||
|
# nginx TLS material (upload fullchain.pem + privkey.pem on the server)
|
||||||
|
nginx/certs/*.pem
|
||||||
|
nginx/certs/*.key
|
||||||
|
data/
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
._*
|
._*
|
||||||
|
|||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
FROM uhub.service.ucloud.cn/mysql-images/node:22-bookworm-slim AS deps
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN --mount=type=cache,target=/root/.npm \
|
||||||
|
npm config set registry https://registry.npmmirror.com \
|
||||||
|
&& npm ci
|
||||||
|
|
||||||
|
FROM uhub.service.ucloud.cn/mysql-images/node:22-bookworm-slim AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
ARG NEXT_PUBLIC_SITE_URL
|
||||||
|
ARG PAYLOAD_SECRET
|
||||||
|
ARG DATABASE_URI
|
||||||
|
|
||||||
|
ENV NEXT_PUBLIC_SITE_URL=$NEXT_PUBLIC_SITE_URL
|
||||||
|
ENV PAYLOAD_SECRET=$PAYLOAD_SECRET
|
||||||
|
ENV DATABASE_URI=$DATABASE_URI
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM uhub.service.ucloud.cn/mysql-images/node:22-bookworm-slim AS runner
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV PORT=3000
|
||||||
|
ENV HOSTNAME=0.0.0.0
|
||||||
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
|
RUN addgroup --system --gid 1001 nodejs \
|
||||||
|
&& adduser --system --uid 1001 --gid nodejs nextjs
|
||||||
|
|
||||||
|
COPY --from=builder /app/public ./public
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||||
|
|
||||||
|
RUN mkdir -p media files videos \
|
||||||
|
&& chown -R nextjs:nodejs media files videos
|
||||||
|
|
||||||
|
USER nextjs
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
CMD ["node", "server.js"]
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
services:
|
||||||
|
app:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
# Enable BuildKit layer/cache mounts: DOCKER_BUILDKIT=1 docker compose build app
|
||||||
|
args:
|
||||||
|
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL}
|
||||||
|
PAYLOAD_SECRET: ${PAYLOAD_SECRET}
|
||||||
|
DATABASE_URI: ${DATABASE_URI}
|
||||||
|
container_name: eversolo-web
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file: .env
|
||||||
|
expose:
|
||||||
|
- "3000"
|
||||||
|
volumes:
|
||||||
|
- ./data/media:/app/media
|
||||||
|
- ./data/files:/app/files
|
||||||
|
- ./data/videos:/app/videos
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
|
||||||
|
nginx:
|
||||||
|
image: uhub.service.ucloud.cn/mysql-images/nginx:latest
|
||||||
|
container_name: eversolo-nginx
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- app
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
- ./nginx/conf.d:/etc/nginx/conf.d:ro
|
||||||
|
- ./nginx/certs:/etc/nginx/certs:ro
|
||||||
|
- ./data/media:/srv/uploads/media:ro
|
||||||
|
- ./data/files:/srv/uploads/files:ro
|
||||||
|
- ./data/videos:/srv/uploads/videos:ro
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
|
||||||
|
bootstrap:
|
||||||
|
image: uhub.service.ucloud.cn/mysql-images/node:22-bookworm-slim
|
||||||
|
working_dir: /app
|
||||||
|
env_file: .env
|
||||||
|
volumes:
|
||||||
|
- .:/app
|
||||||
|
- bootstrap_node_modules:/app/node_modules
|
||||||
|
- ./data/media:/app/media
|
||||||
|
- ./data/files:/app/files
|
||||||
|
- ./data/videos:/app/videos
|
||||||
|
command: >
|
||||||
|
bash -lc "
|
||||||
|
npm ci --include=dev &&
|
||||||
|
npm run payload:migrate &&
|
||||||
|
npm run payload:migrate:status &&
|
||||||
|
npm run seed:import -- --live &&
|
||||||
|
npx tsx ./src/scripts/create-admin.ts
|
||||||
|
"
|
||||||
|
profiles: [bootstrap]
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
bootstrap_node_modules:
|
||||||
@@ -7,6 +7,7 @@ const PUBLIC_PAGE_CACHE_CONTROL = 'public, max-age=0, s-maxage=300, stale-while-
|
|||||||
|
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
|
output: 'standalone',
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
allowedDevOrigins: ['127.0.0.1', '192.168.1.252'],
|
allowedDevOrigins: ['127.0.0.1', '192.168.1.252'],
|
||||||
distDir: process.env.NEXT_DIST_DIR || '.next',
|
distDir: process.env.NEXT_DIST_DIR || '.next',
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
upstream eversolo_app {
|
||||||
|
server app:3000;
|
||||||
|
keepalive 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
map $http_upgrade $connection_upgrade {
|
||||||
|
default upgrade;
|
||||||
|
'' close;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name www.luxsin.net luxsin.net;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
return 301 https://www.luxsin.net$request_uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
listen [::]:443 ssl;
|
||||||
|
http2 on;
|
||||||
|
server_name www.luxsin.net;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||||
|
ssl_session_timeout 1d;
|
||||||
|
ssl_session_cache shared:SSL:10m;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_prefer_server_ciphers off;
|
||||||
|
|
||||||
|
add_header X-Content-Type-Options nosniff always;
|
||||||
|
add_header X-Frame-Options SAMEORIGIN always;
|
||||||
|
add_header Referrer-Policy strict-origin-when-cross-origin always;
|
||||||
|
|
||||||
|
# Payload uploads served directly from the persistent data volume (see docker-compose nginx mounts).
|
||||||
|
location /media/ {
|
||||||
|
alias /srv/uploads/media/;
|
||||||
|
access_log off;
|
||||||
|
expires 30d;
|
||||||
|
add_header Cache-Control "public, max-age=2592000, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
location /files/ {
|
||||||
|
alias /srv/uploads/files/;
|
||||||
|
access_log off;
|
||||||
|
expires 7d;
|
||||||
|
add_header Cache-Control "public, max-age=604800";
|
||||||
|
}
|
||||||
|
|
||||||
|
location /videos/ {
|
||||||
|
alias /srv/uploads/videos/;
|
||||||
|
access_log off;
|
||||||
|
expires 30d;
|
||||||
|
add_header Cache-Control "public, max-age=2592000";
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://eversolo_app;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection $connection_upgrade;
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
proxy_send_timeout 300s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
listen [::]:443 ssl;
|
||||||
|
http2 on;
|
||||||
|
server_name luxsin.net;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||||
|
|
||||||
|
return 301 https://www.luxsin.net$request_uri;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
user nginx;
|
||||||
|
worker_processes auto;
|
||||||
|
error_log /var/log/nginx/error.log warn;
|
||||||
|
pid /var/run/nginx.pid;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||||
|
'$status $body_bytes_sent "$http_referer" '
|
||||||
|
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||||
|
|
||||||
|
access_log /var/log/nginx/access.log main;
|
||||||
|
|
||||||
|
sendfile on;
|
||||||
|
keepalive_timeout 65;
|
||||||
|
client_max_body_size 100m;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
|
||||||
|
|
||||||
|
include /etc/nginx/conf.d/*.conf;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user