diff --git a/packages/nocodb/Dockerfile.local b/packages/nocodb/Dockerfile.local new file mode 100644 index 0000000000..bb3e9a5fcd --- /dev/null +++ b/packages/nocodb/Dockerfile.local @@ -0,0 +1,55 @@ +########### +# Builder +########### +FROM node:16.17.0-alpine3.15 as builder +WORKDIR /usr/src/app + +# install node-gyp dependencies +RUN apk add --no-cache python3 make g++ + +# Copy application dependency manifests to the container image. +# A wildcard is used to ensure both package.json AND package-lock.json are copied. +# Copying this separately prevents re-running npm ci on every code change. +COPY ./package*.json ./ +COPY ./docker/nc-gui/ ./docker/nc-gui/ +COPY ./docker/main.js ./docker/index.js +COPY ./docker/start-local.sh /usr/src/appEntry/start.sh +COPY ./src/lib/public/css/*.css ./docker/public/css/ +COPY ./src/lib/public/js/*.js ./docker/public/js/ +COPY ./src/lib/public/favicon.ico ./docker/public/ + +# install production dependencies, +# reduce node_module size with modclean & removing sqlite deps, +# package built code into app.tar.gz & add execute permission to start.sh +RUN npm ci --omit=dev --quiet \ + && npx modclean --patterns="default:*" --ignore="nc-lib-gui/**,dayjs/**,express-status-monitor/**,@azure/msal-node/dist/**" --run \ + && rm -rf ./node_modules/sqlite3/deps \ + && tar -czf ../appEntry/app.tar.gz ./* \ + && chmod +x /usr/src/appEntry/start.sh + +########## +# Runner +########## +FROM alpine:3.15 +WORKDIR /usr/src/app + +ENV NC_DOCKER 0.6 +ENV NODE_ENV production +ENV PORT 8080 +ENV NC_TOOL_DIR=/usr/app/data/ + +RUN apk --update --no-cache add \ + nodejs \ + tar \ + dumb-init \ + curl \ + jq + +# Copy packaged production code & main entry file +COPY --from=builder /usr/src/appEntry/ /usr/src/appEntry/ + +EXPOSE 8080 +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + +# Start Nocodb +CMD ["/usr/src/appEntry/start.sh"] diff --git a/packages/nocodb/docker/start-local.sh b/packages/nocodb/docker/start-local.sh new file mode 100644 index 0000000000..619e2f58fd --- /dev/null +++ b/packages/nocodb/docker/start-local.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +FILE="/usr/src/app/package.json" + +if [ ! -z "${NC_TOOL_DIR}" ]; then + mkdir -p $NC_TOOL_DIR +fi + +if [ ! -f "$FILE" ] +then + tar -xzf /usr/src/appEntry/app.tar.gz -C /usr/src/app/ +fi + +node docker/index.js diff --git a/packages/nocodb/src/run/local.ts b/packages/nocodb/src/run/local.ts new file mode 100644 index 0000000000..f06c6845b8 --- /dev/null +++ b/packages/nocodb/src/run/local.ts @@ -0,0 +1,18 @@ +import path from 'path'; +import cors from 'cors'; +import express from 'express'; + +import Noco from '../lib/Noco'; + +const server = express(); +server.enable('trust proxy'); +server.use(cors()); +server.use('/dashboard', express.static(path.join(__dirname, 'nc-gui'))); +server.set('view engine', 'ejs'); + +(async () => { + const httpServer = server.listen(process.env.PORT || 8080, () => { + console.log(`App started successfully.\nVisit -> ${Noco.dashboardUrl}`); + }); + server.use(await Noco.init({}, httpServer, server)); +})().catch((e) => console.log(e)); diff --git a/packages/nocodb/webpack.local.config.js b/packages/nocodb/webpack.local.config.js new file mode 100644 index 0000000000..39677bd35d --- /dev/null +++ b/packages/nocodb/webpack.local.config.js @@ -0,0 +1,53 @@ +const nodeExternals = require('webpack-node-externals'); +const webpack = require('webpack'); +const TerserPlugin = require('terser-webpack-plugin'); + +const path = require('path'); +module.exports = { + entry: './src/run/local.ts', + // devtool: 'inline-source-map', + module: { + rules: [ + { + test: /\.tsx?$/, + exclude: /node_modules/, + use: { + loader: 'ts-loader', + options: { + transpileOnly: true + } + }, + }, + ], + }, + + optimization: { + minimize: true, //Update this to true or false + minimizer: [new TerserPlugin()], + nodeEnv: false + }, + externals: [nodeExternals({ + allowlist: ['nocodb-sdk'] + })], + resolve: { + extensions: ['.tsx', '.ts', '.js', '.json'], + }, + output: { + filename: 'main.js', + path: path.resolve(__dirname, 'docker'), + library: 'libs', + libraryTarget: 'umd', + globalObject: "typeof self !== 'undefined' ? self : this" + }, + node: { + fs: 'empty', + __dirname: false, + }, + plugins: [ + new webpack.EnvironmentPlugin([ + 'EE' + ]), + ], + + target: 'node', +};