diff --git a/api/libs/applications/cleanup/index.js b/api/libs/applications/cleanup/index.js index 3cfa6269f..9e78a7cae 100644 --- a/api/libs/applications/cleanup/index.js +++ b/api/libs/applications/cleanup/index.js @@ -2,9 +2,12 @@ const { docker } = require('../../docker') const { execShellAsync } = require('../../common') const Deployment = require('../../../models/Deployment') -async function purgeImagesContainers () { +async function purgeImagesContainers (configuration) { + const { name, tag } = configuration.build.container await execShellAsync('docker container prune -f') - await execShellAsync('docker image prune -f --filter=label!=coolify-reserve=true') + const IDsToDelete = (await execShellAsync(`docker images ls --filter=reference='${name}' --filter=before='${name}:${tag}' --format '{{json .ID }}'`)).trim().replace(/"/g, '').split('\n') + if (IDsToDelete.length !== 0) for (const id of IDsToDelete) await execShellAsync(`docker rmi -f ${id}`) + await execShellAsync('docker image prune -f') } async function cleanupStuckedDeploymentsInDB () { diff --git a/api/libs/applications/index.js b/api/libs/applications/index.js index 875426739..f28341d56 100644 --- a/api/libs/applications/index.js +++ b/api/libs/applications/index.js @@ -1,19 +1,16 @@ const dayjs = require('dayjs') -const { cleanupTmp } = require('../common') - const { saveAppLog } = require('../logging') const copyFiles = require('./deploy/copyFiles') const buildContainer = require('./build/container') const deploy = require('./deploy/deploy') const Deployment = require('../../models/Deployment') -const { purgeImagesContainers } = require('./cleanup') const { updateServiceLabels } = require('./configuration') async function queueAndBuild (configuration, imageChanged) { const { id, organization, name, branch } = configuration.repository const { domain } = configuration.publish - const { deployId, nickname, workdir } = configuration.general + const { deployId, nickname } = configuration.general await new Deployment({ repoId: id, branch, deployId, domain, organization, name, nickname }).save() @@ -25,8 +22,6 @@ async function queueAndBuild (configuration, imageChanged) { { repoId: id, branch, deployId, organization, name, domain }, { repoId: id, branch, deployId, organization, name, domain, progress: 'done' }) await updateServiceLabels(configuration) - cleanupTmp(workdir) - await purgeImagesContainers() } module.exports = { queueAndBuild } diff --git a/api/libs/common.js b/api/libs/common.js index 0225e8224..8a9c09bff 100644 --- a/api/libs/common.js +++ b/api/libs/common.js @@ -10,7 +10,7 @@ const baseServiceConfiguration = { replicas: 1, restart_policy: { condition: 'any', - max_attempts: 3 + max_attempts: 6 }, update_config: { parallelism: 1, diff --git a/api/routes/v1/application/deploy/index.js b/api/routes/v1/application/deploy/index.js index 8bcc84dbd..9b2751afd 100644 --- a/api/routes/v1/application/deploy/index.js +++ b/api/routes/v1/application/deploy/index.js @@ -2,6 +2,7 @@ const Deployment = require('../../../../models/Deployment') const ApplicationLog = require('../../../../models/Logs/Application') const { verifyUserId, cleanupTmp } = require('../../../../libs/common') +const { purgeImagesContainers } = require('../../../../libs/applications/cleanup') const { queueAndBuild } = require('../../../../libs/applications') const { setDefaultConfiguration, precheckDeployment } = require('../../../../libs/applications/configuration') const { docker } = require('../../../../libs/docker') @@ -55,12 +56,14 @@ module.exports = async function (fastify) { await Deployment.findOneAndUpdate( { repoId: id, branch, deployId, organization, name, domain }, { repoId: id, branch, deployId, organization, name, domain, progress: 'failed' }) - cleanupTmp(configuration.general.workdir) if (error.name) { if (error.message && error.stack) await saveServerLog(error) if (reply.sent) await new ApplicationLog({ repoId: id, branch, deployId, event: `[ERROR 😖]: ${error.stack}` }).save() } throw new Error(error) + } finally { + cleanupTmp(configuration.general.workdir) + await purgeImagesContainers(configuration) } }) } diff --git a/api/routes/v1/webhooks/deploy.js b/api/routes/v1/webhooks/deploy.js index 99b758dde..358991738 100644 --- a/api/routes/v1/webhooks/deploy.js +++ b/api/routes/v1/webhooks/deploy.js @@ -9,6 +9,7 @@ const { queueAndBuild } = require('../../../libs/applications') const { setDefaultConfiguration, precheckDeployment } = require('../../../libs/applications/configuration') const { docker } = require('../../../libs/docker') const cloneRepository = require('../../../libs/applications/github/cloneRepository') +const { purgeImagesContainers } = require('../../../libs/applications/cleanup') module.exports = async function (fastify) { // TODO: Add this to fastify plugin @@ -93,9 +94,9 @@ module.exports = async function (fastify) { reply.code(200).send({ message: 'Already in the queue.' }) return } - queueAndBuild(configuration, imageChanged) reply.code(201).send({ message: 'Deployment queued.', nickname: configuration.general.nickname, name: configuration.build.container.name }) + await queueAndBuild(configuration, imageChanged) } catch (error) { const { id, organization, name, branch } = configuration.repository const { domain } = configuration.publish @@ -103,7 +104,6 @@ module.exports = async function (fastify) { await Deployment.findOneAndUpdate( { repoId: id, branch, deployId, organization, name, domain }, { repoId: id, branch, deployId, organization, name, domain, progress: 'failed' }) - cleanupTmp(configuration.general.workdir) if (error.name === 'Error') { // Error during runtime await new ApplicationLog({ repoId: id, branch, deployId, event: `[ERROR 😖]: ${error.stack}` }).save() @@ -114,6 +114,9 @@ module.exports = async function (fastify) { if (reply.sent) await new ApplicationLog({ repoId: id, branch, deployId, event: `[ERROR 😖]: ${error.stack}` }).save() } throw new Error(error) + } finally { + cleanupTmp(configuration.general.workdir) + await purgeImagesContainers(configuration) } }) } diff --git a/api/server.js b/api/server.js index 4f25e93ab..12503dada 100644 --- a/api/server.js +++ b/api/server.js @@ -85,10 +85,8 @@ mongoose.connection.once('open', async function () { console.log('Coolify API is up and running in development.') } try { - const { main } = (await axios.get('https://get.coollabs.io/version.json')).data.coolify - if (main.clearServerLogs) { - await mongoose.connection.db.dropCollection('logs-servers') - } + // Always cleanup server logs + await mongoose.connection.db.dropCollection('logs-servers') } catch (error) { // Could not cleanup logs-servers collection } @@ -102,16 +100,11 @@ mongoose.connection.once('open', async function () { // Doing because I do not want to prune these images. Prune skips coolify-reserve labeled images. const basicImages = ['nginx:stable-alpine', 'node:lts', 'ubuntu:20.04', 'php:apache', 'rust:latest'] for (const image of basicImages) { - await execShellAsync(`echo "FROM ${image}" | docker build --label coolify-reserve=true -t ${image} -`) + // await execShellAsync(`echo "FROM ${image}" | docker build --label coolify-reserve=true -t ${image} -`) + await execShellAsync(`docker pull ${image}`) } } catch (error) { console.log('Could not pull some basic images from Docker Hub.') console.log(error) } - try { - await purgeImagesContainers() - } catch (error) { - console.log('Could not purge containers/images.') - console.log(error) - } }) diff --git a/package.json b/package.json index e8eeb15ef..596c64346 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "coolify", "description": "An open-source, hassle-free, self-hostable Heroku & Netlify alternative.", - "version": "1.0.9", + "version": "1.0.10", "license": "AGPL-3.0", "scripts": { "lint": "standard", diff --git a/src/utils/templates.js b/src/utils/templates.js index a09d45d53..de0a9014f 100644 --- a/src/utils/templates.js +++ b/src/utils/templates.js @@ -13,7 +13,7 @@ const templates = { nuxt: { pack: 'nodejs', ...defaultBuildAndDeploy, - port: 8080, + port: 3000, name: 'Nuxt' }, 'react-scripts': {