11# mux server Docker image
2- # Multi-stage build for minimal runtime image size
2+ # Multi-stage build with esbuild bundling for minimal runtime image
33#
44# Build: docker build -t mux-server .
55# Run: docker run -p 3000:3000 -v ~/.mux:/root/.mux mux-server
@@ -16,21 +16,17 @@ WORKDIR /app
1616# Install bun (used for package management and build tooling)
1717RUN npm install -g bun@1.2
1818
19- # Install git (needed for version generation)
20- RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
19+ # Install git (needed for version generation) and build tools for native modules
20+ # bzip2 is required for lzma-native to extract its bundled xz source tarball
21+ RUN apt-get update && apt-get install -y git python3 make g++ bzip2 && rm -rf /var/lib/apt/lists/*
2122
2223# Copy package files first for better layer caching
2324COPY package.json bun.lock bunfig.toml ./
2425
2526# Copy postinstall script (needed by bun install)
2627COPY scripts/postinstall.sh scripts/
2728
28- # Install build tools needed for native modules
29- # bzip2 is required for lzma-native to extract its bundled xz source tarball
30- RUN apt-get update && apt-get install -y python3 make g++ bzip2 && rm -rf /var/lib/apt/lists/*
31-
32- # Install dependencies (postinstall detects server mode and skips Electron rebuild)
33- # Note: node-pty is in optionalDependencies and will be built for Node.js
29+ # Install dependencies
3430RUN bun install --frozen-lockfile
3531
3632# Copy source files needed for build
@@ -62,6 +58,21 @@ RUN NODE_ENV=production bun run node_modules/@typescript/native-preview/bin/tsgo
6258# Build renderer (frontend)
6359RUN bun x vite build
6460
61+ # Bundle server with esbuild (reduces ~2GB node_modules to ~10MB bundle)
62+ # External: native modules that can't be bundled
63+ # Alias: use ESM version of jsonc-parser to avoid UMD bundling issues
64+ RUN bun x esbuild dist/cli/server.js \
65+ --bundle \
66+ --platform=node \
67+ --target=node22 \
68+ --format=cjs \
69+ --outfile=dist/server-bundle.js \
70+ --external:@lydell/node-pty \
71+ --external:node-pty \
72+ --external:electron \
73+ --alias:jsonc-parser=jsonc-parser/lib/esm/main.js \
74+ --minify
75+
6576# Copy static assets
6677RUN mkdir -p dist/static && cp -r static/* dist/static/ 2>/dev/null || true
6778
@@ -79,10 +90,16 @@ RUN apt-get update && \
7990 apt-get install -y git openssh-client && \
8091 rm -rf /var/lib/apt/lists/*
8192
82- # Copy built artifacts from builder
83- COPY --from=builder /app/dist ./dist
84- COPY --from=builder /app/node_modules ./node_modules
85- COPY --from=builder /app/package.json ./
93+ # Copy bundled server and frontend assets
94+ # Vite outputs JS/CSS/HTML directly to dist/ (assetsDir: ".")
95+ COPY --from=builder /app/dist/server-bundle.js ./dist/
96+ COPY --from=builder /app/dist/*.html ./dist/
97+ COPY --from=builder /app/dist/*.js ./dist/
98+ COPY --from=builder /app/dist/*.css ./dist/
99+ COPY --from=builder /app/dist/static ./dist/static
100+
101+ # Copy only native modules needed at runtime (node-pty for terminal support)
102+ COPY --from=builder /app/node_modules/@lydell ./node_modules/@lydell
86103
87104# Create mux data directory
88105RUN mkdir -p /root/.mux
@@ -98,8 +115,8 @@ EXPOSE 3000
98115HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
99116 CMD node -e "fetch('http://localhost:3000/health').then(r => r.ok ? process.exit(0) : process.exit(1)).catch(() => process.exit(1))"
100117
101- # Run mux server
118+ # Run bundled mux server
102119# --host 0.0.0.0: bind to all interfaces (required for Docker networking)
103120# --port 3000: default port (can be remapped via docker run -p)
104- ENTRYPOINT ["node" , "dist/cli/index .js" , "server " ]
121+ ENTRYPOINT ["node" , "dist/server-bundle .js" ]
105122CMD ["--host" , "0.0.0.0" , "--port" , "3000" ]
0 commit comments