feat: 新增 docker hub
This commit is contained in:
47
Dockerfile
47
Dockerfile
@@ -1,33 +1,36 @@
|
|||||||
# ===== 构建阶段 =====
|
# ===== 构建阶段(Alpine 减小体积)=====
|
||||||
FROM node:22-bullseye AS builder
|
# 未传入的 build-arg 使用占位符,便于运行阶段用环境变量替换
|
||||||
|
# Supabase 构建时会校验 URL,故使用合法占位 URL,运行时再替换
|
||||||
|
FROM node:22-alpine AS builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ARG NEXT_PUBLIC_SUPABASE_URL
|
|
||||||
ARG NEXT_PUBLIC_SUPABASE_ANON_KEY
|
ARG NEXT_PUBLIC_SUPABASE_URL=https://runtime-replace.supabase.co
|
||||||
ARG NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY
|
ARG NEXT_PUBLIC_SUPABASE_ANON_KEY=__NEXT_PUBLIC_SUPABASE_ANON_KEY__
|
||||||
ARG NEXT_PUBLIC_GA_ID
|
ARG NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY=__NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY__
|
||||||
ARG NEXT_PUBLIC_GITHUB_LATEST_RELEASE_URL
|
ARG NEXT_PUBLIC_GA_ID=__NEXT_PUBLIC_GA_ID__
|
||||||
|
ARG NEXT_PUBLIC_GITHUB_LATEST_RELEASE_URL=__NEXT_PUBLIC_GITHUB_LATEST_RELEASE_URL__
|
||||||
ENV NEXT_PUBLIC_SUPABASE_URL=$NEXT_PUBLIC_SUPABASE_URL
|
ENV NEXT_PUBLIC_SUPABASE_URL=$NEXT_PUBLIC_SUPABASE_URL
|
||||||
ENV NEXT_PUBLIC_SUPABASE_ANON_KEY=$NEXT_PUBLIC_SUPABASE_ANON_KEY
|
ENV NEXT_PUBLIC_SUPABASE_ANON_KEY=$NEXT_PUBLIC_SUPABASE_ANON_KEY
|
||||||
ENV NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY=$NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY
|
ENV NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY=$NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY
|
||||||
ENV NEXT_PUBLIC_GA_ID=$NEXT_PUBLIC_GA_ID
|
ENV NEXT_PUBLIC_GA_ID=$NEXT_PUBLIC_GA_ID
|
||||||
ENV NEXT_PUBLIC_GITHUB_LATEST_RELEASE_URL=$NEXT_PUBLIC_GITHUB_LATEST_RELEASE_URL
|
ENV NEXT_PUBLIC_GITHUB_LATEST_RELEASE_URL=$NEXT_PUBLIC_GITHUB_LATEST_RELEASE_URL
|
||||||
|
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
RUN npm install --legacy-peer-deps
|
RUN npm ci --legacy-peer-deps
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN npx next build
|
RUN npx next build
|
||||||
# ===== 运行阶段 =====
|
|
||||||
FROM node:22-bullseye AS runner
|
# ===== 运行阶段(仅静态资源 + nginx,启动时替换占位符)=====
|
||||||
WORKDIR /app
|
FROM nginx:alpine AS runner
|
||||||
ENV NODE_ENV=production
|
WORKDIR /usr/share/nginx/html
|
||||||
ENV NEXT_PUBLIC_SUPABASE_URL=$NEXT_PUBLIC_SUPABASE_URL
|
|
||||||
ENV NEXT_PUBLIC_SUPABASE_ANON_KEY=$NEXT_PUBLIC_SUPABASE_ANON_KEY
|
COPY --from=builder /app/out .
|
||||||
ENV NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY=$NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
ENV NEXT_PUBLIC_GA_ID=$NEXT_PUBLIC_GA_ID
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
ENV NEXT_PUBLIC_GITHUB_LATEST_RELEASE_URL=$NEXT_PUBLIC_GITHUB_LATEST_RELEASE_URL
|
RUN chmod +x /entrypoint.sh
|
||||||
COPY --from=builder /app/package.json ./
|
|
||||||
COPY --from=builder /app/node_modules ./node_modules
|
|
||||||
COPY --from=builder /app/.next ./.next
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
|
||||||
CMD wget -qO- http://localhost:3000 || exit 1
|
CMD curl -f http://localhost:3000/ || exit 1
|
||||||
CMD ["npm", "start"]
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
|
|||||||
42
README.md
42
README.md
@@ -111,18 +111,27 @@ npm run build
|
|||||||
|
|
||||||
### Docker运行
|
### Docker运行
|
||||||
|
|
||||||
需先配置环境变量(与本地开发一致),否则构建出的镜像中 Supabase 等配置为空。可复制 `env.example` 为 `.env` 并填入实际值;若不用登录/反馈功能可留空。
|
镜像支持两种配置方式:
|
||||||
|
|
||||||
1. 构建镜像(构建时会读取当前环境或同目录 `.env` 中的变量)
|
- **构建时写入**:构建时通过 `--build-arg` 或 `.env` 传入 `NEXT_PUBLIC_*`,值会打进镜像,运行时无需再传。
|
||||||
|
- **运行时替换**:构建时不传(或使用默认占位符),启动容器时通过 `-e` 或 `--env-file` 传入,入口脚本会在启动 Nginx 前替换静态资源中的占位符。
|
||||||
|
|
||||||
|
可复制 `env.example` 为 `.env` 并填入实际值;若不用登录/反馈功能可留空。
|
||||||
|
|
||||||
|
1. 构建镜像
|
||||||
```bash
|
```bash
|
||||||
|
# 方式 A:运行时再注入配置(镜像内为占位符)
|
||||||
docker build -t real-time-fund .
|
docker build -t real-time-fund .
|
||||||
# 或通过 --build-arg 传入,例如:
|
|
||||||
# docker build -t real-time-fund --build-arg NEXT_PUBLIC_Supabase_URL=xxx --build-arg NEXT_PUBLIC_Supabase_ANON_KEY=xxx --build-arg NEXT_PUBLIC_GA_ID=G-xxxx .
|
# 方式 B:构建时写入配置
|
||||||
|
docker build -t real-time-fund --build-arg NEXT_PUBLIC_SUPABASE_URL=xxx --build-arg NEXT_PUBLIC_SUPABASE_ANON_KEY=xxx .
|
||||||
|
# 或依赖同目录 .env:docker compose build
|
||||||
```
|
```
|
||||||
|
|
||||||
2. 启动容器
|
2. 启动容器
|
||||||
```bash
|
```bash
|
||||||
docker run -d -p 3000:3000 --name fund real-time-fund
|
# 若构建时未写入配置,可在此注入(与 --env-file .env 二选一)
|
||||||
|
docker run -d -p 3000:3000 --name fund --env-file .env real-time-fund
|
||||||
```
|
```
|
||||||
|
|
||||||
#### docker-compose(会读取同目录 `.env` 作为 build-arg 与运行环境)
|
#### docker-compose(会读取同目录 `.env` 作为 build-arg 与运行环境)
|
||||||
@@ -131,6 +140,29 @@ docker run -d -p 3000:3000 --name fund real-time-fund
|
|||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Docker Hub
|
||||||
|
|
||||||
|
镜像已发布至 Docker Hub,可直接拉取运行,无需本地构建。
|
||||||
|
|
||||||
|
1. **拉取镜像**
|
||||||
|
```bash
|
||||||
|
docker pull hzm0321/real-time-fund:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **启动容器**
|
||||||
|
访问 [http://localhost:3000](http://localhost:3000) 即可使用。
|
||||||
|
```bash
|
||||||
|
docker run -d -p 3000:3000 --name real-time-fund --restart always hzm0321/real-time-fund:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **使用自定义环境变量(运行时替换)**
|
||||||
|
镜像内已预置占位符,启动时通过环境变量即可覆盖,无需重新构建。例如使用本地 `.env`:
|
||||||
|
```bash
|
||||||
|
docker run -d -p 3000:3000 --name real-time-fund --restart always --env-file .env hzm0321/real-time-fund:latest
|
||||||
|
```
|
||||||
|
或单独指定变量:`-e NEXT_PUBLIC_SUPABASE_URL=xxx -e NEXT_PUBLIC_SUPABASE_ANON_KEY=xxx`。
|
||||||
|
变量名与本地开发一致:`NEXT_PUBLIC_SUPABASE_URL`、`NEXT_PUBLIC_SUPABASE_ANON_KEY`、`NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY`、`NEXT_PUBLIC_GA_ID`、`NEXT_PUBLIC_GITHUB_LATEST_RELEASE_URL`。
|
||||||
|
|
||||||
## 📖 使用说明
|
## 📖 使用说明
|
||||||
|
|
||||||
1. **添加基金**:在顶部输入框输入 6 位基金代码(如 `110022`),点击“添加”。
|
1. **添加基金**:在顶部输入框输入 6 位基金代码(如 `110022`),点击“添加”。
|
||||||
|
|||||||
26
entrypoint.sh
Normal file
26
entrypoint.sh
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# 在启动 Nginx 前,将静态资源中的占位符替换为运行时环境变量
|
||||||
|
set -e
|
||||||
|
|
||||||
|
HTML_ROOT="/usr/share/nginx/html"
|
||||||
|
|
||||||
|
# 转义 sed 替换串中的特殊字符:\ & |
|
||||||
|
escape_sed() {
|
||||||
|
printf '%s' "$1" | sed 's/\\/\\\\/g; s/&/\\&/g; s/|/\\|/g'
|
||||||
|
}
|
||||||
|
|
||||||
|
# 占位符与环境变量对应(占位符名 = 变量名)
|
||||||
|
replace_var() {
|
||||||
|
placeholder="$1"
|
||||||
|
value=$(escape_sed "${2:-}")
|
||||||
|
find "$HTML_ROOT" -type f \( -name '*.js' -o -name '*.html' \) -exec sed -i "s|${placeholder}|${value}|g" {} \;
|
||||||
|
}
|
||||||
|
|
||||||
|
# URL 构建时使用合法占位,此处替换为运行时环境变量
|
||||||
|
replace_var "https://runtime-replace.supabase.co" "${NEXT_PUBLIC_SUPABASE_URL}"
|
||||||
|
replace_var "__NEXT_PUBLIC_SUPABASE_ANON_KEY__" "${NEXT_PUBLIC_SUPABASE_ANON_KEY}"
|
||||||
|
replace_var "__NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY__" "${NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY}"
|
||||||
|
replace_var "__NEXT_PUBLIC_GA_ID__" "${NEXT_PUBLIC_GA_ID}"
|
||||||
|
replace_var "__NEXT_PUBLIC_GITHUB_LATEST_RELEASE_URL__" "${NEXT_PUBLIC_GITHUB_LATEST_RELEASE_URL}"
|
||||||
|
|
||||||
|
exec nginx -g "daemon off;"
|
||||||
15
nginx.conf
Normal file
15
nginx.conf
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
server {
|
||||||
|
listen 3000;
|
||||||
|
server_name localhost;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri.html $uri/ /index.html =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user