feat: add initial RISC-V image support (#725)
Some checks failed
Security / Dependency Review (push) Waiting to run
Security / CodeQL (java-kotlin) (push) Waiting to run
Security / CodeQL (javascript-typescript) (push) Waiting to run
Security / CodeQL (python) (push) Waiting to run
Deploy Docs / build (push) Has been cancelled
Deploy Docs / Deploy (push) Has been cancelled

* feat: add initial RISC-V image support

Signed-off-by: FenjuFu <92919259+FenjuFu@users.noreply.github.com>

* chore(ci): tighten riscv64 image guardrails

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

---------

Signed-off-by: FenjuFu <92919259+FenjuFu@users.noreply.github.com>
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
Co-authored-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
This commit is contained in:
FenjuFu 2026-08-24 16:37:34 +08:00 committed by GitHub
parent 1b7a6d5544
commit f846da230c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 146 additions and 14 deletions

View file

@ -13,9 +13,6 @@ permissions:
contents: read contents: read
packages: write packages: write
env:
DOCKER_PLATFORMS: linux/amd64,linux/arm64
jobs: jobs:
publish: publish:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -31,16 +28,19 @@ jobs:
- name: server - name: server
context: ./server context: ./server
dockerfile: ./server/Dockerfile dockerfile: ./server/Dockerfile
platforms: linux/amd64,linux/arm64,linux/riscv64
image: ghcr.io/${{ github.repository_owner }}/skillhub-server image: ghcr.io/${{ github.repository_owner }}/skillhub-server
mirror_image: skillhub-server mirror_image: skillhub-server
- name: web - name: web
context: ./web context: ./web
dockerfile: ./web/Dockerfile dockerfile: ./web/Dockerfile
platforms: linux/amd64,linux/arm64,linux/riscv64
image: ghcr.io/${{ github.repository_owner }}/skillhub-web image: ghcr.io/${{ github.repository_owner }}/skillhub-web
mirror_image: skillhub-web mirror_image: skillhub-web
- name: scanner - name: scanner
context: ./scanner context: ./scanner
dockerfile: ./scanner/Dockerfile dockerfile: ./scanner/Dockerfile
platforms: linux/amd64,linux/arm64
image: ghcr.io/${{ github.repository_owner }}/skillhub-scanner image: ghcr.io/${{ github.repository_owner }}/skillhub-scanner
mirror_image: skillhub-scanner mirror_image: skillhub-scanner
@ -109,7 +109,7 @@ jobs:
with: with:
context: ${{ matrix.context }} context: ${{ matrix.context }}
file: ${{ matrix.dockerfile }} file: ${{ matrix.dockerfile }}
platforms: ${{ env.DOCKER_PLATFORMS }} platforms: ${{ matrix.platforms }}
push: true push: true
provenance: false provenance: false
sbom: false sbom: false

65
.github/workflows/riscv64-images.yml vendored Normal file
View file

@ -0,0 +1,65 @@
name: RISC-V Images
on:
pull_request:
paths:
- '.github/workflows/riscv64-images.yml'
- '.github/workflows/publish-images.yml'
- 'server/**'
- 'web/**'
workflow_dispatch:
permissions:
contents: read
jobs:
build:
name: Build ${{ matrix.name }} (linux/riscv64)
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- name: server
context: ./server
dockerfile: ./server/Dockerfile
- name: web
context: ./web
dockerfile: ./web/Dockerfile
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: riscv64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build RISC-V image
uses: docker/build-push-action@v6
with:
context: ${{ matrix.context }}
file: ${{ matrix.dockerfile }}
platforms: linux/riscv64
load: true
tags: skillhub-${{ matrix.name }}:riscv64-ci
cache-from: type=gha,scope=riscv64-${{ matrix.name }}
cache-to: type=gha,mode=max,scope=riscv64-${{ matrix.name }}
- name: Verify image architecture and runtime
shell: bash
run: |
image="skillhub-${{ matrix.name }}:riscv64-ci"
test "$(docker image inspect "$image" --format '{{.Architecture}}')" = riscv64
case "${{ matrix.name }}" in
server)
docker run --rm --platform linux/riscv64 --entrypoint java "$image" -version
;;
web)
docker run --rm --platform linux/riscv64 --entrypoint nginx "$image" -v
;;
esac

View file

@ -236,7 +236,9 @@ frontend schema, and fails if the checked-in SDK is stale.
Published runtime images are built by GitHub Actions and pushed to GHCR. Published runtime images are built by GitHub Actions and pushed to GHCR.
This is the supported path for anyone who wants a ready-to-use local This is the supported path for anyone who wants a ready-to-use local
environment without building the backend or frontend on their machine. environment without building the backend or frontend on their machine.
Published images target both `linux/amd64` and `linux/arm64`. Published server and web images target `linux/amd64`, `linux/arm64`, and
`linux/riscv64`; the scanner image currently targets `linux/amd64` and
`linux/arm64`.
**Quick deployment with curl:** **Quick deployment with curl:**

View file

@ -136,7 +136,8 @@ skillhub/
- 开发路径:`make dev-all`。前后端在宿主机运行,`docker-compose.yml` 只负责 PostgreSQL、Redis、MinIO。 - 开发路径:`make dev-all`。前后端在宿主机运行,`docker-compose.yml` 只负责 PostgreSQL、Redis、MinIO。
- 交付路径GitHub Actions 构建并发布 `server` / `web` 镜像;用户通过 `compose.release.yml` 在本地一键拉起前后端容器和基础服务。 - 交付路径GitHub Actions 构建并发布 `server` / `web` 镜像;用户通过 `compose.release.yml` 在本地一键拉起前后端容器和基础服务。
- 发布镜像为多架构 manifest至少覆盖 `linux/amd64``linux/arm64` - 发布镜像为多架构 manifest`server` / `web` 覆盖 `linux/amd64``linux/arm64`
`linux/riscv64``scanner` 暂保持 `linux/amd64``linux/arm64`
单机运行时统一入口: 单机运行时统一入口:
- `http://localhost/` → Web 容器Nginx - `http://localhost/` → Web 容器Nginx
@ -169,7 +170,8 @@ skillhub/
- 数据库迁移Flyway - 数据库迁移Flyway
- 认证Spring Security OAuth2 Client一期 GitHub - 认证Spring Security OAuth2 Client一期 GitHub
- 镜像发布GitHub Actions 推送至 GHCR默认维护 `edge` 与语义化版本标签 - 镜像发布GitHub Actions 推送至 GHCR默认维护 `edge` 与语义化版本标签
- 运行时兼容:发布镜像默认输出 `linux/amd64` + `linux/arm64` 多架构 manifest - 运行时兼容:`server` / `web` 发布镜像默认输出 `linux/amd64` + `linux/arm64` +
`linux/riscv64` 多架构 manifest`scanner` 暂保持 `linux/amd64` + `linux/arm64`
## 11. Repository / Query Boundary 约定 ## 11. Repository / Query Boundary 约定

View file

@ -10,7 +10,8 @@
- 单机交付环境:`docker compose --env-file .env.release -f compose.release.yml up -d` - 单机交付环境:`docker compose --env-file .env.release -f compose.release.yml up -d`
- 前端和后端都运行在容器内 - 前端和后端都运行在容器内
- 使用 GitHub Actions 发布到 GHCR 的镜像 - 使用 GitHub Actions 发布到 GHCR 的镜像
- 默认发布 `linux/amd64``linux/arm64` 多架构镜像 - 默认发布多架构镜像:`server` / `web` 覆盖 `linux/amd64``linux/arm64`
`linux/riscv64``scanner` 暂保持 `linux/amd64``linux/arm64`
- PostgreSQL、Redis 与应用容器一起通过 Compose 启动 - PostgreSQL、Redis 与应用容器一起通过 Compose 启动
不再维护本地构建整套 demo 容器的中间模式,也不再保留 `docker-compose.prod.yml` 不再维护本地构建整套 demo 容器的中间模式,也不再保留 `docker-compose.prod.yml`
@ -205,7 +206,8 @@ Sentinel 配置优先于 Cluster 和单机 `host`/`port`。在 Kubernetes 等 Se
- `ghcr.io/iflytek/skillhub-server` - `ghcr.io/iflytek/skillhub-server`
- `ghcr.io/iflytek/skillhub-web` - `ghcr.io/iflytek/skillhub-web`
5. 写入 `edge` / `vX.Y.Z` / `latest` / `sha-*` 标签 5. 写入 `edge` / `vX.Y.Z` / `latest` / `sha-*` 标签
6. 同时发布 `linux/amd64``linux/arm64` manifest避免 Apple Silicon / ARM 主机依赖模拟层 6. 同时发布多架构 manifest`server` / `web` 覆盖 `linux/amd64``linux/arm64`
`linux/riscv64``scanner` 暂保持 `linux/amd64``linux/arm64`
## 7 配置管理 ## 7 配置管理

51
docs/RISCV64.md Normal file
View file

@ -0,0 +1,51 @@
# RISC-V (`linux/riscv64`) support
## Current scope
RISC-V support is incremental. The SkillHub server and web images have
`linux/riscv64` build and runtime paths. The security scanner and the complete
Docker Compose deployment are not yet supported on RISC-V.
| Component | `linux/riscv64` status | Notes |
| --- | --- | --- |
| `skillhub-server` | Supported | The architecture-neutral Java 21 JAR is built on the Buildx host and copied into the target-architecture Eclipse Temurin runtime. |
| `skillhub-web` | Supported | Static assets are built on the Buildx host and served by a target-architecture Nginx runtime. |
| `skillhub-scanner` | Not yet verified | Its Python dependency tree still needs a native-extension and runtime audit. |
| PostgreSQL 16 and Redis 7 | Upstream images available | Keep these images explicitly pinned and verify them on the target board before production use. |
| Complete Compose stack | Unsupported | `compose.release.yml` starts the unverified scanner, so do not deploy it unchanged on RISC-V. |
## Build the supported images
Buildx can create both images from an AMD64 or ARM64 host. Register a RISC-V
QEMU handler before running these commands when the host is not RISC-V:
```bash
docker run --privileged --rm tonistiigi/binfmt --install riscv64
docker buildx create --use --name skillhub-riscv64
docker buildx build \
--platform linux/riscv64 \
--file server/Dockerfile \
--tag skillhub-server:riscv64 \
--load \
server
docker buildx build \
--platform linux/riscv64 \
--file web/Dockerfile \
--tag skillhub-web:riscv64 \
--load \
web
```
The release workflow publishes `linux/amd64`, `linux/arm64`, and
`linux/riscv64` variants for `skillhub-server` and `skillhub-web`. The scanner
remains limited to its existing AMD64/ARM64 platform list.
## Verification boundary
The pull-request workflow builds both supported target images, checks their OCI
architecture metadata, and executes the Java and Nginx runtimes under RISC-V
emulation. This is a component-image guardrail, not a full-stack integration
test. A native RISC-V smoke test with PostgreSQL, Redis, object storage, and a
verified scanner remains required before claiming complete deployment support.

View file

@ -1,5 +1,6 @@
# ---- Build Stage ---- # Build the architecture-neutral JAR on the Buildx host. This avoids emulating
FROM eclipse-temurin:21-jdk-alpine AS build # the complete Maven build when the target image is linux/riscv64.
FROM --platform=$BUILDPLATFORM eclipse-temurin:21-jdk-alpine AS build
WORKDIR /app WORKDIR /app
# Cache dependencies # Cache dependencies
@ -19,8 +20,14 @@ COPY . .
RUN ./mvnw package -DskipTests -B RUN ./mvnw package -DskipTests -B
# ---- Runtime Stage ---- # ---- Runtime Stage ----
FROM eclipse-temurin:21-jre-alpine # The Noble variant publishes a linux/riscv64 image; the Alpine JRE currently
RUN addgroup -S app && adduser -S app -G app # used by this project is limited to amd64 and arm64.
FROM eclipse-temurin:21-jre-noble
RUN apt-get update && \
apt-get install -y --no-install-recommends wget && \
rm -rf /var/lib/apt/lists/* && \
groupadd --system app && \
useradd --system --gid app --create-home app
WORKDIR /app WORKDIR /app
COPY --from=build /app/skillhub-app/target/*.jar app.jar COPY --from=build /app/skillhub-app/target/*.jar app.jar

View file

@ -1,4 +1,7 @@
FROM node:22-alpine AS build # The frontend output is static and architecture-neutral. Build it on the
# Buildx host so linux/riscv64 does not depend on a target-architecture Node.js
# image; only the multi-architecture Nginx runtime is target-specific.
FROM --platform=$BUILDPLATFORM node:22-alpine AS build
RUN corepack enable RUN corepack enable
WORKDIR /app WORKDIR /app
COPY package.json pnpm-lock.yaml ./ COPY package.json pnpm-lock.yaml ./