feat: basic auto-dockerization
This commit is contained in:
parent
0dc49ecc8e
commit
3d3181ebf4
|
@ -45,13 +45,7 @@ export default class ServerFlecks extends Flecks {
|
||||||
Object.keys(this.flecks)
|
Object.keys(this.flecks)
|
||||||
.sort((l, r) => (l < r ? 1 : -1))
|
.sort((l, r) => (l < r ? 1 : -1))
|
||||||
.forEach((fleck) => {
|
.forEach((fleck) => {
|
||||||
const prefix = `FLECKS_ENV_${
|
const prefix = `FLECKS_ENV_${this.constructor.environmentalize(fleck).toUpperCase()}`;
|
||||||
fleck
|
|
||||||
// - `@flecks/core` -> `FLECKS_CORE`
|
|
||||||
.replace(/[^a-zA-Z0-9]/g, '_')
|
|
||||||
.replace(/_*(.*)_*/, '$1')
|
|
||||||
.toUpperCase()
|
|
||||||
}`;
|
|
||||||
keys
|
keys
|
||||||
.filter((key) => key.startsWith(`${prefix}_`) && -1 === seen.indexOf(key))
|
.filter((key) => key.startsWith(`${prefix}_`) && -1 === seen.indexOf(key))
|
||||||
.map((key) => {
|
.map((key) => {
|
||||||
|
@ -360,6 +354,13 @@ export default class ServerFlecks extends Flecks {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static environmentalize(key) {
|
||||||
|
return key
|
||||||
|
// - `@flecks/core` -> `FLECKS_CORE`
|
||||||
|
.replace(/[^a-zA-Z0-9]/g, '_')
|
||||||
|
.replace(/_*(.*)_*/, '$1');
|
||||||
|
}
|
||||||
|
|
||||||
fleckIsAliased(fleck) {
|
fleckIsAliased(fleck) {
|
||||||
return this.constructor.fleckIsAliased(this.resolver, fleck);
|
return this.constructor.fleckIsAliased(this.resolver, fleck);
|
||||||
}
|
}
|
||||||
|
|
132
packages/docker/src/commands.js
Normal file
132
packages/docker/src/commands.js
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
import {spawn} from 'child_process';
|
||||||
|
import {writeFile} from 'fs/promises';
|
||||||
|
import {join, relative} from 'path';
|
||||||
|
|
||||||
|
import {D, dumpYml} from '@flecks/core';
|
||||||
|
|
||||||
|
const {
|
||||||
|
FLECKS_CORE_ROOT = process.cwd(),
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
|
const debug = D('@flecks/docker/commands');
|
||||||
|
|
||||||
|
export default (program, flecks) => {
|
||||||
|
const commands = {};
|
||||||
|
commands.compose = {
|
||||||
|
options: [
|
||||||
|
['-r, --run', 'run docker-compose'],
|
||||||
|
],
|
||||||
|
description: 'generate a docker compose file',
|
||||||
|
action: async (opts) => {
|
||||||
|
const {
|
||||||
|
run,
|
||||||
|
} = opts;
|
||||||
|
const output = join(FLECKS_CORE_ROOT, 'dist');
|
||||||
|
const lines = [
|
||||||
|
"version: '3'",
|
||||||
|
'services:',
|
||||||
|
'',
|
||||||
|
];
|
||||||
|
const services = {
|
||||||
|
app: {
|
||||||
|
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: {}};
|
||||||
|
});
|
||||||
|
return [
|
||||||
|
`FLECKS_ENV_${flecks.constructor.environmentalize(fleck).toUpperCase()}`,
|
||||||
|
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 qualified = 'app' === configService ? `${prefix}_${key}` : key;
|
||||||
|
services[configService].environment[qualified] = value;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Object.entries(services)
|
||||||
|
.forEach(([key, service]) => {
|
||||||
|
lines.push(
|
||||||
|
...dumpYml({[key]: service})
|
||||||
|
.split('\n')
|
||||||
|
.map((line) => ` ${line}`),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
const composeFile = join(output, 'docker-compose.yml');
|
||||||
|
debug('writing %s...', composeFile);
|
||||||
|
await writeFile(
|
||||||
|
composeFile,
|
||||||
|
lines
|
||||||
|
.map((line) => ('' === line.trim() ? '' : line))
|
||||||
|
.join('\n'),
|
||||||
|
);
|
||||||
|
const dockerFile = join(output, 'Dockerfile');
|
||||||
|
debug('writing %s...', dockerFile);
|
||||||
|
await writeFile(
|
||||||
|
dockerFile,
|
||||||
|
[
|
||||||
|
'FROM node:16',
|
||||||
|
'',
|
||||||
|
'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.groupEnd();
|
||||||
|
console.log();
|
||||||
|
/* eslint-enable no-console */
|
||||||
|
if (run) {
|
||||||
|
spawn(
|
||||||
|
'docker-compose',
|
||||||
|
['-f', 'dist/docker-compose.yml', 'up', '--build'],
|
||||||
|
{stdio: 'inherit'},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return commands;
|
||||||
|
};
|
|
@ -1,10 +1,18 @@
|
||||||
import {Hooks} from '@flecks/core';
|
import {Hooks} from '@flecks/core';
|
||||||
|
|
||||||
|
import commands from './commands';
|
||||||
import startContainer from './start-container';
|
import startContainer from './start-container';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
[Hooks]: {
|
[Hooks]: {
|
||||||
|
'@flecks/core/config': () => ({
|
||||||
|
enabled: true,
|
||||||
|
}),
|
||||||
|
'@flecks/core/commands': commands,
|
||||||
'@flecks/server/up': async (flecks) => {
|
'@flecks/server/up': async (flecks) => {
|
||||||
|
if (!flecks.get('@flecks/docker/server.enabled')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const containers = await flecks.invokeReduceAsync('@flecks/docker/containers');
|
const containers = await flecks.invokeReduceAsync('@flecks/docker/containers');
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
Object.entries(containers)
|
Object.entries(containers)
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
export default (flecks) => ({
|
export default (flecks) => ({
|
||||||
redis: {
|
redis: {
|
||||||
image: 'redis',
|
environment: {
|
||||||
|
app: {
|
||||||
|
host: 'redis',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
image: 'redis:6',
|
||||||
mount: '/data',
|
mount: '/data',
|
||||||
ports: {[flecks.get('@flecks/redis/server.port')]: 6379},
|
ports: {[flecks.get('@flecks/redis/server.port')]: 6379},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user