feats: deploy with docker
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
name: Build and Push Docker Image to GHCR
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}/wrdo
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
# 检出代码
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# 设置 Docker Buildx(支持多平台构建)
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
# 登录到 GitHub Container Registry
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# 提取 Docker 镜像元数据(标签、版本等)
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=sha,format=short
|
||||
type=ref,event=branch,prefix=
|
||||
type=ref,event=tag
|
||||
|
||||
# 构建并推送 Docker 镜像
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: ${{ github.event_name != 'pull_request' }} # 仅在 push 时推送
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
ENVIRONMENT=${{ github.event.inputs.environment || 'production' }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
FROM node:22-alpine AS base
|
||||
|
||||
# Install dependencies only when needed
|
||||
FROM base AS deps
|
||||
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||
RUN apk add --no-cache libc6-compat
|
||||
WORKDIR /app
|
||||
|
||||
RUN npm install -g pnpm
|
||||
|
||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./
|
||||
|
||||
RUN pnpm config set registry https://registry.npmmirror.com
|
||||
|
||||
COPY prisma ./prisma
|
||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./
|
||||
RUN pnpm i --frozen-lockfile
|
||||
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
|
||||
RUN npm install -g pnpm
|
||||
|
||||
# ARG DATABASE_URL=""
|
||||
# ARG AUTH_SECRET=""
|
||||
# ARG NEXT_PUBLIC_APP_URL=http://localhost:3000
|
||||
# ARG GOOGLE_CLIENT_ID=""
|
||||
# ARG GOOGLE_CLIENT_SECRET=""
|
||||
# ARG GITHUB_ID=""
|
||||
# ARG GITHUB_SECRET=""
|
||||
# ARG LinuxDo_CLIENT_ID=""
|
||||
# ARG LinuxDo_CLIENT_SECRET=""
|
||||
# ARG RESEND_API_KEY="res"
|
||||
# ARG NEXT_PUBLIC_EMAIL_R2_DOMAIN=""
|
||||
# ARG NEXT_PUBLIC_OPEN_SIGNUP="1"
|
||||
# ARG NEXT_PUBLIC_GOOGLE_ID=""
|
||||
# ARG SCREENSHOTONE_BASE_URL=""
|
||||
# ARG GITHUB_TOKEN="g"
|
||||
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
|
||||
RUN pnpm run build
|
||||
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
RUN npm install -g pnpm
|
||||
|
||||
ENV NODE_ENV=production
|
||||
ENV IS_DOCKER=true
|
||||
|
||||
# 复制必要文件
|
||||
COPY --from=builder /app/public ./public
|
||||
|
||||
# Automatically leverage output traces to reduce image size
|
||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV PORT=3000
|
||||
|
||||
ENV HOSTNAME="0.0.0.0"
|
||||
CMD ["node", "server.js"]
|
||||
@@ -46,13 +46,15 @@ See docs about [email worker](https://wr.do/docs/developer/cloudflare-email-work
|
||||
|
||||
## Local development
|
||||
|
||||
copy `.env.example` to `.env` and fill in the necessary environment variables.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/oiov/wr.do
|
||||
cd wr.do
|
||||
pnpm install
|
||||
```
|
||||
|
||||
copy `.env.example` to `.env` and fill in the necessary environment variables.
|
||||
|
||||
```bash
|
||||
# run on localhost:3000
|
||||
pnpm dev
|
||||
```
|
||||
@@ -68,6 +70,37 @@ pnpm db:push
|
||||
|
||||
Follow https://localhost:3000/setup
|
||||
|
||||
### Start on Docker
|
||||
|
||||
#### Dockerfile
|
||||
|
||||
```bash
|
||||
git clone https://github.com/oiov/wr.do
|
||||
cd wr.do
|
||||
```
|
||||
|
||||
Fill in the environment variables in the `Dockerfile`, then build and run.
|
||||
|
||||
```bash
|
||||
# Build image
|
||||
docker build -t wrdo .
|
||||
# Run
|
||||
docker run -p 3000:3000 wrdo
|
||||
```
|
||||
|
||||
#### Docker Compose
|
||||
|
||||
```bash
|
||||
git clone https://github.com/oiov/wr.do
|
||||
cd wr.do
|
||||
```
|
||||
|
||||
Fill in the environment variables in the `env` file, then:
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Legitimacy review
|
||||
|
||||
- To avoid abuse, applications without website content will be rejected
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
services:
|
||||
wrdo:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: ghcr.io/oiov/wr.do/wrdo:${TAG:-latest}
|
||||
container_name: wrdo
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- IS_DOCKER=true
|
||||
- DATABASE_URL=postgres://postgres:postgres@postgres:5432/wrdo
|
||||
- AUTH_SECRET=${AUTH_SECRET:-your-auth-secret}
|
||||
- NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL:-http://localhost:3000}
|
||||
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID:-}
|
||||
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET:-}
|
||||
- GITHUB_ID=${GITHUB_ID:-}
|
||||
- GITHUB_SECRET=${GITHUB_SECRET:-}
|
||||
- LinuxDo_CLIENT_ID=${LinuxDo_CLIENT_ID:-}
|
||||
- LinuxDo_CLIENT_SECRET=${LinuxDo_CLIENT_SECRET:-}
|
||||
- RESEND_API_KEY=${RESEND_API_KEY:-}
|
||||
- NEXT_PUBLIC_EMAIL_R2_DOMAIN=${NEXT_PUBLIC_EMAIL_R2_DOMAIN:-}
|
||||
- NEXT_PUBLIC_OPEN_SIGNUP=${NEXT_PUBLIC_OPEN_SIGNUP:-1}
|
||||
- NEXT_PUBLIC_GOOGLE_ID=${NEXT_PUBLIC_GOOGLE_ID:-}
|
||||
- SCREENSHOTONE_BASE_URL=${SCREENSHOTONE_BASE_URL:-}
|
||||
- GITHUB_TOKEN=${GITHUB_TOKEN:-}
|
||||
depends_on:
|
||||
- postgres
|
||||
networks:
|
||||
- wrdo-network
|
||||
restart: unless-stopped
|
||||
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: postgres
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
- POSTGRES_DB=wrdo
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5432:5432"
|
||||
networks:
|
||||
- wrdo-network
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
name: wrdo-postgres-data
|
||||
|
||||
networks:
|
||||
wrdo-network:
|
||||
driver: bridge
|
||||
@@ -6,22 +6,22 @@ export const env = createEnv({
|
||||
// This is optional because it's only used in development.
|
||||
// See https://next-auth.js.org/deployment.
|
||||
NEXTAUTH_URL: z.string().url().optional(),
|
||||
AUTH_SECRET: z.string().min(1),
|
||||
AUTH_SECRET: z.string().optional(),
|
||||
GOOGLE_CLIENT_ID: z.string().optional(),
|
||||
GOOGLE_CLIENT_SECRET: z.string().optional(),
|
||||
GITHUB_ID: z.string().optional(),
|
||||
GITHUB_SECRET: z.string().optional(),
|
||||
LinuxDo_CLIENT_ID: z.string().optional(),
|
||||
LinuxDo_CLIENT_SECRET: z.string().optional(),
|
||||
DATABASE_URL: z.string().min(1),
|
||||
DATABASE_URL: z.string().optional(),
|
||||
RESEND_API_KEY: z.string().optional(),
|
||||
SCREENSHOTONE_BASE_URL: z.string().optional(),
|
||||
GITHUB_TOKEN: z.string().optional(),
|
||||
},
|
||||
client: {
|
||||
NEXT_PUBLIC_APP_URL: z.string().min(1),
|
||||
NEXT_PUBLIC_APP_URL: z.string().optional(),
|
||||
NEXT_PUBLIC_OPEN_SIGNUP: z.string().min(1).default("1"),
|
||||
NEXT_PUBLIC_EMAIL_R2_DOMAIN: z.string().min(1),
|
||||
NEXT_PUBLIC_EMAIL_R2_DOMAIN: z.string().optional(),
|
||||
},
|
||||
runtimeEnv: {
|
||||
NEXTAUTH_URL: process.env.NEXTAUTH_URL,
|
||||
|
||||
@@ -6,6 +6,7 @@ import("./env.mjs");
|
||||
const nextConfig = {
|
||||
reactStrictMode: true,
|
||||
swcMinify: true,
|
||||
output: "standalone",
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
"email": "email dev --dir emails --port 3333",
|
||||
"remove-content": "node ./setup.mjs"
|
||||
},
|
||||
"prisma": {
|
||||
"schema": "./prisma/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@auth/prisma-adapter": "^2.4.1",
|
||||
"@hookform/resolvers": "^3.9.0",
|
||||
|
||||
Reference in New Issue
Block a user