UNPKG

7.2 kBJavaScriptView Raw
1'use strict';
2
3const {
4 generateDockerDebugOpts
5} = require('./debug');
6
7const debug = require('debug')('docker-opts');
8const nestedObjectAssign = require('nested-object-assign');
9const { addEnv } = require('./install/env');
10
11const _ = require('lodash');
12
13const { red } = require('colors');
14const httpx = require('httpx');
15const getVisitor = require('../lib/visitor').getVisitor;
16
17const DEFAULT_REGISTRY = 'registry.cn-beijing.aliyuncs.com';
18
19const DOCKER_REGISTRIES = [
20 DEFAULT_REGISTRY,
21 'registry.hub.docker.com'
22];
23
24let DOCKER_REGISTRY_CACHE;
25
26const runtimeImageMap = {
27 'nodejs6': 'nodejs6',
28 'nodejs8': 'nodejs8',
29 'python2.7': 'python2.7',
30 'python3': 'python3.6',
31 'java8': 'java8',
32 'php7.2': 'php7.2',
33 'nodejs10': 'nodejs10',
34 'custom': 'custom'
35};
36
37function resolveDockerEnv(envs = {}) {
38 return _.map(addEnv(envs || {}), (v, k) => `${k}=${v}`);
39}
40
41async function doImageRegisterEventTag(el) {
42 const visitor = await getVisitor();
43 visitor.event({
44 ec: 'imageRegistry',
45 ea: 'resolve',
46 el
47 }).send();
48}
49
50async function resolveDockerRegistry() {
51 await doImageRegisterEventTag('start');
52 if (DOCKER_REGISTRY_CACHE) {
53 return DOCKER_REGISTRY_CACHE;
54 }
55 const promises = DOCKER_REGISTRIES.map(r => httpx.request(`https://${r}/v2/aliyunfc/runtime-nodejs8/tags/list`, { timeout: 3000 }).then(() => r));
56 try {
57 DOCKER_REGISTRY_CACHE = await Promise.race(promises);
58 } catch (error) {
59 DOCKER_REGISTRY_CACHE = DEFAULT_REGISTRY;
60 }
61 await doImageRegisterEventTag(DOCKER_REGISTRY_CACHE);
62 return DOCKER_REGISTRY_CACHE;
63}
64
65const IMAGE_VERSION = '1.6.5';
66
67async function resolveRuntimeToDockerImage(runtime, isBuild) {
68 if (runtimeImageMap[runtime]) {
69 const name = runtimeImageMap[runtime];
70 var imageName;
71 if (isBuild) {
72 imageName = `aliyunfc/runtime-${name}:build-${IMAGE_VERSION}`;
73 } else {
74 imageName = `aliyunfc/runtime-${name}:${IMAGE_VERSION}`;
75 }
76
77 debug('imageName: ' + imageName);
78 return imageName;
79 }
80 throw new Error(red(`invalid runtime name ${runtime}`));
81}
82
83async function resolveImageNameForPull(imageName) {
84
85 const dockerImageRegistry = await resolveDockerRegistry();
86
87 if (dockerImageRegistry) {
88 imageName = `${dockerImageRegistry}/${imageName}`;
89 }
90 return imageName;
91}
92
93function generateInstallOpts(imageName, mounts, envs) {
94 return {
95 Image: imageName,
96 Tty: true,
97 Env: resolveDockerEnv(envs),
98 Cmd: ['/bin/bash'],
99 HostConfig: {
100 AutoRemove: true,
101 Mounts: mounts
102 }
103 };
104}
105
106function generateContainerName(serviceName, functionName, debugPort) {
107 return `fun-local-${serviceName}-${functionName}`.replace(/ /g, '')
108 + (debugPort ? '-debug' : '-run');
109}
110
111function generateContainerNameFilter(containerName, inited) {
112 if (inited) {
113 return `{"name": ["${containerName}-inited"]}`;
114 }
115 return `{"name": ["${containerName}"]}`;
116}
117
118function generateSboxOpts({imageName, hostname, mounts, envs, cmd = [], isTty, isInteractive}) {
119 return {
120 Image: imageName,
121 Hostname: hostname,
122 AttachStdin: isInteractive,
123 AttachStdout: true,
124 AttachStderr: true,
125 Tty: isTty,
126 OpenStdin: isInteractive,
127 StdinOnce: true,
128 Env: resolveDockerEnv(envs),
129 Cmd: cmd.length ? cmd : ['/bin/bash'],
130 HostConfig: {
131 AutoRemove: true,
132 Mounts: mounts
133 }
134 };
135}
136
137function transformPathForVirtualBox(source) {
138 // C:\\Users\\image_crawler\\code -> /c/Users/image_crawler/code
139 const sourcePath = source.split(':').join('');
140 const lowerFirstAndReplace = _.lowerFirst(sourcePath.split('\\').join('/'));
141 return '/' + lowerFirstAndReplace;
142}
143
144function transformMountsForToolbox(mounts) {
145
146 console.warn(red(`We detected that you are using docker toolbox. For a better experience, please upgrade 'docker for windows'.\nYou can refer to Chinese doc https://github.com/alibaba/funcraft/blob/master/docs/usage/installation-zh.md#windows-%E5%AE%89%E8%A3%85-docker or English doc https://github.com/alibaba/funcraft/blob/master/docs/usage/installation.md.\n`));
147
148 if (Array.isArray(mounts)) {
149 return mounts.map(m => {
150
151 return transformSourcePathOfMount(m);
152 });
153 }
154 return transformSourcePathOfMount(mounts);
155}
156
157function transformSourcePathOfMount(mountsObj) {
158
159 if (!_.isEmpty(mountsObj)) {
160
161 const replaceMounts = Object.assign({}, mountsObj);
162 replaceMounts.Source = transformPathForVirtualBox(mountsObj.Source);
163 return replaceMounts;
164 }
165 return {};
166}
167
168async function generateContainerBuildOpts(runtime, containerName, mounts, cmd, envs, preferredImage) {
169
170 const hostOpts = {
171 HostConfig: {
172 AutoRemove: true,
173 Mounts: mounts
174 }
175 };
176
177 const ioOpts = {
178 OpenStdin: true,
179 Tty: false,
180 StdinOnce: true,
181 AttachStdin: true,
182 AttachStdout: true,
183 AttachStderr: true
184 };
185
186 const imageName = await resolveRuntimeToDockerImage(runtime, true);
187
188 const opts = nestedObjectAssign(
189 {
190 Env: resolveDockerEnv(envs),
191 Image: preferredImage || imageName,
192 name: containerName,
193 Cmd: cmd,
194 User: '0:0'
195 },
196 ioOpts,
197 hostOpts);
198
199
200 debug('fc-docker docker options: %j', opts);
201
202 return opts;
203}
204
205async function generateLocalInvokeOpts(runtime, containerName, mounts, cmd, debugPort, envs, dockerUser, debugIde) {
206 const hostOpts = {
207 HostConfig: {
208 AutoRemove: true,
209 Mounts: mounts
210 }
211 };
212
213 let debugOpts = {};
214
215 if (debugPort) {
216 debugOpts = generateDockerDebugOpts(runtime, debugPort, debugIde);
217 }
218
219 const ioOpts = {
220 OpenStdin: true,
221 Tty: false,
222 StdinOnce: true,
223 AttachStdin: true,
224 AttachStdout: true,
225 AttachStderr: true
226 };
227
228 const imageName = await resolveRuntimeToDockerImage(runtime);
229
230 const opts = nestedObjectAssign(
231 {
232 Env: resolveDockerEnv(envs),
233 Image: imageName,
234 name: containerName,
235 Cmd: cmd,
236 User: dockerUser
237 },
238 ioOpts,
239 hostOpts,
240 debugOpts);
241
242
243 debug('fc-docker docker options: %j', opts);
244
245 return opts;
246}
247
248function resolveMockScript(runtime) {
249 return `/var/fc/runtime/${runtime}/mock`;
250}
251
252async function generateLocalStartOpts(runtime, name, mounts, cmd, debugPort, envs, dockerUser, debugIde) {
253
254 const hostOpts = {
255 HostConfig: {
256 AutoRemove: true,
257 Mounts: mounts
258 }
259 };
260
261 let debugOpts = {};
262
263 if (debugPort) {
264 debugOpts = generateDockerDebugOpts(runtime, debugPort, debugIde);
265 }
266
267 const imageName = await resolveRuntimeToDockerImage(runtime);
268
269 const opts = nestedObjectAssign(
270 {
271 Env: resolveDockerEnv(envs),
272 Image: imageName,
273 name,
274 Cmd: cmd,
275 User: dockerUser,
276 Entrypoint: [resolveMockScript(runtime)]
277 },
278 hostOpts,
279 debugOpts);
280
281 debug('docker options: %j', opts);
282
283 return opts;
284}
285
286module.exports = {
287 generateLocalInvokeOpts, resolveRuntimeToDockerImage,
288 generateInstallOpts, generateSboxOpts,
289 generateLocalStartOpts,
290 resolveMockScript, resolveDockerEnv, transformPathForVirtualBox,
291 resolveDockerRegistry, transformMountsForToolbox, transformSourcePathOfMount,
292 DOCKER_REGISTRIES, generateContainerBuildOpts,
293 IMAGE_VERSION, resolveImageNameForPull, generateContainerName,
294 generateContainerNameFilter
295};
\No newline at end of file