From 9f1ed50fc64e8c9144eb5ecbe43e513a4175636e Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Thu, 26 Jan 2023 12:09:13 -0500 Subject: [PATCH] feat(node): improve docker setup for Node server apps (#14647) --- .../packages/node/generators/application.json | 2 +- .../node/generators/setup-docker.json | 8 +++++--- .../bin/create-nx-workspace.ts | 8 ++++---- .../src/generators/application/application.ts | 12 +++++++++--- .../application/files/common/src/app/.gitkeep | 0 .../files/express/src/main.ts__tmpl__ | 5 +++-- .../files/fastify/src/main.ts__tmpl__ | 5 +++-- .../application/files/koa/src/main.ts__tmpl__ | 5 +++-- .../src/generators/application/schema.json | 2 +- .../setup-docker/files/Dockerfile__tmpl__ | 19 ++++++++++++++----- .../src/generators/setup-docker/schema.d.ts | 2 +- .../src/generators/setup-docker/schema.json | 10 +++++++--- .../setup-docker/setup-docker.spec.ts | 4 ++-- .../generators/setup-docker/setup-docker.ts | 12 ++++++------ 14 files changed, 59 insertions(+), 35 deletions(-) delete mode 100644 packages/node/src/generators/application/files/common/src/app/.gitkeep diff --git a/docs/generated/packages/node/generators/application.json b/docs/generated/packages/node/generators/application.json index b813c16fb89cb..6657b9942ad9a 100644 --- a/docs/generated/packages/node/generators/application.json +++ b/docs/generated/packages/node/generators/application.json @@ -89,7 +89,7 @@ "framework": { "description": "Generate the node application using a framework", "type": "string", - "enum": ["express", "koa", "fastify", "none"], + "enum": ["express", "fastify", "koa", "none"], "default": "none", "x-prompt": "Which framework do you want to use?", "x-priority": "important" diff --git a/docs/generated/packages/node/generators/setup-docker.json b/docs/generated/packages/node/generators/setup-docker.json index 28de91d33a50b..f2b0c3cd3acce 100644 --- a/docs/generated/packages/node/generators/setup-docker.json +++ b/docs/generated/packages/node/generators/setup-docker.json @@ -9,10 +9,12 @@ "description": "Nx Node Docker Options Schema.", "type": "object", "properties": { - "projectName": { + "project": { "description": "The name of the project", - "$default": { "$source": "argv", "index": 0 }, - "type": "string" + "$default": { "$source": "projectName" }, + "type": "string", + "x-prompt": "What project would you like to add a Dockerfile to?", + "x-priority": "important" }, "targetName": { "description": "The name of the target to create", diff --git a/packages/create-nx-workspace/bin/create-nx-workspace.ts b/packages/create-nx-workspace/bin/create-nx-workspace.ts index b1438cb400e8e..b5e9c874164a6 100644 --- a/packages/create-nx-workspace/bin/create-nx-workspace.ts +++ b/packages/create-nx-workspace/bin/create-nx-workspace.ts @@ -701,14 +701,14 @@ async function determineFramework( name: 'express', message: 'Express [https://expressjs.com/]', }, - { - name: 'koa', - message: 'koa [https://koajs.com/]', - }, { name: 'fastify', message: 'fastify [https://www.fastify.io/]', }, + { + name: 'koa', + message: 'koa [https://koajs.com/]', + }, ]; if (!parsedArgs.framework) { diff --git a/packages/node/src/generators/application/application.ts b/packages/node/src/generators/application/application.ts index 2dee80504c269..cfb533eba6ab5 100644 --- a/packages/node/src/generators/application/application.ts +++ b/packages/node/src/generators/application/application.ts @@ -59,7 +59,10 @@ function getWebpackBuildConfig( options: { target: 'node', compiler: 'tsc', - outputPath: joinPathFragments('dist', options.appProjectRoot), + outputPath: joinPathFragments( + 'dist', + options.rootProject ? options.name : options.appProjectRoot + ), main: joinPathFragments( project.sourceRoot, 'main' + (options.js ? '.js' : '.ts') @@ -90,7 +93,10 @@ function getEsBuildConfig( executor: '@nrwl/esbuild:esbuild', outputs: ['{options.outputPath}'], options: { - outputPath: joinPathFragments('dist', options.appProjectRoot), + outputPath: joinPathFragments( + 'dist', + options.rootProject ? options.name : options.appProjectRoot + ), format: ['cjs'], main: joinPathFragments( project.sourceRoot, @@ -373,7 +379,7 @@ export async function applicationGenerator(tree: Tree, schema: Schema) { if (options.docker) { const dockerTask = await setupDockerGenerator(tree, { ...options, - projectName: options.name, + project: options.name, }); tasks.push(dockerTask); diff --git a/packages/node/src/generators/application/files/common/src/app/.gitkeep b/packages/node/src/generators/application/files/common/src/app/.gitkeep deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/packages/node/src/generators/application/files/express/src/main.ts__tmpl__ b/packages/node/src/generators/application/files/express/src/main.ts__tmpl__ index ff8cc91f14916..45394e7a95673 100644 --- a/packages/node/src/generators/application/files/express/src/main.ts__tmpl__ +++ b/packages/node/src/generators/application/files/express/src/main.ts__tmpl__ @@ -1,5 +1,6 @@ import express from 'express'; +const host = process.env.HOST ?? 'localhost'; const port = process.env.PORT ? Number(process.env.PORT) : <%= port %>; const app = express(); @@ -8,6 +9,6 @@ app.get('/', (req, res) => { res.send({ 'message': 'Hello API'}); }); -app.listen(port, () => { - console.log(`[ ready ] http://localhost:${port}`); +app.listen(port, host, () => { + console.log(`[ ready ] http://${host}:${port}`); }); diff --git a/packages/node/src/generators/application/files/fastify/src/main.ts__tmpl__ b/packages/node/src/generators/application/files/fastify/src/main.ts__tmpl__ index 55d5885312e96..9d5a682db92a5 100644 --- a/packages/node/src/generators/application/files/fastify/src/main.ts__tmpl__ +++ b/packages/node/src/generators/application/files/fastify/src/main.ts__tmpl__ @@ -1,5 +1,6 @@ import fastify from 'fastify'; +const host = process.env.HOST ?? 'localhost'; const port = process.env.PORT ? Number(process.env.PORT) : <%= port %>; const app = fastify(); @@ -10,8 +11,8 @@ app.get('/', async (req, res) => { const start = async() => { try { - await app.listen({ port }); - console.log(`[ ready ] http://localhost:${port}`); + await app.listen({ host, port }); + console.log(`[ ready ] http://${host}:${port}`); } catch (err) { // Errors are logged here process.exit(1); diff --git a/packages/node/src/generators/application/files/koa/src/main.ts__tmpl__ b/packages/node/src/generators/application/files/koa/src/main.ts__tmpl__ index 34b4ed4bfc878..2445d37a723ec 100644 --- a/packages/node/src/generators/application/files/koa/src/main.ts__tmpl__ +++ b/packages/node/src/generators/application/files/koa/src/main.ts__tmpl__ @@ -1,5 +1,6 @@ import koa from 'koa'; +const host = process.env.HOST ?? 'localhost'; const port = process.env.PORT ? Number(process.env.PORT) : <%= port %>; const app = new koa(); @@ -8,6 +9,6 @@ app.use(async ctx =>{ ctx.body = { 'message': 'Hello API'}; }); -app.listen(port, () => { - console.log(`[ ready ] http://localhost:${port}`); +app.listen(port, host, () => { + console.log(`[ ready ] http://${host}:${port}`); }); diff --git a/packages/node/src/generators/application/schema.json b/packages/node/src/generators/application/schema.json index 05b5ea334d19c..5900efcca44d9 100644 --- a/packages/node/src/generators/application/schema.json +++ b/packages/node/src/generators/application/schema.json @@ -89,7 +89,7 @@ "framework": { "description": "Generate the node application using a framework", "type": "string", - "enum": ["express", "koa", "fastify", "none"], + "enum": ["express", "fastify", "koa", "none"], "default": "none", "x-prompt": "Which framework do you want to use?", "x-priority": "important" diff --git a/packages/node/src/generators/setup-docker/files/Dockerfile__tmpl__ b/packages/node/src/generators/setup-docker/files/Dockerfile__tmpl__ index 30b670a33b879..f22b4e72140b7 100644 --- a/packages/node/src/generators/setup-docker/files/Dockerfile__tmpl__ +++ b/packages/node/src/generators/setup-docker/files/Dockerfile__tmpl__ @@ -1,11 +1,20 @@ +# This file is generated by Nx. +# +# Build the docker image with `npx nx docker-build <%= project %>`. +# Tip: Modify "docker-build" options in project.json to change docker build args. +# +# Run the container with `docker run -p 3000:3000 -t <%= project %>`. FROM docker.io/node:lts-alpine +ENV HOST=0.0.0.0 +ENV PORT=3000 + WORKDIR /app -RUN addgroup --system <%= projectName %> && \ - adduser --system -G <%= projectName %> <%= projectName %> +RUN addgroup --system <%= project %> && \ + adduser --system -G <%= project %> <%= project %> -COPY <%= buildLocation %> dist -RUN chown -R <%= projectName %>:<%= projectName %> . +COPY <%= buildLocation %> <%= project %> +RUN chown -R <%= project %>:<%= project %> . -CMD [ "node", "dist" ] \ No newline at end of file +CMD [ "node", "<%= project %>" ] diff --git a/packages/node/src/generators/setup-docker/schema.d.ts b/packages/node/src/generators/setup-docker/schema.d.ts index 8a7a88e6fee25..8083a66944495 100644 --- a/packages/node/src/generators/setup-docker/schema.d.ts +++ b/packages/node/src/generators/setup-docker/schema.d.ts @@ -1,5 +1,5 @@ export interface SetUpDockerOptions { - projectName?: string; + project?: string; targetName?: string; buildTarget?: string; skipFormat?: boolean; diff --git a/packages/node/src/generators/setup-docker/schema.json b/packages/node/src/generators/setup-docker/schema.json index 3495fad64b8a4..4361b8d6f7f70 100644 --- a/packages/node/src/generators/setup-docker/schema.json +++ b/packages/node/src/generators/setup-docker/schema.json @@ -6,10 +6,14 @@ "description": "Nx Node Docker Options Schema.", "type": "object", "properties": { - "projectName": { + "project": { "description": "The name of the project", - "$default": { "$source": "argv", "index": 0 }, - "type": "string" + "$default": { + "$source": "projectName" + }, + "type": "string", + "x-prompt": "What project would you like to add a Dockerfile to?", + "x-priority": "important" }, "targetName": { "description": "The name of the target to create", diff --git a/packages/node/src/generators/setup-docker/setup-docker.spec.ts b/packages/node/src/generators/setup-docker/setup-docker.spec.ts index 83927822b5d34..3a4b9932fa10e 100644 --- a/packages/node/src/generators/setup-docker/setup-docker.spec.ts +++ b/packages/node/src/generators/setup-docker/setup-docker.spec.ts @@ -25,7 +25,7 @@ describe('setupDockerGenerator', () => { dependsOn: ['build'], executor: 'nx:run-commands', options: { - commands: ['docker build -f api/Dockerfile .'], + commands: ['docker build -f api/Dockerfile . -t api'], }, }, }) @@ -50,7 +50,7 @@ describe('setupDockerGenerator', () => { dependsOn: ['build'], executor: 'nx:run-commands', options: { - commands: ['docker build -f Dockerfile .'], + commands: ['docker build -f Dockerfile . -t api'], }, }, }) diff --git a/packages/node/src/generators/setup-docker/setup-docker.ts b/packages/node/src/generators/setup-docker/setup-docker.ts index 60bf05a7addb0..705ab99e72327 100644 --- a/packages/node/src/generators/setup-docker/setup-docker.ts +++ b/packages/node/src/generators/setup-docker/setup-docker.ts @@ -20,14 +20,14 @@ function normalizeOptions( ): SetUpDockerOptions { return { ...setupOptions, - projectName: setupOptions.projectName ?? readNxJson(tree).defaultProject, + project: setupOptions.project ?? readNxJson(tree).defaultProject, targetName: setupOptions.targetName ?? 'docker-build', buildTarget: setupOptions.buildTarget ?? 'build', }; } function addDocker(tree: Tree, options: SetUpDockerOptions) { - const project = readProjectConfiguration(tree, options.projectName); + const project = readProjectConfiguration(tree, options.project); if (!project || !options.targetName) { return; } @@ -43,13 +43,13 @@ function addDocker(tree: Tree, options: SetUpDockerOptions) { tmpl: '', app: project.sourceRoot, buildLocation: outputPath, - projectName: options.projectName, + project: options.project, }); } } export function updateProjectConfig(tree: Tree, options: SetUpDockerOptions) { - let projectConfig = readProjectConfiguration(tree, options.projectName); + let projectConfig = readProjectConfiguration(tree, options.project); projectConfig.targets[`${options.targetName}`] = { dependsOn: [`${options.buildTarget}`], @@ -59,12 +59,12 @@ export function updateProjectConfig(tree: Tree, options: SetUpDockerOptions) { `docker build -f ${joinPathFragments( projectConfig.root, 'Dockerfile' - )} .`, + )} . -t ${options.project}`, ], }, }; - updateProjectConfiguration(tree, options.projectName, projectConfig); + updateProjectConfiguration(tree, options.project, projectConfig); } export async function setupDockerGenerator(