From 299ceee3a14d29747e400c55a5d1744ff01259fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20Jedlicska?= Date: Tue, 19 Jan 2021 21:54:15 +0100 Subject: [PATCH] feat(dockerfile docker-compose app.js): production environment compatible build Add consistent and optimized dockerfile with docs. Move http-proxy require to only in dev environment. Removes mounting of server source code in the container. Restrict debug loggin only for `speckle:*` logger. --- .dockerignore | 14 ++++++++--- Dockerfile | 53 ++++++++++++++++++++++++++---------------- docker-compose.yaml | 8 +++---- packages/server/app.js | 5 ++-- 4 files changed, 50 insertions(+), 30 deletions(-) diff --git a/.dockerignore b/.dockerignore index 048660091..8b1bb4af5 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,8 +4,6 @@ coverage **/node_modules - - npm-debug.log Dockerfile* docker-compose* @@ -13,4 +11,14 @@ docker-compose* .git .gitignore README.md -LICENSE \ No newline at end of file +LICENSE + +test-queries +.editorconfig +Contributing.md +ISSUE_TEMPLATE.md +lerna.json +.env.example +.eslintrc.json +.mocharc.js +readme.md \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 94549fcb4..0b84a5307 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,32 +1,45 @@ -# FROM node:14-alpine AS node -FROM node:14 AS node +FROM node:14.15.4-alpine3.10@sha256:fe215d05cdde4b7f2a0f546c88a8ddc4f5fa280a204acdfc2383afe901fd6d84 as build -# -e "NODE_ENV=production" +WORKDIR /home/node -FROM node as builder +# Having multiple steps in builder doesn't increase the final image size +# So having verbose steps for readability and caching should be the target -WORKDIR /frontend +# 1. Copy package defs first they are the least likely to change +# Keeping this order will least likely trigger full rebuild +COPY packages/frontend/package*.json frontend/ +COPY packages/server/package*.json server/ -COPY ./packages/frontend/package*.json ./ -RUN npm ci +# 2. Install packages +# Use dev environment to install dev packages for frontend build +ENV NODE_ENV development +RUN npm --prefix frontend ci frontend -COPY ./packages/frontend ./ +# Switch to production env for server install +ENV NODE_ENV production +RUN npm --prefix server ci server -RUN npm run build +# 3. build frontend to static files +# when testing container build, most propably not the frontend files are the ones +# that are changing. So having a separate copy and build step speeds up the container +# build. +COPY packages/frontend frontend +RUN npm --prefix frontend run build -WORKDIR /app -COPY ./packages/server/package*.json ./ +COPY packages/server server +FROM node:14.15.4-alpine3.10@sha256:fe215d05cdde4b7f2a0f546c88a8ddc4f5fa280a204acdfc2383afe901fd6d84 -RUN npm ci +ENV NODE_ENV production -COPY ./packages/server ./ +RUN mkdir -p frontend/dist server -# FROM node:14-alpine as final -EXPOSE 3000 +# only copy in the build artifacts for the frontend +COPY --from=build --chown=node /home/node/frontend/dist frontend/dist +# copy the server with installed modules +COPY --from=build --chown=node /home/node/server server -# COPY --from=builder /app /app -# COPY --from=builder /frontend /frontend +# change to no root user, node +USER node -# WORKDIR /app - -CMD node ./bin/www \ No newline at end of file +WORKDIR /server +CMD ["node", "bin/www"] diff --git a/docker-compose.yaml b/docker-compose.yaml index 737242ff1..dd2b86e0e 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -11,10 +11,10 @@ services: ports: - "3000:3000" environment: - DEBUG: "*" - volumes: - - ./packages/server:/app - + DEBUG: "speckle:*" + env_file: + - .env + database: image: "postgres" # use latest official postgres version env_file: diff --git a/packages/server/app.js b/packages/server/app.js index 50e288320..9f97bd2c2 100644 --- a/packages/server/app.js +++ b/packages/server/app.js @@ -3,7 +3,6 @@ const http = require( 'http' ) const url = require( 'url' ) -const WebSocket = require( 'ws' ) const express = require( 'express' ) const compression = require( 'compression' ) const appRoot = require( 'app-root-path' ) @@ -87,7 +86,6 @@ exports.init = async ( ) => { return { app, graphqlServer } } -const { createProxyMiddleware } = require( 'http-proxy-middleware' ) /** * Starts a http server, hoisting the express app to it. @@ -103,6 +101,7 @@ exports.startHttp = async ( app ) => { // Handles frontend proxying: // Dev mode -> proxy form the local webpack server if ( process.env.NODE_ENV === 'development' ) { + const { createProxyMiddleware } = require( 'http-proxy-middleware' ) const frontendProxy = createProxyMiddleware( { target: `http://localhost:${frontendPort}`, changeOrigin: true, ws: false, logLevel: 'silent' } ) app.use( '/', frontendProxy ) @@ -129,7 +128,7 @@ exports.startHttp = async ( app ) => { app.use( Sentry.Handlers.errorHandler( ) ) server.on( 'listening', ( ) => { - debug( `speckle:startup` )( `🚀 My name is Speckle Server, and I'm running at ${server.address().port}` ) + debug( 'speckle:startup' )( `🚀 My name is Speckle Server, and I'm running at ${server.address().port}` ) } ) server.listen( port )