feat: deploy specific commit for apps

feat: keep number of images locally to revert quickly
This commit is contained in:
Andras Bacsai 2022-11-29 11:47:20 +01:00
parent ec00548f1b
commit 028ee6d7b1
9 changed files with 117 additions and 23 deletions

View File

@ -0,0 +1,35 @@
-- AlterTable
ALTER TABLE "Application" ADD COLUMN "gitCommitHash" TEXT;
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Setting" (
"id" TEXT NOT NULL PRIMARY KEY,
"fqdn" TEXT,
"dualCerts" BOOLEAN NOT NULL DEFAULT false,
"minPort" INTEGER NOT NULL DEFAULT 9000,
"maxPort" INTEGER NOT NULL DEFAULT 9100,
"DNSServers" TEXT NOT NULL DEFAULT '1.1.1.1,8.8.8.8',
"ipv4" TEXT,
"ipv6" TEXT,
"arch" TEXT,
"concurrentBuilds" INTEGER NOT NULL DEFAULT 1,
"applicationStoragePathMigrationFinished" BOOLEAN NOT NULL DEFAULT false,
"numberOfDockerImagesKeptLocally" INTEGER NOT NULL DEFAULT 3,
"proxyDefaultRedirect" TEXT,
"doNotTrack" BOOLEAN NOT NULL DEFAULT false,
"sentryDSN" TEXT,
"isAPIDebuggingEnabled" BOOLEAN NOT NULL DEFAULT false,
"isRegistrationEnabled" BOOLEAN NOT NULL DEFAULT true,
"isAutoUpdateEnabled" BOOLEAN NOT NULL DEFAULT false,
"isDNSCheckEnabled" BOOLEAN NOT NULL DEFAULT true,
"isTraefikUsed" BOOLEAN NOT NULL DEFAULT true,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
INSERT INTO "new_Setting" ("DNSServers", "applicationStoragePathMigrationFinished", "arch", "concurrentBuilds", "createdAt", "doNotTrack", "dualCerts", "fqdn", "id", "ipv4", "ipv6", "isAPIDebuggingEnabled", "isAutoUpdateEnabled", "isDNSCheckEnabled", "isRegistrationEnabled", "isTraefikUsed", "maxPort", "minPort", "proxyDefaultRedirect", "sentryDSN", "updatedAt") SELECT "DNSServers", "applicationStoragePathMigrationFinished", "arch", "concurrentBuilds", "createdAt", "doNotTrack", "dualCerts", "fqdn", "id", "ipv4", "ipv6", "isAPIDebuggingEnabled", "isAutoUpdateEnabled", "isDNSCheckEnabled", "isRegistrationEnabled", "isTraefikUsed", "maxPort", "minPort", "proxyDefaultRedirect", "sentryDSN", "updatedAt" FROM "Setting";
DROP TABLE "Setting";
ALTER TABLE "new_Setting" RENAME TO "Setting";
CREATE UNIQUE INDEX "Setting_fqdn_key" ON "Setting"("fqdn");
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;

View File

@ -30,6 +30,7 @@ model Setting {
arch String?
concurrentBuilds Int @default(1)
applicationStoragePathMigrationFinished Boolean @default(false)
numberOfDockerImagesKeptLocally Int @default(3)
proxyDefaultRedirect String?
doNotTrack Boolean @default(false)
sentryDSN String?

View File

@ -65,6 +65,7 @@ import * as buildpacks from '../lib/buildPacks';
baseImage,
baseBuildImage,
deploymentType,
gitCommitHash,
} = application
let {
@ -169,7 +170,7 @@ import * as buildpacks from '../lib/buildPacks';
githubAppId: gitSource.githubApp?.id,
gitlabAppId: gitSource.gitlabApp?.id,
customPort: gitSource.customPort,
gitCommitHash: gitCommitHash,
gitCommitHash,
configuration,
repository,
branch,

View File

@ -635,7 +635,6 @@ export async function buildImage({
const cache = `${applicationId}:${tag}${isCache ? '-cache' : ''}`
const { dockerRegistry: { url, username, password } } = await prisma.application.findUnique({ where: { id: applicationId }, select: { dockerRegistry: true } })
const location = await saveDockerRegistryCredentials({ url, username, password, workdir })
console.log(`docker ${location ? `--config ${location}` : ''} build --progress plain -f ${workdir}/${dockerFile} -t ${cache} --build-arg SOURCE_COMMIT=${commit} ${workdir}`)
await executeDockerCmd({ debug, buildId, applicationId, dockerId, command: `docker ${location ? `--config ${location}` : ''} build --progress plain -f ${workdir}/${dockerFile} -t ${cache} --build-arg SOURCE_COMMIT=${commit} ${workdir}` })

View File

@ -1587,22 +1587,44 @@ export async function cleanupDockerStorage(dockerId, lowDiskSpace, force) {
}
} catch (error) { }
if (lowDiskSpace || force) {
// if (isDev) {
// if (!force) console.log(`[DEV MODE] Low disk space: ${lowDiskSpace}`);
// return;
// }
// Cleanup images that are not used
try {
await executeDockerCmd({ dockerId, command: `docker image prune -f` });
} catch (error) { }
const { numberOfDockerImagesKeptLocally } = await prisma.setting.findUnique({ where: { id: '0' } })
const { stdout: images } = await executeDockerCmd({
dockerId,
command: `docker images | grep -v "<none>" | grep -v REPOSITORY | awk '{print $1, $2}'`
});
const imagesArray = images.trim().replaceAll(' ', ':').split('\n');
const imagesSet = new Set(imagesArray.map((image) => image.split(':')[0]));
let deleteImage = []
for (const image of imagesSet) {
let keepImage = []
for (const image2 of imagesArray) {
if (image2.startsWith(image)) {
if (keepImage.length >= numberOfDockerImagesKeptLocally) {
deleteImage.push(image2)
} else {
keepImage.push(image2)
}
}
}
}
for (const image of deleteImage) {
await executeDockerCmd({ dockerId, command: `docker image rm -f ${image}` });
}
// Prune coolify managed containers
try {
await executeDockerCmd({
dockerId,
command: `docker container prune -f --filter "label=coolify.managed=true"`
});
} catch (error) { }
try {
await executeDockerCmd({ dockerId, command: `docker image prune -f` });
} catch (error) { }
try {
await executeDockerCmd({ dockerId, command: `docker image prune -a -f` });
} catch (error) { }
// Cleanup build caches
try {
await executeDockerCmd({ dockerId, command: `docker builder prune -a -f` });

View File

@ -53,7 +53,8 @@ export async function listAllSettings(request: FastifyRequest) {
}
export async function saveSettings(request: FastifyRequest<SaveSettings>, reply: FastifyReply) {
try {
const {
let {
numberOfDockerImagesKeptLocally,
doNotTrack,
fqdn,
isAPIDebuggingEnabled,
@ -67,9 +68,12 @@ export async function saveSettings(request: FastifyRequest<SaveSettings>, reply:
proxyDefaultRedirect
} = request.body
const { id } = await listSettings();
if (numberOfDockerImagesKeptLocally) {
numberOfDockerImagesKeptLocally = Number(numberOfDockerImagesKeptLocally)
}
await prisma.setting.update({
where: { id },
data: { doNotTrack, isRegistrationEnabled, dualCerts, isAutoUpdateEnabled, isDNSCheckEnabled, DNSServers, isAPIDebuggingEnabled, }
data: { numberOfDockerImagesKeptLocally, doNotTrack, isRegistrationEnabled, dualCerts, isAutoUpdateEnabled, isDNSCheckEnabled, DNSServers, isAPIDebuggingEnabled, }
});
if (fqdn) {
await prisma.setting.update({ where: { id }, data: { fqdn } });

View File

@ -2,6 +2,7 @@ import { OnlyId } from "../../../../types"
export interface SaveSettings {
Body: {
numberOfDockerImagesKeptLocally: number,
doNotTrack: boolean,
fqdn: string,
isAPIDebuggingEnabled: boolean,

View File

@ -517,20 +517,28 @@
</div>
<div class="grid grid-cols-2 items-center">
<label for="repository">Git commit</label>
{#if isDisabled}
<div class="flex gap-2">
<input
class="w-full"
disabled={isDisabled || application.settings.isPublicRepository}
disabled={isDisabled}
placeholder="default: latest commit"
bind:value={application.gitCommitHash}
/>
{:else}
<input
class="w-full"
placeholder="default: latest commit"
bind:value={application.gitCommitHash}
/>
{/if}
<a href={application.gitSource.htmlUrl}/{application.repository}/commits/{application.branch} target="_blank" rel="noreferrer" class="btn btn-primary text-xs" >Commits<svg
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 24 24"
stroke-width="3"
stroke="currentColor"
class="w-3 h-3 text-white ml-2"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M4.5 19.5l15-15m0 0H8.25m11.25 0v11.25"
/>
</svg></a>
</div>
</div>
<div class="grid grid-cols-2 items-center">
<label for="repository">{$t('application.git_repository')}</label>

View File

@ -36,6 +36,7 @@
let maxPort = settings.maxPort;
let proxyDefaultRedirect = settings.proxyDefaultRedirect;
let doNotTrack = settings.doNotTrack;
let numberOfDockerImagesKeptLocally = settings.numberOfDockerImagesKeptLocally;
let forceSave = false;
let fqdn = settings.fqdn;
@ -165,6 +166,9 @@
if (proxyDefaultRedirect !== settings.proxyDefaultRedirect) {
await post(`/settings`, { proxyDefaultRedirect });
}
if (numberOfDockerImagesKeptLocally !== settings.numberOfDockerImagesKeptLocally) {
await post(`/settings`, { numberOfDockerImagesKeptLocally });
}
if (minPort !== settings.minPort || maxPort !== settings.maxPort) {
await post(`/settings`, { minPort, maxPort });
settings.minPort = minPort;
@ -393,6 +397,25 @@
on:click|preventDefault|stopPropagation={rollback}>Rollback</button
>
</div>
<div class="grid grid-cols-2 items-center">
<div>
Number of Docker Images kept locally
<Explainer
position="dropdown-bottom"
explanation="The number of Docker images kept locally on the server for EACH application. The oldest images will be deleted when the limit is reached.<br><br>Useful to rollback to a specific version of your applications quickly, but it will use more storage locally."
/>
</div>
<input
type="number"
class="w-full"
bind:value={numberOfDockerImagesKeptLocally}
readonly={!$appSession.isAdmin}
disabled={!$appSession.isAdmin}
name="numberOfDockerImagesKeptLocally"
id="numberOfDockerImagesKeptLocally"
placeholder="default: 3"
/>
</div>
<div class="grid grid-cols-2 items-center">
<div>
{$t('forms.public_port_range')}