Skip to content

Commit c27867b

Browse files
committed
chore(dashboard): add dockerfile for separate deployment
Signed-off-by: Toma Puljak <[email protected]>
1 parent c7a45a8 commit c27867b

File tree

8 files changed

+76
-9
lines changed

8 files changed

+76
-9
lines changed

apps/api/.env

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,5 @@ ADMIN_SNAPSHOT_QUOTA=100
108108
ADMIN_MAX_SNAPSHOT_SIZE=100
109109
ADMIN_VOLUME_QUOTA=0
110110

111-
SKIP_USER_EMAIL_VERIFICATION=true
111+
SKIP_USER_EMAIL_VERIFICATION=true
112+
DONT_SERVE_DASHBOARD=true

apps/api/Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ ENV SKIP_USER_EMAIL_VERIFICATION=true
120120

121121
ENV RUN_MIGRATIONS=true
122122

123+
ENV DONT_SERVE_DASHBOARD=false
124+
123125
HEALTHCHECK CMD [ "curl", "-f", "http://localhost:3000/api/config" ]
124126

125127
ENTRYPOINT ["sh", "-c", "dockerd-entrypoint.sh & node dist/apps/api/main.js"]

apps/api/src/app.module.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,22 @@ import { getPinoTransport, swapMessageAndObject } from './common/utils/pino.util
9090
cacheControl: false,
9191
},
9292
}),
93-
ServeStaticModule.forRoot({
94-
rootPath: join(__dirname, '..', 'dashboard'),
95-
exclude: ['/api/*'],
96-
renderPath: '/',
97-
serveStaticOptions: {
98-
cacheControl: false,
93+
ServeStaticModule.forRootAsync({
94+
inject: [TypedConfigService],
95+
useFactory: (configService: TypedConfigService) => {
96+
if (configService.get('dontServeDashboard')) {
97+
return []
98+
}
99+
return [
100+
{
101+
rootPath: join(__dirname, '..', 'dashboard'),
102+
exclude: ['/api/*'],
103+
renderPath: '/',
104+
serveStaticOptions: {
105+
cacheControl: false,
106+
},
107+
},
108+
]
99109
},
100110
}),
101111
ThrottlerModule.forRoot([

apps/api/src/config/configuration.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ const configuration = {
216216
volumeQuota: parseInt(process.env.ADMIN_VOLUME_QUOTA || '0', 10),
217217
},
218218
skipUserEmailVerification: process.env.SKIP_USER_EMAIL_VERIFICATION === 'true',
219+
dontServeDashboard: process.env.DONT_SERVE_DASHBOARD === 'true',
219220
}
220221

221222
export { configuration }

apps/api/src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const httpsOptions: HttpsOptions = {
3838

3939
async function bootstrap() {
4040
if (process.env.OTEL_ENABLED === 'true') {
41-
await otelSdk.start()
41+
otelSdk.start()
4242
}
4343
const app = await NestFactory.create<NestExpressApplication>(AppModule, {
4444
bufferLogs: true,

apps/dashboard/Dockerfile

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Stage 1: Build the Vite app
2+
FROM node:20-alpine AS builder
3+
4+
RUN npm install -g corepack && corepack enable
5+
6+
WORKDIR /daytona
7+
8+
COPY . .
9+
10+
RUN yarn
11+
12+
RUN VITE_BASE_API_URL=%DAYTONA_BASE_API_URL% yarn nx build dashboard --configuration=production --nxBail=true
13+
14+
FROM nginx:alpine as dashboard
15+
16+
COPY --from=builder /daytona/dist/apps/dashboard /usr/share/nginx/html
17+
18+
RUN echo 'server { \
19+
listen 80; \
20+
server_name localhost; \
21+
root /usr/share/nginx/html; \
22+
index index.html; \
23+
location / { \
24+
try_files $uri $uri/ /index.html; \
25+
} \
26+
}' > /etc/nginx/conf.d/default.conf
27+
28+
ENV DAYTONA_BASE_API_URL="http://api:3000"
29+
30+
# Create startup script for runtime environment variable substitution
31+
RUN echo '#!/bin/sh' > /docker-entrypoint.sh && \
32+
echo 'set -e' >> /docker-entrypoint.sh && \
33+
echo '' >> /docker-entrypoint.sh && \
34+
echo '# Replace %DAYTONA_BASE_API_URL% with actual environment variable value' >> /docker-entrypoint.sh && \
35+
echo 'find /usr/share/nginx/html -type f \( -name "*.js" -o -name "*.html" \) -exec sed -i "s|%DAYTONA_BASE_API_URL%|${DAYTONA_BASE_API_URL}|g" {} +' >> /docker-entrypoint.sh && \
36+
echo '' >> /docker-entrypoint.sh && \
37+
echo '# Start nginx' >> /docker-entrypoint.sh && \
38+
echo 'exec nginx -g "daemon off;"' >> /docker-entrypoint.sh && \
39+
chmod +x /docker-entrypoint.sh
40+
41+
EXPOSE 80
42+
43+
HEALTHCHECK CMD [ "curl", "-f", "http://localhost/" ]
44+
45+
CMD ["/docker-entrypoint.sh"]

apps/dashboard/project.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
"options": {
1818
"command": "cd {projectRoot} && prettier --write \"**/*.{ts,tsx,js,jsx,json,css,mjs,html}\" --config ../../.prettierrc"
1919
}
20-
}
20+
},
21+
"check-version-env": {},
22+
"docker": {
23+
"options": {
24+
"target": "dashboard"
25+
}
26+
},
27+
"push-manifest": {}
2128
}
2229
}

apps/docs/src/content/docs/en/oss-deployment.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ Below is a full list of environment variables with their default values:
198198
| `ADMIN_MAX_SNAPSHOT_SIZE` | number | `100` | Admin max snapshot size, used only upon initial setup |
199199
| `ADMIN_VOLUME_QUOTA` | number | `0` | Admin volume quota, used only upon initial setup |
200200
| `SKIP_USER_EMAIL_VERIFICATION` | boolean | `true` | Skip user email verification process |
201+
| `DONT_SERVE_DASHBOARD` | boolean | `false` | Disable serving dashboard static files from API service |
201202

202203
### Runner
203204

0 commit comments

Comments
 (0)