From 88f3f628ef7d1b58ff548eb1ba58db954da26236 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 19 Dec 2022 11:51:44 +0100 Subject: [PATCH] fix: docker buildpack env --- apps/api/src/jobs/deployApplication.ts | 4 +- apps/api/src/lib/buildPacks/common.ts | 130 ++++++++++++++++--------- apps/api/src/lib/buildPacks/docker.ts | 22 +---- 3 files changed, 92 insertions(+), 64 deletions(-) diff --git a/apps/api/src/jobs/deployApplication.ts b/apps/api/src/jobs/deployApplication.ts index c43b63bec..7f0977043 100644 --- a/apps/api/src/jobs/deployApplication.ts +++ b/apps/api/src/jobs/deployApplication.ts @@ -589,7 +589,8 @@ import * as buildpacks from '../lib/buildPacks'; denoOptions, baseImage, baseBuildImage, - deploymentType + deploymentType, + forceRebuild }); else { await saveBuildLog({ @@ -716,7 +717,6 @@ import * as buildpacks from '../lib/buildPacks'; } }); } - console.log('hello'); await fs.writeFile(`${workdir}/.env`, envs.join('\n')); if (dockerRegistry) { const { url, username, password } = dockerRegistry; diff --git a/apps/api/src/lib/buildPacks/common.ts b/apps/api/src/lib/buildPacks/common.ts index 3eabbdcc2..f25e15e7d 100644 --- a/apps/api/src/lib/buildPacks/common.ts +++ b/apps/api/src/lib/buildPacks/common.ts @@ -1,6 +1,17 @@ -import { base64Encode, decrypt, encrypt, executeCommand, generateTimestamp, getDomain, isARM, isDev, prisma, version } from "../common"; +import { + base64Encode, + decrypt, + encrypt, + executeCommand, + generateTimestamp, + getDomain, + isARM, + isDev, + prisma, + version +} from '../common'; import { promises as fs } from 'fs'; -import { day } from "../dayjs"; +import { day } from '../dayjs'; const staticApps = ['static', 'react', 'vuejs', 'svelte', 'gatsby', 'astro', 'eleventy']; const nodeBased = [ @@ -17,7 +28,10 @@ const nodeBased = [ 'nextjs' ]; -export function setDefaultBaseImage(buildPack: string | null, deploymentType: string | null = null) { +export function setDefaultBaseImage( + buildPack: string | null, + deploymentType: string | null = null +) { const nodeVersions = [ { value: 'node:lts', @@ -316,8 +330,8 @@ export function setDefaultBaseImage(buildPack: string | null, deploymentType: st { value: 'heroku/builder-classic:22', label: 'heroku/builder-classic:22' - }, - ] + } + ]; let payload: any = { baseImage: null, baseBuildImage: null, @@ -327,7 +341,9 @@ export function setDefaultBaseImage(buildPack: string | null, deploymentType: st if (nodeBased.includes(buildPack)) { if (deploymentType === 'static') { payload.baseImage = isARM(process.arch) ? 'nginx:alpine' : 'webdevops/nginx:alpine'; - payload.baseImages = isARM(process.arch) ? staticVersions.filter((version) => !version.value.includes('webdevops')) : staticVersions; + payload.baseImages = isARM(process.arch) + ? staticVersions.filter((version) => !version.value.includes('webdevops')) + : staticVersions; payload.baseBuildImage = 'node:lts'; payload.baseBuildImages = nodeVersions; } else { @@ -339,7 +355,9 @@ export function setDefaultBaseImage(buildPack: string | null, deploymentType: st } if (staticApps.includes(buildPack)) { payload.baseImage = isARM(process.arch) ? 'nginx:alpine' : 'webdevops/nginx:alpine'; - payload.baseImages = isARM(process.arch) ? staticVersions.filter((version) => !version.value.includes('webdevops')) : staticVersions; + payload.baseImages = isARM(process.arch) + ? staticVersions.filter((version) => !version.value.includes('webdevops')) + : staticVersions; payload.baseBuildImage = 'node:lts'; payload.baseBuildImages = nodeVersions; } @@ -357,12 +375,20 @@ export function setDefaultBaseImage(buildPack: string | null, deploymentType: st payload.baseImage = 'denoland/deno:latest'; } if (buildPack === 'php') { - payload.baseImage = isARM(process.arch) ? 'php:8.1-fpm-alpine' : 'webdevops/php-apache:8.2-alpine'; - payload.baseImages = isARM(process.arch) ? phpVersions.filter((version) => !version.value.includes('webdevops')) : phpVersions + payload.baseImage = isARM(process.arch) + ? 'php:8.1-fpm-alpine' + : 'webdevops/php-apache:8.2-alpine'; + payload.baseImages = isARM(process.arch) + ? phpVersions.filter((version) => !version.value.includes('webdevops')) + : phpVersions; } if (buildPack === 'laravel') { - payload.baseImage = isARM(process.arch) ? 'php:8.1-fpm-alpine' : 'webdevops/php-apache:8.2-alpine'; - payload.baseImages = isARM(process.arch) ? phpVersions.filter((version) => !version.value.includes('webdevops')) : phpVersions + payload.baseImage = isARM(process.arch) + ? 'php:8.1-fpm-alpine' + : 'webdevops/php-apache:8.2-alpine'; + payload.baseImages = isARM(process.arch) + ? phpVersions.filter((version) => !version.value.includes('webdevops')) + : phpVersions; payload.baseBuildImage = 'node:18'; payload.baseBuildImages = nodeVersions; } @@ -405,7 +431,8 @@ export const setDefaultConfiguration = async (data: any) => { if (!publishDirectory) publishDirectory = template?.publishDirectory || null; if (baseDirectory) { if (!baseDirectory.startsWith('/')) baseDirectory = `/${baseDirectory}`; - if (baseDirectory.endsWith('/') && baseDirectory !== '/') baseDirectory = baseDirectory.slice(0, -1); + if (baseDirectory.endsWith('/') && baseDirectory !== '/') + baseDirectory = baseDirectory.slice(0, -1); } if (dockerFileLocation) { if (!dockerFileLocation.startsWith('/')) dockerFileLocation = `/${dockerFileLocation}`; @@ -414,8 +441,10 @@ export const setDefaultConfiguration = async (data: any) => { dockerFileLocation = '/Dockerfile'; } if (dockerComposeFileLocation) { - if (!dockerComposeFileLocation.startsWith('/')) dockerComposeFileLocation = `/${dockerComposeFileLocation}`; - if (dockerComposeFileLocation.endsWith('/')) dockerComposeFileLocation = dockerComposeFileLocation.slice(0, -1); + if (!dockerComposeFileLocation.startsWith('/')) + dockerComposeFileLocation = `/${dockerComposeFileLocation}`; + if (dockerComposeFileLocation.endsWith('/')) + dockerComposeFileLocation = dockerComposeFileLocation.slice(0, -1); } else { dockerComposeFileLocation = '/Dockerfile'; } @@ -479,7 +508,6 @@ export const scanningTemplates = { } }; - export const saveBuildLog = async ({ line, buildId, @@ -491,7 +519,7 @@ export const saveBuildLog = async ({ }): Promise => { if (buildId === 'undefined' || buildId === 'null' || !buildId) return; if (applicationId === 'undefined' || applicationId === 'null' || !applicationId) return; - const { default: got } = await import('got') + const { default: got } = await import('got'); if (typeof line === 'object' && line) { if (line.shortMessage) { line = line.shortMessage + '\n' + line.stderr; @@ -504,7 +532,11 @@ export const saveBuildLog = async ({ line = line.replace(regex, '@'); } const addTimestamp = `[${generateTimestamp()}] ${line}`; - const fluentBitUrl = isDev ? process.env.COOLIFY_CONTAINER_DEV === 'true' ? 'http://coolify-fluentbit:24224' : 'http://localhost:24224' : 'http://coolify-fluentbit:24224'; + const fluentBitUrl = isDev + ? process.env.COOLIFY_CONTAINER_DEV === 'true' + ? 'http://coolify-fluentbit:24224' + : 'http://localhost:24224' + : 'http://coolify-fluentbit:24224'; if (isDev && !process.env.COOLIFY_CONTAINER_DEV) { console.debug(`[${applicationId}] ${addTimestamp}`); @@ -514,15 +546,17 @@ export const saveBuildLog = async ({ json: { line: encrypt(line) } - }) + }); } catch (error) { return await prisma.buildLog.create({ data: { - line: addTimestamp, buildId, time: Number(day().valueOf()), applicationId + line: addTimestamp, + buildId, + time: Number(day().valueOf()), + applicationId } }); } - }; export async function copyBaseConfigurationFiles( @@ -610,7 +644,7 @@ export function checkPnpm(installCommand = null, buildCommand = null, startComma export async function saveDockerRegistryCredentials({ url, username, password, workdir }) { if (!username || !password) { - return null + return null; } let decryptedPassword = decrypt(password); @@ -622,14 +656,14 @@ export async function saveDockerRegistryCredentials({ url, username, password, w console.log(error); } const payload = JSON.stringify({ - "auths": { + auths: { [url]: { - "auth": Buffer.from(`${username}:${decryptedPassword}`).toString('base64') + auth: Buffer.from(`${username}:${decryptedPassword}`).toString('base64') } } - }) - await fs.writeFile(`${location}/config.json`, payload) - return location + }); + await fs.writeFile(`${location}/config.json`, payload); + return location; } export async function buildImage({ applicationId, @@ -640,29 +674,41 @@ export async function buildImage({ isCache = false, debug = false, dockerFileLocation = '/Dockerfile', - commit + commit, + forceRebuild = false }) { if (isCache) { await saveBuildLog({ line: `Building cache image...`, buildId, applicationId }); } else { await saveBuildLog({ line: `Building production image...`, buildId, applicationId }); } - const dockerFile = isCache ? `${dockerFileLocation}-cache` : `${dockerFileLocation}` - const cache = `${applicationId}:${tag}${isCache ? '-cache' : ''}` + const dockerFile = isCache ? `${dockerFileLocation}-cache` : `${dockerFileLocation}`; + const cache = `${applicationId}:${tag}${isCache ? '-cache' : ''}`; + let location = null; - let location = null - - const { dockerRegistry } = await prisma.application.findUnique({ where: { id: applicationId }, select: { dockerRegistry: true } }) + const { dockerRegistry } = await prisma.application.findUnique({ + where: { id: applicationId }, + select: { dockerRegistry: true } + }); if (dockerRegistry) { - const { url, username, password } = dockerRegistry - location = await saveDockerRegistryCredentials({ url, username, password, workdir }) + const { url, username, password } = dockerRegistry; + location = await saveDockerRegistryCredentials({ url, username, password, workdir }); } - await executeCommand({ stream: true, debug, buildId, applicationId, dockerId, command: `docker ${location ? `--config ${location}` : ''} build --progress plain -f ${workdir}/${dockerFile} -t ${cache} --build-arg SOURCE_COMMIT=${commit} ${workdir}` }) + await executeCommand({ + stream: true, + debug, + buildId, + applicationId, + dockerId, + command: `docker ${location ? `--config ${location}` : ''} build ${ + forceRebuild ? '--no-cache' : '' + } --progress plain -f ${workdir}/${dockerFile} -t ${cache} --build-arg SOURCE_COMMIT=${commit} ${workdir}` + }); - const { status } = await prisma.build.findUnique({ where: { id: buildId } }) + const { status } = await prisma.build.findUnique({ where: { id: buildId } }); if (status === 'canceled') { - throw new Error('Canceled.') + throw new Error('Canceled.'); } } export function makeLabelForSimpleDockerfile({ applicationId, port, type }) { @@ -744,7 +790,7 @@ export async function buildCacheImageWithNode(data, imageForBuild) { secrets.forEach((secret) => { if (secret.isBuildSecret) { if (pullmergeRequestId) { - const isSecretFound = secrets.filter(s => s.name === secret.name && s.isPRMRSecret) + const isSecretFound = secrets.filter((s) => s.name === secret.name && s.isPRMRSecret); if (isSecretFound.length > 0) { Dockerfile.push(`ARG ${secret.name}='${isSecretFound[0].value}'`); } else { @@ -782,7 +828,7 @@ export async function buildCacheImageForLaravel(data, imageForBuild) { secrets.forEach((secret) => { if (secret.isBuildSecret) { if (pullmergeRequestId) { - const isSecretFound = secrets.filter(s => s.name === secret.name && s.isPRMRSecret) + const isSecretFound = secrets.filter((s) => s.name === secret.name && s.isPRMRSecret); if (isSecretFound.length > 0) { Dockerfile.push(`ARG ${secret.name}='${isSecretFound[0].value}'`); } else { @@ -804,11 +850,7 @@ export async function buildCacheImageForLaravel(data, imageForBuild) { } export async function buildCacheImageWithCargo(data, imageForBuild) { - const { - applicationId, - workdir, - buildId, - } = data; + const { applicationId, workdir, buildId } = data; const Dockerfile: Array = []; Dockerfile.push(`FROM ${imageForBuild} as planner-${applicationId}`); diff --git a/apps/api/src/lib/buildPacks/docker.ts b/apps/api/src/lib/buildPacks/docker.ts index 9ab37e81c..2ef265fe3 100644 --- a/apps/api/src/lib/buildPacks/docker.ts +++ b/apps/api/src/lib/buildPacks/docker.ts @@ -2,24 +2,11 @@ import { promises as fs } from 'fs'; import { buildImage } from './common'; export default async function (data) { - let { - applicationId, - debug, - tag, - workdir, - buildId, - baseDirectory, - secrets, - pullmergeRequestId, - dockerFileLocation - } = data + let { workdir, buildId, baseDirectory, secrets, pullmergeRequestId, dockerFileLocation } = data; const file = `${workdir}${baseDirectory}${dockerFileLocation}`; data.workdir = `${workdir}${baseDirectory}`; - const DockerfileRaw = await fs.readFile(`${file}`, 'utf8') - const Dockerfile: Array = DockerfileRaw - .toString() - .trim() - .split('\n'); + const DockerfileRaw = await fs.readFile(`${file}`, 'utf8'); + const Dockerfile: Array = DockerfileRaw.toString().trim().split('\n'); Dockerfile.forEach((line, index) => { if (line.startsWith('FROM')) { Dockerfile.splice(index + 1, 0, `LABEL coolify.buildId=${buildId}`); @@ -41,7 +28,6 @@ export default async function (data) { } }); } - - await fs.writeFile(`${workdir}${dockerFileLocation}`, Dockerfile.join('\n')); + await fs.writeFile(`${data.workdir}${dockerFileLocation}`, Dockerfile.join('\n')); await buildImage(data); }