增加lite镜像

This commit is contained in:
mtvpls
2026-03-27 15:15:59 +08:00
parent 068459cc5f
commit 8acc50b198
5 changed files with 235 additions and 9 deletions

View File

@@ -1,2 +1,5 @@
.env .env
.env*.local .env*.local
public/screenshot1.png
public/screenshot2.png
public/screenshot3.png

125
.github/workflows/docker-image-lite.yml vendored Normal file
View File

@@ -0,0 +1,125 @@
name: Build & Push Docker lite image
on:
workflow_dispatch:
inputs:
tag:
description: 'Docker 标签'
required: false
default: 'latest'
type: string
push:
branches: [ main ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: write
packages: write
actions: write
jobs:
build:
strategy:
matrix:
include:
- platform: linux/amd64
os: ubuntu-latest
- platform: linux/arm64
os: ubuntu-24.04-arm
runs-on: ${{ matrix.os }}
steps:
- name: Prepare platform name
run: |
echo "PLATFORM_NAME=${{ matrix.platform }}" | sed 's|/|-|g' >> $GITHUB_ENV
- name: Checkout source code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/mtvpls/moontvplus-lite
tags: |
type=raw,value=${{ github.event.inputs.tag || 'latest' }}
- name: Build and push by digest
id: build
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile.lite
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
tags: ghcr.io/mtvpls/moontvplus-lite:${{ github.event.inputs.tag || 'latest' }}
outputs: type=image,name=ghcr.io/mtvpls/moontvplus-lite,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ env.PLATFORM_NAME }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
runs-on: ubuntu-latest
needs:
- build
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create -t ghcr.io/mtvpls/moontvplus-lite:${{ github.event.inputs.tag || 'latest' }} \
$(printf 'ghcr.io/mtvpls/moontvplus-lite@sha256:%s ' *)
cleanup-refresh:
runs-on: ubuntu-latest
needs:
- merge
if: always()
steps:
- name: Delete workflow runs
uses: Mattraks/delete-workflow-runs@main
with:
token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.repository }}
retain_days: 0
keep_minimum_runs: 2

52
Dockerfile.lite Normal file
View File

@@ -0,0 +1,52 @@
# ---- 第 1 阶段:安装依赖 ----
FROM node:24-alpine AS deps
RUN corepack enable && corepack prepare pnpm@latest --activate
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
# ---- 第 2 阶段:构建项目 ----
FROM node:24-alpine AS builder
RUN corepack enable && corepack prepare pnpm@latest --activate
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV DOCKER_ENV=true
ENV MOONTV_LITE=true
ENV WATCH_ROOM_ENABLED=false
ENV WATCH_ROOM_SERVER_TYPE=external
RUN pnpm run build
# ---- 第 3 阶段:生成 lite 运行时镜像 ----
FROM node:24-alpine AS runner
RUN addgroup -g 1001 -S nodejs && adduser -u 1001 -S nextjs -G nodejs
WORKDIR /app
ENV NODE_ENV=production
ENV HOSTNAME=0.0.0.0
ENV PORT=3000
ENV DOCKER_ENV=true
ENV MOONTV_LITE=true
ENV WATCH_ROOM_ENABLED=false
ENV WATCH_ROOM_SERVER_TYPE=external
# standalone 输出自带运行所需的最小服务端依赖
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/scripts ./scripts
COPY --from=builder --chown=nextjs:nodejs /app/start.js ./start.js
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
CMD ["node", "start.js"]

View File

@@ -285,6 +285,44 @@ services:
- UPSTASH_TOKEN=上面的 TOKEN - UPSTASH_TOKEN=上面的 TOKEN
``` ```
#### Lite 镜像说明
`ghcr.io/mtvpls/moontvplus-lite:latest` 为更小的镜像,但不支持启动内置观影室服务。
示例:
```yml
services:
moontv-core:
image: ghcr.io/mtvpls/moontvplus-lite:latest
container_name: moontv-core
restart: on-failure
ports:
- '3000:3000'
environment:
- USERNAME=admin
- PASSWORD=admin_password
- NEXT_PUBLIC_STORAGE_TYPE=kvrocks
- KVROCKS_URL=redis://moontv-kvrocks:6666
networks:
- moontv-network
depends_on:
- moontv-kvrocks
moontv-kvrocks:
image: apache/kvrocks
container_name: moontv-kvrocks
restart: unless-stopped
volumes:
- kvrocks-data:/var/lib/kvrocks/data
networks:
- moontv-network
networks:
moontv-network:
driver: bridge
volumes:
kvrocks-data:
```
## 配置文件 ## 配置文件
完成部署后为空壳应用,无播放源,需要站长在管理后台的配置文件设置中填写配置文件,本版本已不支持无数据库运行。 完成部署后为空壳应用,无播放源,需要站长在管理后台的配置文件设置中填写配置文件,本版本已不支持无数据库运行。

View File

@@ -3,7 +3,7 @@
import { NextRequest, NextResponse } from 'next/server'; import { NextRequest, NextResponse } from 'next/server';
import { getConfig } from '@/lib/config'; import { getConfig } from '@/lib/config';
import { CURRENT_VERSION } from '@/lib/version' import { CURRENT_VERSION } from '@/lib/version';
export const runtime = 'nodejs'; export const runtime = 'nodejs';
export const dynamic = 'force-dynamic'; // 禁用缓存 export const dynamic = 'force-dynamic'; // 禁用缓存
@@ -13,14 +13,22 @@ export async function GET(request: NextRequest) {
const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage'; const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
// 观影室配置从环境变量读取 const isLiteMode = process.env.MOONTV_LITE === 'true';
// Lite 镜像不暴露内置观影室能力,避免前端尝试连接本地 Socket.IO 服务
// 注意:不要暴露 externalServerAuth 到前端,这是敏感凭据 // 注意:不要暴露 externalServerAuth 到前端,这是敏感凭据
const watchRoomConfig = { const watchRoomConfig = isLiteMode
enabled: process.env.WATCH_ROOM_ENABLED === 'true', ? {
serverType: (process.env.WATCH_ROOM_SERVER_TYPE as 'internal' | 'external') || 'internal', enabled: false,
externalServerUrl: process.env.WATCH_ROOM_EXTERNAL_SERVER_URL, serverType: 'external' as const,
// externalServerAuth 不应该暴露给前端 externalServerUrl: undefined,
}; }
: {
enabled: process.env.WATCH_ROOM_ENABLED === 'true',
serverType:
(process.env.WATCH_ROOM_SERVER_TYPE as 'internal' | 'external') || 'internal',
externalServerUrl: process.env.WATCH_ROOM_EXTERNAL_SERVER_URL,
};
// 如果使用 localStorage返回默认配置 // 如果使用 localStorage返回默认配置
if (storageType === 'localstorage') { if (storageType === 'localstorage') {