feat(node): add docker as a build target (#14475)
This commit is contained in:
parent
7857ae00a0
commit
0e018e620e
@ -5015,6 +5015,14 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExternal": false,
|
"isExternal": false,
|
||||||
"disableCollapsible": false
|
"disableCollapsible": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "setup-docker",
|
||||||
|
"path": "/packages/node/generators/setup-docker",
|
||||||
|
"name": "setup-docker",
|
||||||
|
"children": [],
|
||||||
|
"isExternal": false,
|
||||||
|
"disableCollapsible": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"isExternal": false,
|
"isExternal": false,
|
||||||
|
|||||||
@ -1554,6 +1554,15 @@
|
|||||||
"originalFilePath": "/packages/node/src/generators/library/schema.json",
|
"originalFilePath": "/packages/node/src/generators/library/schema.json",
|
||||||
"path": "/packages/node/generators/library",
|
"path": "/packages/node/generators/library",
|
||||||
"type": "generator"
|
"type": "generator"
|
||||||
|
},
|
||||||
|
"/packages/node/generators/setup-docker": {
|
||||||
|
"description": "Set up Docker configuration for a project.",
|
||||||
|
"file": "generated/packages/node/generators/setup-docker.json",
|
||||||
|
"hidden": false,
|
||||||
|
"name": "setup-docker",
|
||||||
|
"originalFilePath": "/packages/node/src/generators/setup-docker/schema.json",
|
||||||
|
"path": "/packages/node/generators/setup-docker",
|
||||||
|
"type": "generator"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"path": "/packages/node"
|
"path": "/packages/node"
|
||||||
|
|||||||
@ -1531,6 +1531,15 @@
|
|||||||
"originalFilePath": "/packages/node/src/generators/library/schema.json",
|
"originalFilePath": "/packages/node/src/generators/library/schema.json",
|
||||||
"path": "node/generators/library",
|
"path": "node/generators/library",
|
||||||
"type": "generator"
|
"type": "generator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Set up Docker configuration for a project.",
|
||||||
|
"file": "generated/packages/node/generators/setup-docker.json",
|
||||||
|
"hidden": false,
|
||||||
|
"name": "setup-docker",
|
||||||
|
"originalFilePath": "/packages/node/src/generators/setup-docker/schema.json",
|
||||||
|
"path": "node/generators/setup-docker",
|
||||||
|
"type": "generator"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"githubRoot": "https://github.com/nrwl/nx/blob/master",
|
"githubRoot": "https://github.com/nrwl/nx/blob/master",
|
||||||
|
|||||||
@ -110,6 +110,10 @@
|
|||||||
"enum": ["jest", "none"],
|
"enum": ["jest", "none"],
|
||||||
"description": "Test runner to use for end to end (e2e) tests",
|
"description": "Test runner to use for end to end (e2e) tests",
|
||||||
"default": "jest"
|
"default": "jest"
|
||||||
|
},
|
||||||
|
"docker": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Add a docker build target"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [],
|
"required": [],
|
||||||
|
|||||||
36
docs/generated/packages/node/generators/setup-docker.json
Normal file
36
docs/generated/packages/node/generators/setup-docker.json
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "setup-docker",
|
||||||
|
"factory": "./src/generators/setup-docker/setup-docker",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "http://json-schema.org/schema",
|
||||||
|
"cli": "nx",
|
||||||
|
"$id": "SchematicsNxSetupDocker",
|
||||||
|
"title": "Nx Node Docker Options Schema",
|
||||||
|
"description": "Nx Node Docker Options Schema.",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"projectName": {
|
||||||
|
"description": "The name of the project",
|
||||||
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"targetName": {
|
||||||
|
"description": "The name of the target to create",
|
||||||
|
"type": "string",
|
||||||
|
"default": "docker-build"
|
||||||
|
},
|
||||||
|
"buildTargetName": {
|
||||||
|
"description": "The name of the build target",
|
||||||
|
"type": "string",
|
||||||
|
"default": "build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presets": []
|
||||||
|
},
|
||||||
|
"description": "Set up Docker configuration for a project.",
|
||||||
|
"hidden": false,
|
||||||
|
"implementation": "/packages/node/src/generators/setup-docker/setup-docker.ts",
|
||||||
|
"aliases": [],
|
||||||
|
"path": "/packages/node/src/generators/setup-docker/schema.json",
|
||||||
|
"type": "generator"
|
||||||
|
}
|
||||||
@ -23,6 +23,12 @@
|
|||||||
"aliases": ["lib"],
|
"aliases": ["lib"],
|
||||||
"x-type": "library",
|
"x-type": "library",
|
||||||
"description": "Create a node library."
|
"description": "Create a node library."
|
||||||
|
},
|
||||||
|
"setup-docker": {
|
||||||
|
"factory": "./src/generators/setup-docker/setup-docker",
|
||||||
|
"schema": "./src/generators/setup-docker/schema.json",
|
||||||
|
"description": "Set up Docker configuration for a project.",
|
||||||
|
"hidden": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"schematics": {
|
"schematics": {
|
||||||
@ -46,6 +52,11 @@
|
|||||||
"aliases": ["lib"],
|
"aliases": ["lib"],
|
||||||
"x-type": "library",
|
"x-type": "library",
|
||||||
"description": "Create a node library."
|
"description": "Create a node library."
|
||||||
|
},
|
||||||
|
"setup-docker": {
|
||||||
|
"factory": "./src/generators/setup-docker/setup-docker#setupDockerGenerator",
|
||||||
|
"schema": "./src/generators/setup-docker/schema.json",
|
||||||
|
"description": "Set up Docker configuration for a project."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,6 +44,7 @@ import {
|
|||||||
|
|
||||||
import * as shared from '@nrwl/workspace/src/utils/create-ts-config';
|
import * as shared from '@nrwl/workspace/src/utils/create-ts-config';
|
||||||
import { e2eProjectGenerator } from '../e2e-project/e2e-project';
|
import { e2eProjectGenerator } from '../e2e-project/e2e-project';
|
||||||
|
import { setupDockerGenerator } from '../setup-docker/setup-docker';
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema extends Schema {
|
||||||
appProjectRoot: string;
|
appProjectRoot: string;
|
||||||
@ -374,6 +375,15 @@ export async function applicationGenerator(tree: Tree, schema: Schema) {
|
|||||||
addProxy(tree, options);
|
addProxy(tree, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.docker) {
|
||||||
|
const dockerTask = await setupDockerGenerator(tree, {
|
||||||
|
...options,
|
||||||
|
projectName: options.name,
|
||||||
|
});
|
||||||
|
|
||||||
|
tasks.push(dockerTask);
|
||||||
|
}
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
await formatFiles(tree);
|
await formatFiles(tree);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ export interface Schema {
|
|||||||
framework?: NodeJsFrameWorks;
|
framework?: NodeJsFrameWorks;
|
||||||
port?: number;
|
port?: number;
|
||||||
rootProject?: boolean;
|
rootProject?: boolean;
|
||||||
|
docker?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type NodeJsFrameWorks =
|
export type NodeJsFrameWorks =
|
||||||
|
|||||||
@ -110,6 +110,10 @@
|
|||||||
"enum": ["jest", "none"],
|
"enum": ["jest", "none"],
|
||||||
"description": "Test runner to use for end to end (e2e) tests",
|
"description": "Test runner to use for end to end (e2e) tests",
|
||||||
"default": "jest"
|
"default": "jest"
|
||||||
|
},
|
||||||
|
"docker": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Add a docker build target"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
FROM docker.io/node:lts-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN addgroup --system <%= projectName %> && \
|
||||||
|
adduser --system -G <%= projectName %> <%= projectName %>
|
||||||
|
|
||||||
|
COPY <%= buildLocation %> dist
|
||||||
|
RUN chown -R <%= projectName %>:<%= projectName %> .
|
||||||
|
|
||||||
|
CMD [ "node", "dist" ]
|
||||||
6
packages/node/src/generators/setup-docker/schema.d.ts
vendored
Normal file
6
packages/node/src/generators/setup-docker/schema.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export interface SetUpDockerOptions {
|
||||||
|
projectName?: string;
|
||||||
|
targetName?: string;
|
||||||
|
buildTarget?: string;
|
||||||
|
skipFormat?: boolean;
|
||||||
|
}
|
||||||
25
packages/node/src/generators/setup-docker/schema.json
Normal file
25
packages/node/src/generators/setup-docker/schema.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/schema",
|
||||||
|
"cli": "nx",
|
||||||
|
"$id": "SchematicsNxSetupDocker",
|
||||||
|
"title": "Nx Node Docker Options Schema",
|
||||||
|
"description": "Nx Node Docker Options Schema.",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"projectName": {
|
||||||
|
"description": "The name of the project",
|
||||||
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"targetName": {
|
||||||
|
"description": "The name of the target to create",
|
||||||
|
"type": "string",
|
||||||
|
"default": "docker-build"
|
||||||
|
},
|
||||||
|
"buildTargetName": {
|
||||||
|
"description": "The name of the build target",
|
||||||
|
"type": "string",
|
||||||
|
"default": "build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
import { readProjectConfiguration, Tree } from '@nrwl/devkit';
|
||||||
|
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||||
|
import { applicationGenerator } from '../application/application';
|
||||||
|
describe('setupDockerGenerator', () => {
|
||||||
|
let tree: Tree;
|
||||||
|
beforeEach(async () => {
|
||||||
|
tree = createTreeWithEmptyWorkspace();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('integrated', () => {
|
||||||
|
it('should create docker assets when --docker is passed', async () => {
|
||||||
|
await applicationGenerator(tree, {
|
||||||
|
name: 'api',
|
||||||
|
framework: 'express',
|
||||||
|
e2eTestRunner: 'none',
|
||||||
|
docker: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const project = readProjectConfiguration(tree, 'api');
|
||||||
|
|
||||||
|
expect(tree.exists('api/Dockerfile')).toBeTruthy();
|
||||||
|
expect(project.targets).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
'docker-build': {
|
||||||
|
dependsOn: ['build'],
|
||||||
|
executor: 'nx:run-commands',
|
||||||
|
options: {
|
||||||
|
commands: ['docker build -f api/Dockerfile .'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('standalone', () => {
|
||||||
|
it('should create docker assets when --docker is passed', async () => {
|
||||||
|
await applicationGenerator(tree, {
|
||||||
|
name: 'api',
|
||||||
|
framework: 'fastify',
|
||||||
|
rootProject: true,
|
||||||
|
docker: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const project = readProjectConfiguration(tree, 'api');
|
||||||
|
expect(tree.exists('Dockerfile')).toBeTruthy();
|
||||||
|
expect(project.targets).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
'docker-build': {
|
||||||
|
dependsOn: ['build'],
|
||||||
|
executor: 'nx:run-commands',
|
||||||
|
options: {
|
||||||
|
commands: ['docker build -f Dockerfile .'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
88
packages/node/src/generators/setup-docker/setup-docker.ts
Normal file
88
packages/node/src/generators/setup-docker/setup-docker.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import {
|
||||||
|
addDependenciesToPackageJson,
|
||||||
|
convertNxGenerator,
|
||||||
|
formatFiles,
|
||||||
|
generateFiles,
|
||||||
|
GeneratorCallback,
|
||||||
|
joinPathFragments,
|
||||||
|
logger,
|
||||||
|
readNxJson,
|
||||||
|
readProjectConfiguration,
|
||||||
|
Tree,
|
||||||
|
updateProjectConfiguration,
|
||||||
|
} from '@nrwl/devkit';
|
||||||
|
import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial';
|
||||||
|
import { SetUpDockerOptions } from './schema';
|
||||||
|
|
||||||
|
function normalizeOptions(
|
||||||
|
tree: Tree,
|
||||||
|
setupOptions: SetUpDockerOptions
|
||||||
|
): SetUpDockerOptions {
|
||||||
|
return {
|
||||||
|
...setupOptions,
|
||||||
|
projectName: setupOptions.projectName ?? readNxJson(tree).defaultProject,
|
||||||
|
targetName: setupOptions.targetName ?? 'docker-build',
|
||||||
|
buildTarget: setupOptions.buildTarget ?? 'build',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function addDocker(tree: Tree, options: SetUpDockerOptions) {
|
||||||
|
const project = readProjectConfiguration(tree, options.projectName);
|
||||||
|
if (!project || !options.targetName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tree.exists(joinPathFragments(project.root, 'DockerFile'))) {
|
||||||
|
logger.info(
|
||||||
|
`Skipping setup since a Dockerfile already exists inside ${project.root}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const outputPath =
|
||||||
|
project.targets[`${options.buildTarget}`]?.options.outputPath;
|
||||||
|
generateFiles(tree, joinPathFragments(__dirname, './files'), project.root, {
|
||||||
|
tmpl: '',
|
||||||
|
app: project.sourceRoot,
|
||||||
|
buildLocation: outputPath,
|
||||||
|
projectName: options.projectName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateProjectConfig(tree: Tree, options: SetUpDockerOptions) {
|
||||||
|
let projectConfig = readProjectConfiguration(tree, options.projectName);
|
||||||
|
|
||||||
|
projectConfig.targets[`${options.targetName}`] = {
|
||||||
|
dependsOn: [`${options.buildTarget}`],
|
||||||
|
executor: 'nx:run-commands',
|
||||||
|
options: {
|
||||||
|
commands: [
|
||||||
|
`docker build -f ${joinPathFragments(
|
||||||
|
projectConfig.root,
|
||||||
|
'Dockerfile'
|
||||||
|
)} .`,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
updateProjectConfiguration(tree, options.projectName, projectConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setupDockerGenerator(
|
||||||
|
tree: Tree,
|
||||||
|
setupOptions: SetUpDockerOptions
|
||||||
|
) {
|
||||||
|
const tasks: GeneratorCallback[] = [];
|
||||||
|
const options = normalizeOptions(tree, setupOptions);
|
||||||
|
// Should check if the node project exists
|
||||||
|
addDocker(tree, options);
|
||||||
|
updateProjectConfig(tree, options);
|
||||||
|
|
||||||
|
if (!options.skipFormat) {
|
||||||
|
await formatFiles(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
return runTasksInSerial(...tasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default setupDockerGenerator;
|
||||||
|
export const setupDockerSchematic = convertNxGenerator(setupDockerGenerator);
|
||||||
Loading…
x
Reference in New Issue
Block a user