diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 058c91a..6926720 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -49,6 +49,8 @@ jobs: - 'public/**' - '.github/workflows/**' - 'tests/**' + - Dockerfile + - docker-entrypoint.sh docs: - 'docs/**' - '.github/workflows/**' diff --git a/Dockerfile b/Dockerfile index 5851fe2..fde769e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,42 +1,49 @@ -# base node image -FROM node:20-bookworm-slim as base +# +# Net-Doc Docker File +# -# Install openssl for Prisma -RUN apt-get update && apt-get install -y openssl +# Start with the node debian image +FROM node:22-bullseye-slim AS base -# Install all node_modules, including dev dependencies -FROM base as deps +# Install openssl for Prisma and NGINX +RUN apt-get update && apt-get install openssl nginx -y -RUN mkdir /app -WORKDIR /app +# Create a new temp container called `deps` from `base` +# Add the package files and install all the deps. + FROM base AS deps -ADD package.json package-lock.json ./ -RUN npm install --production=false + RUN mkdir /app + WORKDIR /app -# Setup production node_modules -FROM base as production-deps + ADD package.json package-lock.json ./ + RUN npm install --production=false -RUN mkdir /app -WORKDIR /app +# create a new temp container called `production-deps` from `base` +# copy the `deps` node_modules folder over and prune it to production only. + FROM base AS production-deps -COPY --from=deps /app/node_modules /app/node_modules -ADD package.json package-lock.json ./ -RUN npm prune --production + RUN mkdir /app + WORKDIR /app -# Build the app -FROM base as build + COPY --from=deps /app/node_modules /app/node_modules + ADD package.json package-lock.json ./ + RUN npm prune --production -ENV NODE_ENV=production +# create a new temp container called `build` from `base` +# Copy over the full deps and run build. + FROM base AS build -RUN mkdir /app -WORKDIR /app + ENV NODE_ENV=production -COPY --from=deps /app/node_modules /app/node_modules + RUN mkdir /app + WORKDIR /app -ADD . . -RUN npm run build + COPY --from=deps /app/node_modules /app/node_modules -# Finally, build the production image with minimal footprint + ADD . . + RUN npm run build + +# Go back to the `base` image and copy in the production deps and build FROM base ENV NODE_ENV=production @@ -50,4 +57,7 @@ COPY --from=build /app/build/server /app/build/server COPY --from=build /app/build/client /app/build/client ADD . . -CMD ["npm", "run", "docker"] \ No newline at end of file +RUN chmod +x /app/docker-entrypoint.sh + +ENTRYPOINT [ "/app/docker-entrypoint.sh" ] +CMD [] \ No newline at end of file diff --git a/docker-compose.sample.yml b/docker-compose.sample.yml index a22f89c..03b05ff 100644 --- a/docker-compose.sample.yml +++ b/docker-compose.sample.yml @@ -1,23 +1,41 @@ -version: '3.9' -services: - remix: - image: longridgehighschool/net-doc:main - restart: always - ports: - - '3000:3000' - environment: +x-shared: + net-doc-service: &net-doc-service + environment: &net-doc-environment - PASSWORD_KEY=YOUR KEY - PASSWORD_SALT=YOUR SALT - PASSWORD_IV=YOUR IV - DATABASE_URL=file:./data/net-doc.db - volumes: + - REDIS_URL=net-doc-redis:6379 + volumes: &net-doc-volumes - ./db:/app/prisma/data - ./uploads:/app/public/uploads - ./backups:/app/public/backups - redis: + image: longridgehighschool/net-doc:2 + restart: always + depends_on: + - net-doc-redis + +services: + net-doc-remix: + <<: *net-doc-service + command: ['net-doc-remix'] + + net-doc-worker: + <<: *net-doc-service + command: ['net-doc-worker'] + depends_on: + - net-doc-remix + + net-doc-nginx: + <<: *net-doc-service + command: ['net-doc-nginx'] + depends_on: + - net-doc-remix + ports: + - '8080:80' + + net-doc-redis: image: redis:7 restart: always volumes: - ./data/redis:/data - ports: - - 6379:6379 diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100644 index 0000000..b18da7d --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +: "${REMIX_HOST:=net-doc-remix}" +: "${REMIX_PORT:=3000}" + +function prepare_database { + npm uninstall bcrypt + npm install bcrypt + + npx prisma migrate deploy + npx prisma generate --sql +} + +if [ "$1" = 'net-doc-remix' ]; then + prepare_database + + npm run start:remix + +elif [ "$1" = 'net-doc-worker' ]; then + prepare_database + + npm run start:worker +elif [ "$1" = 'net-doc-nginx' ]; then + # configure nginx + sed -e "s#server .*:3000#server ${REMIX_HOST}:${REMIX_PORT}#g" \ + -e 's#/var/log/nginx/net-doc.\(access\|error\).log#/dev/stdout#g' < /app/docker/nginx.conf > /etc/nginx/sites-enabled/default + + echo "starting nginx..." + + exec /usr/sbin/nginx -g 'daemon off;' +fi \ No newline at end of file diff --git a/docker/nginx.conf b/docker/nginx.conf new file mode 100644 index 0000000..e9ef5c4 --- /dev/null +++ b/docker/nginx.conf @@ -0,0 +1,38 @@ +upstream net-doc-remix { + server 127.0.0.1:3000; +} + +server { + listen 80; + listen [::]:80; + + # replace 'localhost' with your fqdn if you want to use zammad from remote + server_name localhost; + + # security - prevent information disclosure about server version + server_tokens off; + + root /app/build/client; + + access_log /var/log/nginx/net-doc.access.log; + error_log /var/log/nginx/net-doc.error.log; + + client_max_body_size 50M; + + location ~ ^/(assets/|robots.txt|humans.txt|favicon.ico|apple-touch-icon.png) { + expires max; + } + + location / { + proxy_set_header Host $http_host; + proxy_set_header CLIENT_IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_read_timeout 300; + proxy_pass http://net-doc-remix; + + gzip on; + gzip_types text/plain text/xml text/css image/svg+xml application/javascript application/x-javascript application/json application/xml; + gzip_proxied any; + } +} \ No newline at end of file diff --git a/docs/docs/getting-started/install.md b/docs/docs/getting-started/install.md index 234cc6e..ee67bc0 100644 --- a/docs/docs/getting-started/install.md +++ b/docs/docs/getting-started/install.md @@ -13,32 +13,52 @@ Net-Doc is distributed as a docker container. > The tag `latest` will always pull the latest > [release](https://github.com/Longridge-High-School/net-doc/releases), `main` -> will pull the latest commit to the main branch. +> will pull the latest commit to the main branch. Ideally you should use the +> major version tag e.g. `2` to avoid automatically installing any breaking +> changes. `2` would include any `2.x.y` release. ```yml -version: '3.9' -services: - remix: - image: longridgehighschool/net-doc:latest - restart: always - ports: - - '3000:3000' - environment: +x-shared: + net-doc-service: &net-doc-service + environment: &net-doc-environment - PASSWORD_KEY=YOUR KEY - PASSWORD_SALT=YOUR SALT - PASSWORD_IV=YOUR IV - DATABASE_URL=file:./data/net-doc.db - volumes: + - REDIS_URL=net-doc-redis:6379 + volumes: &net-doc-volumes - ./db:/app/prisma/data - ./uploads:/app/public/uploads - ./backups:/app/public/backups - redis: + image: longridgehighschool/net-doc:2 + restart: always + depends_on: + - net-doc-redis + +services: + net-doc-remix: + <<: *net-doc-service + command: ['net-doc-remix'] + + net-doc-worker: + <<: *net-doc-service + command: ['net-doc-worker'] + depends_on: + - net-doc-remix + + net-doc-nginx: + <<: *net-doc-service + command: ['net-doc-nginx'] + depends_on: + - net-doc-remix + ports: + - '8080:80' + + net-doc-redis: image: redis:7 restart: always volumes: - ./data/redis:/data - ports: - - 6379:6379 ``` ### Environment Variables