feat: bundle multi-arch nginx for native fnOS stage 2
This commit is contained in:
@@ -11,22 +11,35 @@
|
|||||||
|
|
||||||
构建过程不再引用 `F:\Fonu-main\havline`。
|
构建过程不再引用 `F:\Fonu-main\havline`。
|
||||||
|
|
||||||
阶段一范围:
|
阶段二范围:
|
||||||
|
|
||||||
- Go 主程序原生运行
|
- Go 主程序原生运行
|
||||||
- 统一网关 `/app/havline`
|
- 统一网关 `/app/havline`
|
||||||
- Unix Socket `app.sock`
|
- Unix Socket `app.sock`
|
||||||
- `cmd/main` 启动、停止和状态检查
|
- `cmd/main` 启动、停止和状态检查
|
||||||
- amd64 与 arm64 双架构二进制
|
- amd64 与 arm64 双架构二进制
|
||||||
|
- Nginx amd64 与 arm64 双架构二进制
|
||||||
|
- Nginx 依赖库与 `mime.types`
|
||||||
|
- HTTP 18080 与 HTTPS 9443
|
||||||
|
|
||||||
当前不包含:
|
当前不包含:
|
||||||
|
|
||||||
- Nginx 二进制
|
|
||||||
- frpc
|
- frpc
|
||||||
- cloudflared
|
- cloudflared
|
||||||
|
|
||||||
这些依赖将在后续阶段加入。
|
这些依赖将在后续阶段加入。
|
||||||
|
|
||||||
|
## 构建前置条件
|
||||||
|
|
||||||
|
构建脚本需要本地存在用于提取 Nginx 的 Havline 镜像:
|
||||||
|
|
||||||
|
```text
|
||||||
|
jayhub.top/mrlee/havline:1.9.0 amd64
|
||||||
|
havline:1.9.0 arm64
|
||||||
|
```
|
||||||
|
|
||||||
|
如果本地没有对应架构镜像,先加载 amd64 与 arm64 镜像归档。
|
||||||
|
|
||||||
## 构建
|
## 构建
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
@@ -43,5 +56,17 @@ dist/havline-native-1.9.0.fpk
|
|||||||
构建脚本会:
|
构建脚本会:
|
||||||
|
|
||||||
1. 使用 `VITE_BASE_PATH=/app/havline/` 构建前端;
|
1. 使用 `VITE_BASE_PATH=/app/havline/` 构建前端;
|
||||||
2. 交叉编译 amd64 与 arm64 Go 二进制;
|
2. 从本地镜像提取 amd64 与 arm64 Nginx 及依赖库;
|
||||||
3. 调用 `fnpack build` 打包。
|
3. 交叉编译 amd64 与 arm64 Go 二进制;
|
||||||
|
4. 调用 `fnpack build` 打包。
|
||||||
|
|
||||||
|
## 真机注意
|
||||||
|
|
||||||
|
当前 Nginx 来自 Debian 12,依赖目标系统 glibc。飞牛设备建议满足:
|
||||||
|
|
||||||
|
```text
|
||||||
|
glibc >= 2.36
|
||||||
|
```
|
||||||
|
|
||||||
|
如果目标设备 glibc 版本较低,需要改为静态编译 Nginx 或打包完整
|
||||||
|
loader 与 libc。
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ http {
|
|||||||
include ` + absNginxPath(cfg.NginxMimeTypes) + `;
|
include ` + absNginxPath(cfg.NginxMimeTypes) + `;
|
||||||
default_type application/octet-stream;
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
client_body_temp_path ` + absNginxPath(filepath.Join(cfg.NginxDir(), "temp", "client_body_temp")) + `;
|
||||||
|
proxy_temp_path ` + absNginxPath(filepath.Join(cfg.NginxDir(), "temp", "proxy_temp")) + `;
|
||||||
|
fastcgi_temp_path ` + absNginxPath(filepath.Join(cfg.NginxDir(), "temp", "fastcgi_temp")) + `;
|
||||||
|
uwsgi_temp_path ` + absNginxPath(filepath.Join(cfg.NginxDir(), "temp", "uwsgi_temp")) + `;
|
||||||
|
scgi_temp_path ` + absNginxPath(filepath.Join(cfg.NginxDir(), "temp", "scgi_temp")) + `;
|
||||||
|
|
||||||
log_format havline_access '$time_iso8601 $host $server_port $request_method $request_uri $status $request_time $remote_addr $upstream_addr $request_length $bytes_sent';
|
log_format havline_access '$time_iso8601 $host $server_port $request_method $request_uri $status $request_time $remote_addr $upstream_addr $request_length $bytes_sent';
|
||||||
access_log ` + absNginxPath(filepath.Join(cfg.LogsDir(), "access.log")) + ` havline_access;
|
access_log ` + absNginxPath(filepath.Join(cfg.LogsDir(), "access.log")) + ` havline_access;
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,55 @@ function Copy-Tree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Resolve-DockerCli {
|
||||||
|
if ($env:DOCKER_BIN) { return $env:DOCKER_BIN }
|
||||||
|
$command = Get-Command docker -ErrorAction SilentlyContinue
|
||||||
|
if ($command) { return $command.Source }
|
||||||
|
$default = "C:\Program Files\Docker\Docker\resources\bin\docker.exe"
|
||||||
|
if (Test-Path -LiteralPath $default) { return $default }
|
||||||
|
throw "找不到 docker 命令"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Export-Nginx {
|
||||||
|
param(
|
||||||
|
[string]$DockerBin,
|
||||||
|
[string]$Platform,
|
||||||
|
[string]$Arch,
|
||||||
|
[string]$Image,
|
||||||
|
[string]$OutputDir
|
||||||
|
)
|
||||||
|
|
||||||
|
$archInfo = (& $DockerBin image inspect $Image --format '{{.Architecture}}' 2>$null)
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "找不到 Nginx 来源镜像:$Image"
|
||||||
|
}
|
||||||
|
if ($archInfo.Trim() -ne $Arch) {
|
||||||
|
throw "镜像架构不匹配:$Image 是 $($archInfo.Trim()),需要 $Arch"
|
||||||
|
}
|
||||||
|
|
||||||
|
$archDir = Join-Path $OutputDir $Arch
|
||||||
|
New-Item -ItemType Directory -Force $archDir | Out-Null
|
||||||
|
$script = @'
|
||||||
|
set -e
|
||||||
|
mkdir -p /out/lib
|
||||||
|
cp /usr/sbin/nginx /out/nginx
|
||||||
|
cp /etc/nginx/mime.types /out/mime.types
|
||||||
|
ldd /usr/sbin/nginx | awk '/=> \// {print $3} /^\// {print $1}' | sort -u | while read lib; do
|
||||||
|
case "$(basename "$lib")" in
|
||||||
|
libc.so.6|ld-linux-*.so.*) continue ;;
|
||||||
|
esac
|
||||||
|
cp "$lib" /out/lib/
|
||||||
|
done
|
||||||
|
'@
|
||||||
|
|
||||||
|
& $DockerBin run --rm --platform $Platform -v "${archDir}:/out" --entrypoint sh $Image -c $script
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "提取 $Arch Nginx 失败,退出码:$LASTEXITCODE"
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy-Item -LiteralPath (Join-Path $archDir "mime.types") -Destination (Join-Path $OutputDir "mime.types") -Force
|
||||||
|
}
|
||||||
|
|
||||||
if (-not (Test-Path -LiteralPath $project)) {
|
if (-not (Test-Path -LiteralPath $project)) {
|
||||||
throw "找不到 Native 应用工程:$project"
|
throw "找不到 Native 应用工程:$project"
|
||||||
}
|
}
|
||||||
@@ -67,6 +116,11 @@ if ($LASTEXITCODE -ge 8) {
|
|||||||
Copy-Tree -Source (Join-Path $mainRepo "migrations") -Destination (Join-Path $stage "app\migrations")
|
Copy-Tree -Source (Join-Path $mainRepo "migrations") -Destination (Join-Path $stage "app\migrations")
|
||||||
Copy-Tree -Source (Join-Path $mainRepo "web\assets\image") -Destination (Join-Path $stage "app\web\assets\image")
|
Copy-Tree -Source (Join-Path $mainRepo "web\assets\image") -Destination (Join-Path $stage "app\web\assets\image")
|
||||||
|
|
||||||
|
$serverDir = Join-Path $stage "app\server"
|
||||||
|
$dockerBin = Resolve-DockerCli
|
||||||
|
Export-Nginx -DockerBin $dockerBin -Platform "linux/amd64" -Arch "amd64" -Image "jayhub.top/mrlee/havline:$version" -OutputDir $serverDir
|
||||||
|
Export-Nginx -DockerBin $dockerBin -Platform "linux/arm64" -Arch "arm64" -Image "havline:$version" -OutputDir $serverDir
|
||||||
|
|
||||||
$env:CGO_ENABLED = "0"
|
$env:CGO_ENABLED = "0"
|
||||||
$env:GOOS = "linux"
|
$env:GOOS = "linux"
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,18 @@ if [ ! -f "$BIN" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
chmod +x "$BIN"
|
NGINX_BIN="$TRIM_APPDEST/server/$ARCH_DIR/nginx"
|
||||||
|
if [ ! -f "$NGINX_BIN" ]; then
|
||||||
|
echo "找不到 Nginx 二进制:$NGINX_BIN" > "$TRIM_TEMP_LOGFILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
MIME_TYPES="$TRIM_APPDEST/server/mime.types"
|
||||||
|
if [ ! -f "$MIME_TYPES" ]; then
|
||||||
|
echo "找不到 Nginx mime.types:$MIME_TYPES" > "$TRIM_TEMP_LOGFILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod +x "$BIN" "$NGINX_BIN"
|
||||||
echo "Havline 数据目录已准备:$TRIM_PKGVAR"
|
echo "Havline 数据目录已准备:$TRIM_PKGVAR"
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -58,8 +58,12 @@ start_app() {
|
|||||||
export HAVLINE_GATEWAY_SOCKET="$SOCKET_PATH"
|
export HAVLINE_GATEWAY_SOCKET="$SOCKET_PATH"
|
||||||
export HAVLINE_GATEWAY_PREFIX="/app/havline"
|
export HAVLINE_GATEWAY_PREFIX="/app/havline"
|
||||||
export HAVLINE_UPDATER_SOCKET=""
|
export HAVLINE_UPDATER_SOCKET=""
|
||||||
|
export HAVLINE_NGINX_BIN="$TRIM_APPDEST/server/$arch/nginx"
|
||||||
|
export HAVLINE_NGINX_MIME_TYPES="$TRIM_APPDEST/server/mime.types"
|
||||||
|
export HAVLINE_NGINX_PID="$TRIM_PKGVAR/nginx/nginx.pid"
|
||||||
export HAVLINE_NGINX_HTTP_PORT="${wizard_nginx_http_port:-18080}"
|
export HAVLINE_NGINX_HTTP_PORT="${wizard_nginx_http_port:-18080}"
|
||||||
export HAVLINE_NGINX_HTTPS_PORT="${wizard_nginx_https_port:-9443}"
|
export HAVLINE_NGINX_HTTPS_PORT="${wizard_nginx_https_port:-9443}"
|
||||||
|
export LD_LIBRARY_PATH="$TRIM_APPDEST/server/$arch/lib:${LD_LIBRARY_PATH:-}"
|
||||||
export TZ="${wizard_timezone:-Asia/Shanghai}"
|
export TZ="${wizard_timezone:-Asia/Shanghai}"
|
||||||
|
|
||||||
if [ -n "${wizard_initial_admin_password:-}" ]; then
|
if [ -n "${wizard_initial_admin_password:-}" ]; then
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
appname = havline
|
appname = havline
|
||||||
version = 1.9.0
|
version = 1.9.0
|
||||||
display_name = Havline
|
display_name = Havline
|
||||||
desc = NAS 公网访问管理:原生应用阶段一
|
desc = NAS 公网访问管理:原生应用阶段二
|
||||||
platform = all
|
platform = all
|
||||||
source = thirdparty
|
source = thirdparty
|
||||||
maintainer = Havline
|
maintainer = Havline
|
||||||
@@ -11,4 +11,4 @@ desktop_uidir = ui
|
|||||||
desktop_applaunchname = havline.main
|
desktop_applaunchname = havline.main
|
||||||
ctl_stop = true
|
ctl_stop = true
|
||||||
os_min_version = 1.1.3100
|
os_min_version = 1.1.3100
|
||||||
changelog = 原生应用阶段一:Go 主程序、统一网关和启停脚本
|
changelog = 原生应用阶段二:Nginx amd64/arm64 双架构打包
|
||||||
|
|||||||
Reference in New Issue
Block a user