forked from loopbackio/loopback4-example-shopping
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdockerize.js
More file actions
executable file
·159 lines (135 loc) · 3.86 KB
/
Copy pathdockerize.js
File metadata and controls
executable file
·159 lines (135 loc) · 3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/usr/bin/env node
// Copyright IBM Corp. 2019,2020. All Rights Reserved.
// Node module: loopback4-example-shopping-monorepo
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
/**
* **Experimental**
*
* This script generates Docker files for packages from a monorepo managed
* by lerna. The image is built in two stages:
*
* 1. Create an image for the monorepo by copying the source code and running a build
* 2. Copy individual packages to their own images
*/
'use strict';
const path = require('path');
const fs = require('fs-extra');
const Project = require('@lerna/project');
/**
* Generate a file
* @param - file File path
* @param - content File content
*/
async function generateFile(
file,
content,
options = {
rootPath: process.cwd(),
dryRun: process.argv.includes('--dry-run'),
},
) {
if (options.dryRun) {
console.log('\n%s:', path.relative(options.rootPath, file));
console.log('-----------------------------------------------------------');
console.log(content);
console.log('-----------------------------------------------------------');
return;
}
await fs.outputFile(file, content, {encoding: 'utf-8', mode: options.mode});
}
/**
* Generate Docker files for the monorepo
* @param project - Lerna project
*/
async function generateDockerFiles(project = new Project(process.cwd())) {
const packages = await project.getPackages();
const rootPkg = require(path.join(project.rootPath, 'package.json'));
const appName = rootPkg.name.replace(/[@\/]/g, '_');
const appVersion = rootPkg.version;
const outDir = path.join(project.rootPath, 'docker-build');
const options = {
rootPath: project.rootPath,
dryRun: process.argv.includes('--dry-run'),
};
const rootDockerFile = path.join(outDir, 'Dockerfile');
// Generate root-level Dockerfile
await generateFile(
rootDockerFile,
`# Stage 1: build the monorepo
# Use the full image so that binary modules can be built
FROM node:12
# Set to a non-root built-in user \`node\`
USER node
# Create app directory (with user \`node\`)
RUN mkdir -p /home/node/app
WORKDIR /home/node/app
# Bundle app source code
COPY --chown=node . ./
RUN HUSKY_SKIP_INSTALL=1 npm ci && npm run build
`,
options,
);
// Generate root-level .dockerignore
await generateFile(
`${rootDockerFile}.dockerignore`,
`**/node_modules
npm-debug.log
**/dist
**/*.tsbuildinfo
`,
options,
);
for (const p of packages) {
const dir = path.relative(project.rootPath, p.location);
const dockerFile = path.join(outDir, dir, 'Dockerfile');
await generateFile(
dockerFile,
`# Stage 1: build the monorepo
ARG version=${appVersion}
FROM ${appName}:$\{version\} AS monorepo
# Stage 2: create the ${p.name} image
FROM node:12-slim
# Set to a non-root built-in user \`node\`
USER node
# Create app directory (with user \`node\`)
RUN mkdir -p /home/node/app
WORKDIR /home/node/app
# Bundle app source code
COPY --from=monorepo --chown=node /home/node/app/${dir} .
# Bind to all network interfaces so that it can be mapped to the host OS
ENV HOST=0.0.0.0 PORT=3001
EXPOSE $\{PORT\} 50051
CMD [ "node", "." ]
`,
options,
);
}
const buildCommands = [];
for (const p of packages) {
const dir = path.relative(project.rootPath, p.location);
buildCommands.push(`docker build -t ${p.name}:${p.version} ${dir}`);
}
await generateFile(
path.join(outDir, 'build-docker-images.sh'),
`#!/bin/bash
export DOCKER_BUILDKIT=1
set -e
BASE_DIR=\`dirname "$0"\`
pushd $BASE_DIR 2>&1 1>/dev/null
docker build -t ${appName}:${appVersion} -f Dockerfile ${path.relative(
outDir,
project.rootPath,
)}
${buildCommands.join('\n')}
popd
`,
{...options, mode: 0o755},
);
}
if (require.main === module) {
generateDockerFiles().catch(err => {
console.error(err);
process.exit(1);
});
}