Compare commits
2 Commits
97cae698db
...
1ac6435c3f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ac6435c3f | ||
|
|
80ecad6ddd |
@@ -15,15 +15,6 @@ COPY --from=syslibs /usr/lib/x86_64-linux-gnu/libfontconfig.so* /usr/lib/x86_64-
|
||||
COPY --from=syslibs /usr/lib/x86_64-linux-gnu/libxml2.so* /usr/lib/x86_64-linux-gnu/
|
||||
COPY --from=syslibs /usr/lib/x86_64-linux-gnu/libfribidi.so* /usr/lib/x86_64-linux-gnu/
|
||||
|
||||
# The standalone SEA binary contains Node.js runtime, src/, package.json, and all app logic
|
||||
COPY dist/dashback ./dist/dashback
|
||||
|
||||
# Only native C++ addon packages required by OS dynamic linker (dlopen)
|
||||
COPY node_modules/better-sqlite3 ./node_modules/better-sqlite3
|
||||
COPY node_modules/canvas ./node_modules/canvas
|
||||
COPY node_modules/@img ./node_modules/@img
|
||||
COPY node_modules/sharp ./node_modules/sharp
|
||||
|
||||
# Set production defaults: port 4208
|
||||
ENV NODE_ENV=production \
|
||||
HOST=0.0.0.0 \
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
services:
|
||||
dashback:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: dashback:latest
|
||||
container_name: dashback
|
||||
read_only: true
|
||||
user: "${UID:-1000}:${GID:-1000}"
|
||||
tmpfs:
|
||||
- /tmp:rw,noexec,nosuid,size=512m
|
||||
- /run:rw,noexec,nosuid,size=16m
|
||||
networks:
|
||||
- dash_net
|
||||
ports:
|
||||
- "127.0.0.1:4208:4208"
|
||||
environment:
|
||||
- HOST=0.0.0.0
|
||||
- PORT=4208
|
||||
- HTTPS_PORT=0
|
||||
- MSSQL_SERVER=sql_server
|
||||
- HEALTH_MONITOR_ENABLED=false
|
||||
- SQLITE_PATH=/app/data/dash.db
|
||||
- STORAGE_DIR=/app/data/storage
|
||||
- BACKUP_DIR=/app/data/backups
|
||||
# If a .env file is present, its values will be loaded:
|
||||
env_file:
|
||||
- path: .env
|
||||
required: false
|
||||
volumes:
|
||||
# Writable data directory
|
||||
- ./data:/app/data:rw
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
dash_net:
|
||||
external: true
|
||||
@@ -18,10 +18,7 @@ if (!fs.existsSync(distDir)) {
|
||||
fs.mkdirSync(distDir, { recursive: true });
|
||||
}
|
||||
|
||||
console.log('Packaging application, siblings, and JavaScript dependencies into SEA payload...');
|
||||
|
||||
// Native C++ addon folders that will be loaded from the host filesystem via dlopen
|
||||
const NATIVE_ADDON_PKGS = new Set(['better-sqlite3', 'canvas', 'sharp', '@img']);
|
||||
console.log('Packaging application, siblings, and dependencies into SEA payload...');
|
||||
|
||||
function packDirectory(dir, prefix, result) {
|
||||
if (!fs.existsSync(dir)) return;
|
||||
@@ -30,11 +27,10 @@ function packDirectory(dir, prefix, result) {
|
||||
const full = path.join(dir, entry.name);
|
||||
const rel = path.join(prefix, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
if (entry.name === 'test' || entry.name === 'tests' || entry.name === 'docs' || entry.name === '.github' || entry.name === '.git') continue;
|
||||
if (entry.name === 'test' || entry.name === 'tests' || entry.name === 'docs' || entry.name === '.github' || entry.name === '.git' || entry.name === 'obj.target') continue;
|
||||
packDirectory(full, rel, result);
|
||||
} else if (entry.isFile()) {
|
||||
// Ignore compiled native binary extensions which are linked from the host
|
||||
if (entry.name.endsWith('.node') || entry.name.endsWith('.so') || entry.name.endsWith('.dylib') || entry.name.endsWith('.dll') || entry.name.endsWith('.a')) continue;
|
||||
if (entry.name.endsWith('.a') || entry.name.endsWith('.o') || entry.name.endsWith('.cc') || entry.name.endsWith('.cpp') || entry.name.endsWith('.c') || entry.name.endsWith('.h')) continue;
|
||||
result[rel] = fs.readFileSync(full).toString('base64');
|
||||
}
|
||||
}
|
||||
@@ -67,15 +63,14 @@ if (fs.existsSync(path.join(llmorbiterDir, 'src'))) {
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Pack all non-native node_modules dependencies
|
||||
// 3. Pack all node_modules dependencies
|
||||
function packNodeModules(nmPath) {
|
||||
if (!fs.existsSync(nmPath)) return;
|
||||
for (const name of fs.readdirSync(nmPath)) {
|
||||
if (NATIVE_ADDON_PKGS.has(name) || name.startsWith('.') || name === 'libdashstore' || name === 'libllmorbiter') continue;
|
||||
if (name.startsWith('.') || name === 'libdashstore' || name === 'libllmorbiter') continue;
|
||||
const pkgDir = path.join(nmPath, name);
|
||||
if (name.startsWith('@')) {
|
||||
for (const sub of fs.readdirSync(pkgDir)) {
|
||||
if (NATIVE_ADDON_PKGS.has(sub) || NATIVE_ADDON_PKGS.has(`${name}/${sub}`)) continue;
|
||||
packDirectory(path.join(pkgDir, sub), `node_modules/${name}/${sub}`, payload);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
* SEA Entry point for dashback.
|
||||
* Embedded inside the Node.js single executable binary.
|
||||
*
|
||||
* Unpacks the bundled application, sibling packages, and JavaScript dependencies
|
||||
* to a runtime directory, and links only the native C++ addons from the host.
|
||||
* Unpacks the bundled application, sibling packages, and all dependencies
|
||||
* (including native C++ addons) to a runtime directory.
|
||||
*/
|
||||
const sea = require('node:sea');
|
||||
const fs = require('node:fs');
|
||||
@@ -32,23 +32,6 @@ function getProjectRoot() {
|
||||
fs.writeFileSync(markerFile, '1');
|
||||
}
|
||||
|
||||
// Link host native addons into runtime node_modules
|
||||
const hostNodeModules = path.resolve(process.cwd(), 'node_modules');
|
||||
const runtimeNodeModules = path.join(runtimeDir, 'node_modules');
|
||||
fs.mkdirSync(runtimeNodeModules, { recursive: true });
|
||||
|
||||
const NATIVE_ADDON_DIRS = ['better-sqlite3', 'canvas', 'sharp', '@img'];
|
||||
for (const addon of NATIVE_ADDON_DIRS) {
|
||||
const hostAddon = path.join(hostNodeModules, addon);
|
||||
const targetAddon = path.join(runtimeNodeModules, addon);
|
||||
if (fs.existsSync(hostAddon) && !fs.existsSync(targetAddon)) {
|
||||
try {
|
||||
fs.mkdirSync(path.dirname(targetAddon), { recursive: true });
|
||||
fs.symlinkSync(hostAddon, targetAddon, 'junction');
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
// Link host .env if present so config/env.js can find it
|
||||
const hostEnv = path.resolve(process.cwd(), '.env');
|
||||
const runtimeEnv = path.join(runtimeDir, '.env');
|
||||
|
||||
35
start-docker.sh
Executable file
35
start-docker.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Ensure the writable data directory exists on the host
|
||||
mkdir -p "${SCRIPT_DIR}/data"
|
||||
|
||||
ENV_ARGS=()
|
||||
if [ -f "${SCRIPT_DIR}/.env" ]; then
|
||||
ENV_ARGS+=(--env-file "${SCRIPT_DIR}/.env")
|
||||
fi
|
||||
|
||||
docker run -d \
|
||||
--name dashback \
|
||||
--restart unless-stopped \
|
||||
--read-only \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
--tmpfs /tmp:rw,exec,nosuid,size=512m \
|
||||
--tmpfs /run:rw,noexec,nosuid,size=16m \
|
||||
-p 127.0.0.1:4608:4208 \
|
||||
"${ENV_ARGS[@]}" \
|
||||
--add-host=host.docker.internal:host-gateway \
|
||||
-e HOST=0.0.0.0 \
|
||||
-e PORT=4208 \
|
||||
-e HTTPS_PORT=0 \
|
||||
-e MSSQL_SERVER=host.docker.internal \
|
||||
-e HEALTH_MONITOR_ENABLED=false \
|
||||
-e SQLITE_PATH=/app/data/dash.db \
|
||||
-e STORAGE_DIR=/app/data/storage \
|
||||
-e BACKUP_DIR=/app/data/backups \
|
||||
-v "${SCRIPT_DIR}/dist/dashback:/app/dist/dashback:ro" \
|
||||
-v "${SCRIPT_DIR}/data:/app/data:rw" \
|
||||
dashback:latest
|
||||
|
||||
Reference in New Issue
Block a user