feat(docker): generation and hooks
This commit is contained in:
parent
f3f7fc7f6f
commit
2f7ebf66a2
|
@ -19,5 +19,23 @@ export const hooks = {
|
|||
ports: {3000: 3000},
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} dockerfile The content of the Dockerfile.
|
||||
*
|
||||
* @returns The new content of the Dockerfile.
|
||||
*/
|
||||
'@flecks/docker.Dockerfile': (dockerfile) => (
|
||||
dockerfile.replace('DEBUG=*', 'DEBUG=*,-*:silly')
|
||||
),
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Object} config The object representing the docker compose configuration.
|
||||
*/
|
||||
'@flecks/docker.docker-compose.yml': (config) => {
|
||||
config.version = '3.1';
|
||||
},
|
||||
|
||||
};
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import {spawn} from 'child_process';
|
||||
import {writeFile} from 'fs/promises';
|
||||
import {join, relative} from 'path';
|
||||
import {join} from 'path';
|
||||
|
||||
import {D} from '@flecks/core';
|
||||
import {dumpYml} from '@flecks/core/server';
|
||||
|
||||
import {generateComposeConfig, generateDockerFile} from './generate';
|
||||
|
||||
const {
|
||||
FLECKS_CORE_ROOT = process.cwd(),
|
||||
} = process.env;
|
||||
|
@ -26,105 +28,32 @@ export default (program, flecks) => {
|
|||
compose,
|
||||
tag,
|
||||
} = opts;
|
||||
const output = join(FLECKS_CORE_ROOT, 'dist');
|
||||
const lines = [
|
||||
"version: '3'",
|
||||
'services:',
|
||||
'',
|
||||
];
|
||||
const dockerFile = generateDockerFile(flecks);
|
||||
const composeConfig = await generateComposeConfig(flecks);
|
||||
const composeFile = dumpYml(composeConfig);
|
||||
const id = flecks.get('@flecks/core.id');
|
||||
const appServiceName = `${id}_app`;
|
||||
const services = {
|
||||
[appServiceName]: {
|
||||
build: {
|
||||
context: '..',
|
||||
dockerfile: 'dist/Dockerfile',
|
||||
},
|
||||
environment: {
|
||||
FLECKS_ENV_FLECKS_DOCKER_SERVER_enabled: 'false',
|
||||
},
|
||||
volumes: [
|
||||
'../node_modules:/var/www/node_modules',
|
||||
],
|
||||
},
|
||||
};
|
||||
const containers = flecks.invoke('@flecks/docker.containers');
|
||||
(
|
||||
await Promise.all(
|
||||
Object.entries(containers)
|
||||
.map(async ([fleck, config]) => {
|
||||
Object.entries(await config)
|
||||
.forEach(([key, config]) => {
|
||||
services[key] = {image: config.image, environment: {}, ...config.extra};
|
||||
});
|
||||
return [
|
||||
`FLECKS_ENV_${flecks.constructor.environmentalize(fleck)}`,
|
||||
config,
|
||||
];
|
||||
}),
|
||||
)
|
||||
)
|
||||
// Set environment.
|
||||
.forEach(([prefix, config]) => {
|
||||
Object.values(config)
|
||||
.forEach((config) => {
|
||||
Object.entries(config.environment || {})
|
||||
.forEach(([configService, environment]) => {
|
||||
Object.entries(environment || {})
|
||||
.forEach(([key, value]) => {
|
||||
const [realKey, realService] = 'app' === configService
|
||||
? [`${prefix}_${key}`, appServiceName]
|
||||
: [key, configService];
|
||||
services[realService].environment[realKey] = value;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Object.entries(services)
|
||||
.forEach(([key, service]) => {
|
||||
lines.push(
|
||||
...dumpYml({[key]: service})
|
||||
.split('\n')
|
||||
.map((line) => ` ${line}`),
|
||||
);
|
||||
});
|
||||
const composeFile = join(output, 'docker-compose.yml');
|
||||
const output = join(FLECKS_CORE_ROOT, 'dist');
|
||||
debug('writing %s...', composeFile);
|
||||
await writeFile(
|
||||
join(output, 'docker-compose.yml'),
|
||||
composeFile,
|
||||
lines
|
||||
.map((line) => ('' === line.trim() ? '' : line))
|
||||
.join('\n'),
|
||||
);
|
||||
const dockerFile = join(output, 'Dockerfile');
|
||||
debug('writing %s...', dockerFile);
|
||||
await writeFile(
|
||||
join(output, 'Dockerfile'),
|
||||
dockerFile,
|
||||
[
|
||||
'FROM node:20',
|
||||
'',
|
||||
'RUN mkdir -p /var/www',
|
||||
'WORKDIR /var/www',
|
||||
'COPY package.json /var/www',
|
||||
'COPY build /var/www/build',
|
||||
'COPY dist /var/www/dist',
|
||||
'',
|
||||
'ENV DEBUG=*',
|
||||
'ENV NODE_ENV=production',
|
||||
'',
|
||||
'CMD ["node", "./dist/index.js"]',
|
||||
'',
|
||||
'VOLUME /var/www/node_modules',
|
||||
'',
|
||||
].join('\n'),
|
||||
);
|
||||
/* eslint-disable no-console */
|
||||
console.log();
|
||||
console.log('Outputs:');
|
||||
console.log();
|
||||
console.group();
|
||||
console.log(relative(FLECKS_CORE_ROOT, composeFile));
|
||||
console.log(relative(FLECKS_CORE_ROOT, dockerFile));
|
||||
console.group('dist');
|
||||
console.group('Dockerfile');
|
||||
console.log(dockerFile);
|
||||
console.groupEnd();
|
||||
console.group('docker-compose.yml');
|
||||
console.log(composeFile);
|
||||
console.groupEnd();
|
||||
console.groupEnd();
|
||||
console.log();
|
||||
/* eslint-enable no-console */
|
||||
|
|
74
packages/docker/src/generate.js
Normal file
74
packages/docker/src/generate.js
Normal file
|
@ -0,0 +1,74 @@
|
|||
export const generateDockerFile = (flecks) => {
|
||||
const dockerfile = [
|
||||
'FROM node:20',
|
||||
'',
|
||||
'RUN mkdir -p /var/www',
|
||||
'WORKDIR /var/www',
|
||||
'COPY package.json /var/www',
|
||||
'COPY build /var/www/build',
|
||||
'COPY dist /var/www/dist',
|
||||
'',
|
||||
'ENV DEBUG=*',
|
||||
'ENV NODE_ENV=production',
|
||||
'',
|
||||
'CMD ["node", "./dist/index.js"]',
|
||||
'',
|
||||
'VOLUME /var/www/node_modules',
|
||||
'',
|
||||
].join('\n');
|
||||
return flecks.invokeComposed('@flecks/docker.Dockerfile', dockerfile);
|
||||
};
|
||||
|
||||
export const generateComposeConfig = async (flecks) => {
|
||||
const id = flecks.get('@flecks/core.id');
|
||||
const appServiceName = `${id}_app`;
|
||||
const services = {
|
||||
[appServiceName]: {
|
||||
build: {
|
||||
context: '..',
|
||||
dockerfile: 'dist/Dockerfile',
|
||||
},
|
||||
environment: {
|
||||
FLECKS_ENV_FLECKS_DOCKER_SERVER_enabled: 'false',
|
||||
},
|
||||
volumes: [
|
||||
'../node_modules:/var/www/node_modules',
|
||||
],
|
||||
},
|
||||
};
|
||||
const containers = flecks.invoke('@flecks/docker.containers');
|
||||
(
|
||||
await Promise.all(
|
||||
Object.entries(containers)
|
||||
.map(async ([fleck, config]) => {
|
||||
Object.entries(await config)
|
||||
.forEach(([key, config]) => {
|
||||
services[key] = {image: config.image, environment: {}, ...config.extra};
|
||||
});
|
||||
return [
|
||||
`FLECKS_ENV_${flecks.constructor.environmentalize(fleck)}`,
|
||||
config,
|
||||
];
|
||||
}),
|
||||
)
|
||||
)
|
||||
// Set environment.
|
||||
.forEach(([prefix, config]) => {
|
||||
Object.values(config)
|
||||
.forEach((config) => {
|
||||
Object.entries(config.environment || {})
|
||||
.forEach(([configService, environment]) => {
|
||||
Object.entries(environment || {})
|
||||
.forEach(([key, value]) => {
|
||||
const [realKey, realService] = 'app' === configService
|
||||
? [`${prefix}_${key}`, appServiceName]
|
||||
: [key, configService];
|
||||
services[realService].environment[realKey] = value;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
const config = {version: '3', services};
|
||||
flecks.invoke('@flecks/docker.docker-compose.yml', config);
|
||||
return config;
|
||||
};
|
33
packages/docker/src/plugin.js
Normal file
33
packages/docker/src/plugin.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
import {dumpYml} from '@flecks/core/server';
|
||||
|
||||
import {generateComposeConfig, generateDockerFile} from './generate';
|
||||
|
||||
class FlecksDockerOutput {
|
||||
|
||||
constructor(options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
apply(compiler) {
|
||||
compiler.hooks.compilation.tap('FlecksDockerOutput', (compilation) => {
|
||||
compilation.hooks.additionalAssets.tapAsync('FlecksDockerOutput', async (callback) => {
|
||||
const dockerFile = generateDockerFile(this.options.flecks);
|
||||
compilation.assets.Dockerfile = {
|
||||
source: () => dockerFile,
|
||||
size: () => dockerFile.length,
|
||||
};
|
||||
const composeConfig = await generateComposeConfig(this.options.flecks);
|
||||
const composeFile = dumpYml(composeConfig);
|
||||
compilation.assets['docker-compose.yml'] = {
|
||||
source: () => composeFile,
|
||||
size: () => composeFile.length,
|
||||
};
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default FlecksDockerOutput;
|
|
@ -1,7 +1,14 @@
|
|||
import commands from './commands';
|
||||
import FlecksDockerOutput from './plugin';
|
||||
import startContainer from './start-container';
|
||||
|
||||
export const hooks = {
|
||||
'@flecks/core.build': (target, config, env, argv, flecks) => {
|
||||
if ('server' !== target) {
|
||||
return;
|
||||
}
|
||||
config.plugins.push(new FlecksDockerOutput({flecks}));
|
||||
},
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* Whether to run docker containers.
|
||||
|
|
Loading…
Reference in New Issue
Block a user