refactor: slim down the backend containers (#4233)

* refactor: slim down the backend containers

* refactor: make containers run as non-root user in container

* chore: correct casing for the build stage definitions

* chore: remove docker compose version field as its obsolete

* chore: optimise chown and chmod into the COPY command itself

* chore: add package overrides for packages with reported vulns

* chore: add pnpm to containers + set workdir dir to the backend project

* fix: permission issues with the fe containers

* chore: define env variables on AIO
This commit is contained in:
Andrew Bastin
2024-08-08 11:31:13 +05:30
committed by GitHub
parent bbda18c728
commit afea75694f
12 changed files with 1256 additions and 442 deletions

View File

@@ -51,7 +51,7 @@ fs.rmSync("build.env")
const caddyFileName = process.env.ENABLE_SUBPATH_BASED_ACCESS === 'true' ? 'aio-subpath-access.Caddyfile' : 'aio-multiport-setup.Caddyfile' const caddyFileName = process.env.ENABLE_SUBPATH_BASED_ACCESS === 'true' ? 'aio-subpath-access.Caddyfile' : 'aio-multiport-setup.Caddyfile'
const caddyProcess = runChildProcessWithPrefix("caddy", ["run", "--config", `/etc/caddy/${caddyFileName}`, "--adapter", "caddyfile"], "App/Admin Dashboard Caddy") const caddyProcess = runChildProcessWithPrefix("caddy", ["run", "--config", `/etc/caddy/${caddyFileName}`, "--adapter", "caddyfile"], "App/Admin Dashboard Caddy")
const backendProcess = runChildProcessWithPrefix("pnpm", ["run", "start:prod"], "Backend Server") const backendProcess = runChildProcessWithPrefix("node", ["/dist/backend/dist/main.js"], "Backend Server")
caddyProcess.on("exit", (code) => { caddyProcess.on("exit", (code) => {
console.log(`Exiting process because Caddy Server exited with code ${code}`) console.log(`Exiting process because Caddy Server exited with code ${code}`)

View File

@@ -1,8 +1,6 @@
# THIS IS NOT TO BE USED FOR PERSONAL DEPLOYMENTS! # THIS IS NOT TO BE USED FOR PERSONAL DEPLOYMENTS!
# Internal Docker Compose Image used for internal testing deployments # Internal Docker Compose Image used for internal testing deployments
version: "3.7"
services: services:
hoppscotch-db: hoppscotch-db:
image: postgres:15 image: postgres:15

View File

@@ -1,7 +1,6 @@
# To make it easier to self-host, we have a preset docker compose config that also # To make it easier to self-host, we have a preset docker compose config that also
# has a container with a Postgres instance running. # has a container with a Postgres instance running.
# You can tweak around this file to match your instances # You can tweak around this file to match your instances
version: "3.7"
services: services:
# This service runs the backend app in the port 3170 # This service runs the backend app in the port 3170

View File

@@ -34,7 +34,13 @@
}, },
"pnpm": { "pnpm": {
"overrides": { "overrides": {
"vue": "3.3.9" "vue": "3.3.9",
"@nestjs-modules/mailer>mjml": "5.0.0-alpha.4",
"subscriptions-transport-ws>ws": "7.5.10",
"@nestjs/graphql>ws": "8.17.1",
"braces": "3.0.3",
"express": "4.19.2",
"pug": "3.0.3"
}, },
"packageExtensions": { "packageExtensions": {
"@hoppscotch/httpsnippet": { "@hoppscotch/httpsnippet": {

View File

@@ -5,6 +5,10 @@
"author": "", "author": "",
"private": true, "private": true,
"license": "UNLICENSED", "license": "UNLICENSED",
"files": [
"prisma",
"dist"
],
"scripts": { "scripts": {
"prebuild": "rimraf dist", "prebuild": "rimraf dist",
"build": "nest build", "build": "nest build",
@@ -56,7 +60,7 @@
"handlebars": "4.7.7", "handlebars": "4.7.7",
"io-ts": "2.2.16", "io-ts": "2.2.16",
"luxon": "3.2.1", "luxon": "3.2.1",
"nodemailer": "6.9.1", "nodemailer": "6.9.14",
"passport": "0.6.0", "passport": "0.6.0",
"passport-github2": "0.1.12", "passport-github2": "0.1.12",
"passport-google-oauth20": "2.0.0", "passport-google-oauth20": "2.0.0",

View File

@@ -39,8 +39,8 @@ const caddyProcess = runChildProcessWithPrefix(
'App/Admin Dashboard Caddy', 'App/Admin Dashboard Caddy',
); );
const backendProcess = runChildProcessWithPrefix( const backendProcess = runChildProcessWithPrefix(
'pnpm', 'node',
['run', 'start:prod'], ['/dist/backend/dist/main.js'],
'Backend Server', 'Backend Server',
); );

View File

@@ -1,4 +1,8 @@
{ {
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"] "exclude": ["node_modules", "test", "dist", "**/*spec.ts"],
"compilerOptions": {
"declaration": false,
"sourceMap": false
}
} }

View File

@@ -1,5 +1,5 @@
:80 :3000 { :80 :3000 {
try_files {path} / try_files {path} /
root * /site root * /site/selfhost-web
file_server file_server
} }

1544
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
FROM node:20-alpine3.19 as base_builder FROM node:20-alpine3.19 AS base_builder
WORKDIR /usr/src/app WORKDIR /usr/src/app
@@ -15,73 +15,132 @@ COPY . .
RUN pnpm install -f --offline RUN pnpm install -f --offline
FROM base_builder as backend FROM base_builder AS backend_builder
RUN apk add caddy
WORKDIR /usr/src/app/packages/hoppscotch-backend WORKDIR /usr/src/app/packages/hoppscotch-backend
RUN pnpm exec prisma generate RUN pnpm exec prisma generate
RUN pnpm run build RUN pnpm run build
COPY --from=base_builder /usr/src/app/packages/hoppscotch-backend/backend.Caddyfile /etc/caddy/backend.Caddyfile RUN pnpm --filter=hoppscotch-backend deploy /dist/backend --prod
WORKDIR /dist/backend
RUN pnpm exec prisma generate
FROM node:20-alpine3.19 AS backend
RUN apk add caddy
RUN npm install -g pnpm
RUN addgroup -S hoppgroup && adduser -S hoppuser -G hoppgroup
COPY --from=base_builder /usr/src/app/packages/hoppscotch-backend/backend.Caddyfile /etc/caddy/backend.Caddyfile
COPY --from=backend_builder --chown=hoppuser:hoppgroup --chmod=755 /dist/backend /dist/backend
COPY --from=base_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-backend/prod_run.mjs /dist/backend
# Remove the env file to avoid backend copying it in and using it # Remove the env file to avoid backend copying it in and using it
RUN rm "../../.env"
ENV PRODUCTION="true" ENV PRODUCTION="true"
ENV PORT=8080 ENV PORT=8080
ENV APP_PORT=${PORT} ENV APP_PORT=${PORT}
ENV DB_URL=${DATABASE_URL} ENV DB_URL=${DATABASE_URL}
CMD ["node", "/usr/src/app/packages/hoppscotch-backend/prod_run.mjs"]
USER hoppuser
WORKDIR /dist/backend
CMD ["node", "prod_run.mjs"]
EXPOSE 80 EXPOSE 80
EXPOSE 3170 EXPOSE 3170
FROM base_builder as fe_builder FROM base_builder AS fe_builder
WORKDIR /usr/src/app/packages/hoppscotch-selfhost-web WORKDIR /usr/src/app/packages/hoppscotch-selfhost-web
RUN pnpm run generate RUN pnpm run generate
FROM caddy:2-alpine as app FROM caddy:2-alpine AS app
WORKDIR /site RUN addgroup -S hoppgroup && adduser -S hoppuser -G hoppgroup
COPY --from=fe_builder /usr/src/app/packages/hoppscotch-selfhost-web/prod_run.mjs /usr
COPY --from=fe_builder /usr/src/app/packages/hoppscotch-selfhost-web/selfhost-web.Caddyfile /etc/caddy/selfhost-web.Caddyfile COPY --from=fe_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-selfhost-web/prod_run.mjs /site/prod_run.mjs
COPY --from=fe_builder /usr/src/app/packages/hoppscotch-selfhost-web/dist/ . COPY --from=fe_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-selfhost-web/selfhost-web.Caddyfile /etc/caddy/selfhost-web.Caddyfile
COPY --from=fe_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-selfhost-web/dist/ /site/selfhost-web
RUN apk add nodejs npm RUN apk add nodejs npm
RUN npm install -g @import-meta-env/cli RUN npm install -g @import-meta-env/cli
USER hoppuser
EXPOSE 80 EXPOSE 80
EXPOSE 3000 EXPOSE 3000
CMD ["/bin/sh", "-c", "node /usr/prod_run.mjs && caddy run --config /etc/caddy/selfhost-web.Caddyfile --adapter caddyfile"]
FROM base_builder as sh_admin_builder WORKDIR /site
CMD ["/bin/sh", "-c", "node /site/prod_run.mjs && caddy run --config /etc/caddy/selfhost-web.Caddyfile --adapter caddyfile"]
FROM base_builder AS sh_admin_builder
WORKDIR /usr/src/app/packages/hoppscotch-sh-admin WORKDIR /usr/src/app/packages/hoppscotch-sh-admin
# Generate two builds for `sh-admin`, one based on subpath-access and the regular build # Generate two builds for `sh-admin`, one based on subpath-access and the regular build
RUN pnpm run build --outDir dist-multiport-setup RUN pnpm run build --outDir dist-multiport-setup
RUN pnpm run build --outDir dist-subpath-access --base /admin/ RUN pnpm run build --outDir dist-subpath-access --base /admin/
FROM caddy:2-alpine as sh_admin FROM caddy:2-alpine AS sh_admin
WORKDIR /site RUN addgroup -S hoppgroup && adduser -S hoppuser -G hoppgroup
COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/prod_run.mjs /usr
COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/sh-admin-multiport-setup.Caddyfile /etc/caddy/sh-admin-multiport-setup.Caddyfile COPY --from=sh_admin_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-sh-admin/prod_run.mjs /site/prod_run.mjs
COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/sh-admin-subpath-access.Caddyfile /etc/caddy/sh-admin-subpath-access.Caddyfile COPY --from=sh_admin_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-sh-admin/sh-admin-multiport-setup.Caddyfile /etc/caddy/sh-admin-multiport-setup.Caddyfile
COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/dist-multiport-setup /site/sh-admin-multiport-setup COPY --from=sh_admin_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-sh-admin/sh-admin-subpath-access.Caddyfile /etc/caddy/sh-admin-subpath-access.Caddyfile
COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/dist-subpath-access /site/sh-admin-subpath-access COPY --from=sh_admin_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-sh-admin/dist-multiport-setup /site/sh-admin-multiport-setup
COPY --from=sh_admin_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-sh-admin/dist-subpath-access /site/sh-admin-subpath-access
RUN apk add nodejs npm RUN apk add nodejs npm
RUN npm install -g @import-meta-env/cli RUN npm install -g @import-meta-env/cli
USER hoppuser
EXPOSE 80 EXPOSE 80
EXPOSE 3100 EXPOSE 3100
CMD ["node","/usr/prod_run.mjs"]
FROM backend as aio WORKDIR /site
RUN apk add caddy tini
RUN npm install -g @import-meta-env/cli CMD ["node","/site/prod_run.mjs"]
COPY --from=fe_builder /usr/src/app/packages/hoppscotch-selfhost-web/dist /site/selfhost-web
COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/dist-multiport-setup /site/sh-admin-multiport-setup FROM node:20-alpine3.19 AS aio
COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/dist-subpath-access /site/sh-admin-subpath-access
ENV PRODUCTION="true"
ENV PORT=8080
ENV APP_PORT=${PORT}
ENV DB_URL=${DATABASE_URL}
# Run this separately to use the cache from backend
RUN apk add caddy
RUN apk add tini curl
RUN npm install -g pnpm
RUN addgroup -S hoppgroup && adduser -S hoppuser -G hoppgroup
# Copy necessary files
# Backend files
COPY --from=base_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-backend/backend.Caddyfile /etc/caddy/backend.Caddyfile
COPY --from=backend_builder --chown=hoppuser:hoppgroup --chmod=755 /dist/backend /dist/backend
COPY --from=base_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-backend/prod_run.mjs /dist/backend
# FE Files
COPY --from=base_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/aio_run.mjs /usr/src/app/aio_run.mjs
COPY --from=fe_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-selfhost-web/dist /site/selfhost-web
COPY --from=sh_admin_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-sh-admin/dist-multiport-setup /site/sh-admin-multiport-setup
COPY --from=sh_admin_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-sh-admin/dist-subpath-access /site/sh-admin-subpath-access
COPY aio-multiport-setup.Caddyfile /etc/caddy/aio-multiport-setup.Caddyfile COPY aio-multiport-setup.Caddyfile /etc/caddy/aio-multiport-setup.Caddyfile
COPY aio-subpath-access.Caddyfile /etc/caddy/aio-subpath-access.Caddyfile COPY aio-subpath-access.Caddyfile /etc/caddy/aio-subpath-access.Caddyfile
RUN npm install -g @import-meta-env/cli
USER hoppuser
ENTRYPOINT [ "tini", "--" ] ENTRYPOINT [ "tini", "--" ]
RUN apk --no-cache add curl
COPY --chmod=755 healthcheck.sh . COPY --chmod=755 healthcheck.sh .
HEALTHCHECK --interval=2s CMD /bin/sh ./healthcheck.sh HEALTHCHECK --interval=2s CMD /bin/sh ./healthcheck.sh
WORKDIR /dist/backend
CMD ["node", "/usr/src/app/aio_run.mjs"] CMD ["node", "/usr/src/app/aio_run.mjs"]
EXPOSE 3170 EXPOSE 3170
EXPOSE 3000 EXPOSE 3000
EXPOSE 3100 EXPOSE 3100
EXPOSE 80 EXPOSE 80