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,20 +16,16 @@ 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+ RUN apt-get update && apt-get install -y git python3 make g++ && rm -rf /var/lib/apt/lists/*
2121
2222# Copy package files first for better layer caching
2323COPY package.json bun.lock bunfig.toml ./
2424
2525# Copy postinstall script (needed by bun install)
2626COPY scripts/postinstall.sh scripts/
2727
28- # Install build tools needed for native modules
29- RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/*
30-
31- # Install dependencies (postinstall detects server mode and skips Electron rebuild)
32- # Note: node-pty is in optionalDependencies and will be built for Node.js
28+ # Install dependencies
3329RUN bun install --frozen-lockfile
3430
3531# Copy source files needed for build
@@ -60,6 +56,21 @@ RUN NODE_ENV=production bun x tsc -p tsconfig.main.json && \
6056# Build renderer (frontend)
6157RUN bun x vite build
6258
59+ # Bundle server with esbuild (reduces ~2GB node_modules to ~10MB bundle)
60+ # External: native modules that can't be bundled
61+ # Alias: use ESM version of jsonc-parser to avoid UMD bundling issues
62+ RUN bun x esbuild dist/cli/server.js \
63+ --bundle \
64+ --platform=node \
65+ --target=node22 \
66+ --format=cjs \
67+ --outfile=dist/server-bundle.js \
68+ --external:@lydell/node-pty \
69+ --external:node-pty \
70+ --external:electron \
71+ --alias:jsonc-parser=jsonc-parser/lib/esm/main.js \
72+ --minify
73+
6374# Copy static assets
6475RUN mkdir -p dist/static && cp -r static/* dist/static/ 2>/dev/null || true
6576
@@ -77,10 +88,16 @@ RUN apt-get update && \
7788 apt-get install -y git openssh-client && \
7889 rm -rf /var/lib/apt/lists/*
7990
80- # Copy built artifacts from builder
81- COPY --from=builder /app/dist ./dist
82- COPY --from=builder /app/node_modules ./node_modules
83- COPY --from=builder /app/package.json ./
91+ # Copy bundled server and frontend assets
92+ # Vite outputs JS/CSS/HTML directly to dist/ (assetsDir: ".")
93+ COPY --from=builder /app/dist/server-bundle.js ./dist/
94+ COPY --from=builder /app/dist/*.html ./dist/
95+ COPY --from=builder /app/dist/*.js ./dist/
96+ COPY --from=builder /app/dist/*.css ./dist/
97+ COPY --from=builder /app/dist/static ./dist/static
98+
99+ # Copy only native modules needed at runtime (node-pty for terminal support)
100+ COPY --from=builder /app/node_modules/@lydell ./node_modules/@lydell
84101
85102# Create mux data directory
86103RUN mkdir -p /root/.mux
@@ -96,8 +113,8 @@ EXPOSE 3000
96113HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
97114 CMD node -e "fetch('http://localhost:3000/health').then(r => r.ok ? process.exit(0) : process.exit(1)).catch(() => process.exit(1))"
98115
99- # Run mux server
116+ # Run bundled mux server
100117# --host 0.0.0.0: bind to all interfaces (required for Docker networking)
101118# --port 3000: default port (can be remapped via docker run -p)
102- ENTRYPOINT ["node" , "dist/cli/index .js" , "server " ]
119+ ENTRYPOINT ["node" , "dist/server-bundle .js" ]
103120CMD ["--host" , "0.0.0.0" , "--port" , "3000" ]
0 commit comments