feat: able to push image to docker registry
This commit is contained in:
parent
127880cf8d
commit
8ccb0c88db
@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "Application" ADD COLUMN "dockerRegistryImageName" TEXT;
|
@ -133,6 +133,7 @@ model Application {
|
||||
baseBuildImage String?
|
||||
settings ApplicationSettings?
|
||||
dockerRegistryId String?
|
||||
dockerRegistryImageName String?
|
||||
simpleDockerfile String?
|
||||
|
||||
persistentStorage ApplicationPersistentStorage[]
|
||||
|
@ -3,8 +3,8 @@ import crypto from 'crypto';
|
||||
import fs from 'fs/promises';
|
||||
import yaml from 'js-yaml';
|
||||
|
||||
import { copyBaseConfigurationFiles, makeLabelForSimpleDockerfile, makeLabelForStandaloneApplication, saveBuildLog, setDefaultConfiguration } from '../lib/buildPacks/common';
|
||||
import { createDirectories, decrypt, defaultComposeConfiguration, executeDockerCmd, getDomain, prisma, decryptApplication, isDev } from '../lib/common';
|
||||
import { copyBaseConfigurationFiles, makeLabelForSimpleDockerfile, makeLabelForStandaloneApplication, saveBuildLog, saveDockerRegistryCredentials, setDefaultConfiguration } from '../lib/buildPacks/common';
|
||||
import { createDirectories, decrypt, defaultComposeConfiguration, executeDockerCmd, getDomain, prisma, decryptApplication, isDev, pushToRegistry } from '../lib/common';
|
||||
import * as importers from '../lib/importers';
|
||||
import * as buildpacks from '../lib/buildPacks';
|
||||
|
||||
@ -37,7 +37,7 @@ import * as buildpacks from '../lib/buildPacks';
|
||||
|
||||
for (const queueBuild of queuedBuilds) {
|
||||
actions.push(async () => {
|
||||
let application = await prisma.application.findUnique({ where: { id: queueBuild.applicationId }, include: { destinationDocker: true, gitSource: { include: { githubApp: true, gitlabApp: true } }, persistentStorage: true, secrets: true, settings: true, teams: true } })
|
||||
let application = await prisma.application.findUnique({ where: { id: queueBuild.applicationId }, include: { dockerRegistry: true, destinationDocker: true, gitSource: { include: { githubApp: true, gitlabApp: true } }, persistentStorage: true, secrets: true, settings: true, teams: true } })
|
||||
|
||||
let { id: buildId, type, gitSourceId, sourceBranch = null, pullmergeRequestId = null, previewApplicationId = null, forceRebuild, sourceRepository = null } = queueBuild
|
||||
application = decryptApplication(application)
|
||||
@ -51,7 +51,8 @@ import * as buildpacks from '../lib/buildPacks';
|
||||
port,
|
||||
persistentStorage,
|
||||
exposePort,
|
||||
simpleDockerfile
|
||||
simpleDockerfile,
|
||||
dockerRegistry
|
||||
} = application
|
||||
const { workdir } = await createDirectories({ repository: applicationId, buildId });
|
||||
try {
|
||||
@ -109,6 +110,11 @@ import * as buildpacks from '../lib/buildPacks';
|
||||
}
|
||||
|
||||
await fs.writeFile(`${workdir}/Dockerfile`, simpleDockerfile);
|
||||
if (dockerRegistry) {
|
||||
const { url, username, password } = dockerRegistry
|
||||
await saveDockerRegistryCredentials({ url, username, password, workdir })
|
||||
}
|
||||
|
||||
const labels = makeLabelForSimpleDockerfile({
|
||||
applicationId,
|
||||
type,
|
||||
@ -164,7 +170,7 @@ import * as buildpacks from '../lib/buildPacks';
|
||||
}
|
||||
throw new Error(error);
|
||||
}
|
||||
await prisma.build.update({ where: { id: buildId }, data: { status: 'success' } });
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
const foundBuild = await prisma.build.findUnique({ where: { id: buildId } })
|
||||
@ -179,10 +185,27 @@ import * as buildpacks from '../lib/buildPacks';
|
||||
if (error !== 1) {
|
||||
await saveBuildLog({ line: error, buildId, applicationId: application.id });
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (application.dockerRegistryImageName) {
|
||||
const customTag = application.dockerRegistryImageName.split(':')[1] || buildId;
|
||||
const imageName = application.dockerRegistryImageName.split(':')[0];
|
||||
await saveBuildLog({ line: `Pushing ${imageName}:${customTag} to Docker Registry... It could take a while...`, buildId, applicationId: application.id });
|
||||
await pushToRegistry(application, workdir, buildId, imageName, customTag)
|
||||
await saveBuildLog({ line: "Success 🎉", buildId, applicationId: application.id });
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.stdout) {
|
||||
await saveBuildLog({ line: error.stdout, buildId, applicationId });
|
||||
}
|
||||
if (error.stderr) {
|
||||
await saveBuildLog({ line: error.stderr, buildId, applicationId });
|
||||
}
|
||||
} finally {
|
||||
if (!isDev) {
|
||||
await fs.rm(workdir, { recursive: true, force: true });
|
||||
}
|
||||
await prisma.build.update({ where: { id: buildId }, data: { status: 'success' } });
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -211,6 +234,7 @@ import * as buildpacks from '../lib/buildPacks';
|
||||
baseBuildImage,
|
||||
deploymentType,
|
||||
gitCommitHash,
|
||||
dockerRegistry
|
||||
} = application
|
||||
|
||||
let {
|
||||
@ -231,7 +255,7 @@ import * as buildpacks from '../lib/buildPacks';
|
||||
|
||||
let imageId = applicationId;
|
||||
let domain = getDomain(fqdn);
|
||||
|
||||
let tag = null
|
||||
if (pullmergeRequestId) {
|
||||
const previewApplications = await prisma.previewApplication.findMany({ where: { applicationId: originalApplicationId, pullmergeRequestId } })
|
||||
if (previewApplications.length > 0) {
|
||||
@ -330,7 +354,7 @@ import * as buildpacks from '../lib/buildPacks';
|
||||
if (!commit) {
|
||||
throw new Error('No commit found?');
|
||||
}
|
||||
let tag = commit.slice(0, 7);
|
||||
tag = commit.slice(0, 7);
|
||||
if (pullmergeRequestId) {
|
||||
tag = `${commit.slice(0, 7)}-${pullmergeRequestId}`;
|
||||
}
|
||||
@ -500,6 +524,9 @@ import * as buildpacks from '../lib/buildPacks';
|
||||
}
|
||||
await fs.writeFile(`${workdir}/.env`, envs.join('\n'));
|
||||
|
||||
const { url, username, password } = dockerRegistry
|
||||
await saveDockerRegistryCredentials({ url, username, password, workdir })
|
||||
|
||||
let envFound = false;
|
||||
try {
|
||||
envFound = !!(await fs.stat(`${workdir}/.env`));
|
||||
@ -553,7 +580,7 @@ import * as buildpacks from '../lib/buildPacks';
|
||||
}
|
||||
throw new Error(error);
|
||||
}
|
||||
await prisma.build.update({ where: { id: buildId }, data: { status: 'success' } });
|
||||
|
||||
if (!pullmergeRequestId) await prisma.application.update({
|
||||
where: { id: applicationId },
|
||||
data: { configHash: currentHash }
|
||||
@ -573,10 +600,28 @@ import * as buildpacks from '../lib/buildPacks';
|
||||
if (error !== 1) {
|
||||
await saveBuildLog({ line: error, buildId, applicationId: application.id });
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (application.dockerRegistryImageName) {
|
||||
const customTag = application.dockerRegistryImageName.split(':')[1] || tag;
|
||||
const imageName = application.dockerRegistryImageName.split(':')[0];
|
||||
await saveBuildLog({ line: `Pushing ${imageName}:${customTag} to Docker Registry... It could take a while...`, buildId, applicationId: application.id });
|
||||
await pushToRegistry(application, workdir, tag, imageName, customTag)
|
||||
await saveBuildLog({ line: "Success 🎉", buildId, applicationId: application.id });
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.stdout) {
|
||||
await saveBuildLog({ line: error.stdout, buildId, applicationId });
|
||||
}
|
||||
if (error.stderr) {
|
||||
await saveBuildLog({ line: error.stderr, buildId, applicationId });
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (!isDev) {
|
||||
await fs.rm(workdir, { recursive: true, force: true });
|
||||
}
|
||||
await prisma.build.update({ where: { id: buildId }, data: { status: 'success' } });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -607,13 +607,13 @@ export function checkPnpm(installCommand = null, buildCommand = null, startComma
|
||||
}
|
||||
|
||||
export async function saveDockerRegistryCredentials({ url, username, password, workdir }) {
|
||||
let decryptedPassword = decrypt(password);
|
||||
const location = `${workdir}/.docker`;
|
||||
|
||||
if (!username || !password) {
|
||||
return null
|
||||
}
|
||||
|
||||
let decryptedPassword = decrypt(password);
|
||||
const location = `${workdir}/.docker`;
|
||||
|
||||
try {
|
||||
await fs.mkdir(`${workdir}/.docker`);
|
||||
} catch (error) {
|
||||
|
@ -15,7 +15,7 @@ import sshConfig from 'ssh-config';
|
||||
import jsonwebtoken from 'jsonwebtoken';
|
||||
import { checkContainer, removeContainer } from './docker';
|
||||
import { day } from './dayjs';
|
||||
import { saveBuildLog } from './buildPacks/common';
|
||||
import { saveBuildLog, saveDockerRegistryCredentials } from './buildPacks/common';
|
||||
import { scheduler } from './scheduler';
|
||||
|
||||
export const version = '3.12.0';
|
||||
@ -1713,3 +1713,17 @@ export function decryptApplication(application: any) {
|
||||
return application;
|
||||
}
|
||||
}
|
||||
|
||||
export async function pushToRegistry(application: any, workdir: string, tag: string, imageName: string, customTag: string) {
|
||||
const location = `${workdir}/.docker`
|
||||
const tagCommand = `docker tag ${application.id}:${tag} ${imageName}:${customTag}`
|
||||
const pushCommand = `docker --config ${location} push ${imageName}:${customTag}`
|
||||
await executeDockerCmd({
|
||||
dockerId: application.destinationDockerId,
|
||||
command: tagCommand
|
||||
})
|
||||
await executeDockerCmd({
|
||||
dockerId: application.destinationDockerId,
|
||||
command: pushCommand
|
||||
})
|
||||
}
|
@ -335,7 +335,8 @@ export async function saveApplication(request: FastifyRequest<SaveApplication>,
|
||||
dockerComposeFile,
|
||||
dockerComposeFileLocation,
|
||||
dockerComposeConfiguration,
|
||||
simpleDockerfile
|
||||
simpleDockerfile,
|
||||
dockerRegistryImageName
|
||||
} = request.body
|
||||
if (port) port = Number(port);
|
||||
if (exposePort) {
|
||||
@ -375,6 +376,7 @@ export async function saveApplication(request: FastifyRequest<SaveApplication>,
|
||||
dockerComposeFileLocation,
|
||||
dockerComposeConfiguration,
|
||||
simpleDockerfile,
|
||||
dockerRegistryImageName,
|
||||
...defaultConfiguration,
|
||||
connectedDatabase: { update: { hostedDatabaseDBName: baseDatabaseBranch } }
|
||||
}
|
||||
@ -398,6 +400,7 @@ export async function saveApplication(request: FastifyRequest<SaveApplication>,
|
||||
dockerComposeFileLocation,
|
||||
dockerComposeConfiguration,
|
||||
simpleDockerfile,
|
||||
dockerRegistryImageName,
|
||||
...defaultConfiguration
|
||||
}
|
||||
});
|
||||
|
@ -26,7 +26,8 @@ export interface SaveApplication extends OnlyId {
|
||||
dockerComposeFile: string,
|
||||
dockerComposeFileLocation: string,
|
||||
dockerComposeConfiguration: string,
|
||||
simpleDockerfile: string
|
||||
simpleDockerfile: string,
|
||||
dockerRegistryImageName: string
|
||||
}
|
||||
}
|
||||
export interface SaveApplicationSettings extends OnlyId {
|
||||
|
@ -218,7 +218,7 @@
|
||||
<li class="menu-title">
|
||||
<span>Advanced</span>
|
||||
</li>
|
||||
{#if !application.simpleDockerfile}
|
||||
{#if application.gitSourceId}
|
||||
<li
|
||||
class="rounded"
|
||||
class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/revert`}
|
||||
@ -267,7 +267,7 @@
|
||||
</svg>Monitoring</a
|
||||
>
|
||||
</li>
|
||||
{#if !application.settings.isBot && !application.simpleDockerfile}
|
||||
{#if !application.settings.isBot && application.gitSourceId}
|
||||
<li
|
||||
class="rounded"
|
||||
class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/previews`}
|
||||
|
@ -568,8 +568,6 @@
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
|
||||
{/if}
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="registry">Docker Registry</label>
|
||||
@ -592,6 +590,24 @@
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
{#if application.dockerRegistry?.id && application.gitSourceId}
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="registry"
|
||||
>Push Image to Registry <Explainer
|
||||
explanation="Push the build image to the specific Docker Registry.<br><br>This is useful if you want to use the image in other places. If you don't fill this the image will be only available on the server.<br><br>Tag is optional. If you don't fill it, the tag will be the same as the git commit hash."
|
||||
/></label
|
||||
>
|
||||
<input
|
||||
name="dockerRegistryImageName"
|
||||
id="dockerRegistryImageName"
|
||||
readonly={isDisabled}
|
||||
disabled={isDisabled}
|
||||
class="w-full"
|
||||
placeholder="e.g. coollabsio/myimage (tag will be commit sha) or coollabsio/myimage:tag"
|
||||
bind:value={application.dockerRegistryImageName}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{#if !isSimpleDockerfile}
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="buildPack">{$t('application.build_pack')} </label>
|
||||
@ -728,13 +744,13 @@
|
||||
<div class="title font-bold pb-3 pt-10 border-b border-coolgray-500 mb-6">
|
||||
Configuration
|
||||
</div>
|
||||
|
||||
|
||||
<div class="grid grid-flow-row gap-2 px-4 pr-5">
|
||||
<div class="grid grid-cols-2 items-center pt-4">
|
||||
<label for="simpleDockerfile">Dockerfile</label>
|
||||
<div class="flex gap-2">
|
||||
<textarea
|
||||
rows=10
|
||||
rows="10"
|
||||
id="simpleDockerfile"
|
||||
name="simpleDockerfile"
|
||||
class="w-full"
|
||||
|
Loading…
Reference in New Issue
Block a user