coolify/apps/api/src/lib/buildPacks/compose.ts

131 lines
4 KiB
TypeScript
Raw Normal View History

2022-10-05 10:27:12 +00:00
import { promises as fs } from 'fs';
2022-12-21 09:11:03 +00:00
import { defaultComposeConfiguration, executeCommand, generateSecrets } from '../common';
import { saveBuildLog } from './common';
2022-10-05 10:27:12 +00:00
import yaml from 'js-yaml';
export default async function (data) {
let {
applicationId,
debug,
buildId,
dockerId,
network,
volumes,
labels,
workdir,
baseDirectory,
secrets,
pullmergeRequestId,
dockerComposeConfiguration,
dockerComposeFileLocation
} = data;
const fileYaml = `${workdir}${baseDirectory}${dockerComposeFileLocation}`;
const dockerComposeRaw = await fs.readFile(fileYaml, 'utf8');
const dockerComposeYaml = yaml.load(dockerComposeRaw);
if (!dockerComposeYaml.services) {
throw 'No Services found in docker-compose file.';
}
2022-12-21 12:24:30 +00:00
let envs = [];
let buildEnvs = [];
if (secrets.length > 0) {
2022-12-21 12:24:30 +00:00
envs = [...envs, ...generateSecrets(secrets, pullmergeRequestId, false, null)];
buildEnvs = [...buildEnvs, ...generateSecrets(secrets, pullmergeRequestId, true, null, true)];
}
2022-12-21 09:11:03 +00:00
const composeVolumes = [];
if (volumes.length > 0) {
for (const volume of volumes) {
let [v, path] = volume.split(':');
composeVolumes[v] = {
name: v
};
}
}
let networks = {};
for (let [key, value] of Object.entries(dockerComposeYaml.services)) {
value['container_name'] = `${applicationId}-${key}`;
2023-01-16 08:44:08 +00:00
let environment = typeof value['environment'] === 'undefined' ? [] : value['environment'];
if (Object.keys(environment).length > 0) {
environment = Object.entries(environment).map(([key, value]) => `${key}=${value}`);
}
2022-12-24 19:27:10 +00:00
value['environment'] = [...environment, ...envs];
2023-01-17 01:04:01 +00:00
let build = typeof value['build'] === 'undefined' ? {} : value['build'];
2023-01-17 01:11:06 +00:00
if (typeof build === 'string') {
build = { context: build }
}
2023-01-17 01:04:01 +00:00
let buildArgs = typeof build['args'] === 'undefined' ? [] : value['args'];
if (Object.keys(buildArgs).length > 0) {
buildArgs = Object.entries(buildArgs).map(([key, value]) => `${key}=${value}`);
}
value['build'] = {
...build,
2023-01-17 01:04:01 +00:00
args: [...buildArgs, ...buildEnvs]
};
value['labels'] = labels;
// TODO: If we support separated volume for each service, we need to add it here
if (value['volumes']?.length > 0) {
value['volumes'] = value['volumes'].map((volume) => {
let [v, path, permission] = volume.split(':');
if (!path) {
path = v;
v = `${applicationId}${v.replace(/\//gi, '-').replace(/\./gi, '')}`;
} else {
v = `${applicationId}${v.replace(/\//gi, '-').replace(/\./gi, '')}`;
}
composeVolumes[v] = {
name: v
};
return `${v}:${path}${permission ? ':' + permission : ''}`;
});
}
if (volumes.length > 0) {
for (const volume of volumes) {
value['volumes'].push(volume);
}
}
if (dockerComposeConfiguration[key].port) {
value['expose'] = [dockerComposeConfiguration[key].port];
}
if (value['networks']?.length > 0) {
value['networks'].forEach((network) => {
networks[network] = {
name: network
};
});
}
value['networks'] = [...(value['networks'] || ''), network];
dockerComposeYaml.services[key] = {
...dockerComposeYaml.services[key],
restart: defaultComposeConfiguration(network).restart,
deploy: defaultComposeConfiguration(network).deploy
};
}
if (Object.keys(composeVolumes).length > 0) {
dockerComposeYaml['volumes'] = { ...composeVolumes };
}
dockerComposeYaml['networks'] = Object.assign({ ...networks }, { [network]: { external: true } });
2022-12-21 09:11:03 +00:00
await fs.writeFile(fileYaml, yaml.dump(dockerComposeYaml));
console.log(yaml.dump(dockerComposeYaml));
await executeCommand({
debug,
buildId,
applicationId,
dockerId,
2023-01-16 08:44:08 +00:00
command: `docker compose --project-directory ${workdir} -f ${fileYaml} pull`
});
await saveBuildLog({ line: 'Pulling images from Compose file...', buildId, applicationId });
await executeCommand({
debug,
buildId,
applicationId,
dockerId,
2023-01-16 08:44:08 +00:00
command: `docker compose --project-directory ${workdir} -f ${fileYaml} build --progress plain`
});
await saveBuildLog({ line: 'Building images from Compose file...', buildId, applicationId });
2022-10-05 10:27:12 +00:00
}