Merge branch 'main' into next

This commit is contained in:
Andras Bacsai 2022-12-13 09:35:33 +01:00
commit 1639d1725a
6 changed files with 300 additions and 206 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
- templateVersion: 1.0.0
defaultVersion: '0.8.0'
defaultVersion: "0.8.0"
documentation: https://pocketbase.io/docs/
type: pocketbase
name: Pocketbase
@ -12,7 +12,7 @@
ports:
- "8080"
- templateVersion: 1.0.0
defaultVersion: 1.5.0-rc.0
defaultVersion: v1.5.1
documentation: https://plausible.io/doc/
type: plausibleanalytics-arm
name: Plausible Analytics (ARM)
@ -313,7 +313,7 @@
defaultValue: keycloak
description: ""
- templateVersion: 1.0.0
defaultVersion: v3.6
defaultVersion: v3.7
documentation: https://github.com/freyacodes/Lavalink
description: Standalone audio sending node based on Lavaplayer.
type: lavalink
@ -375,7 +375,7 @@
defaultValue: $$generate_password
required: true
- templateVersion: 1.0.0
defaultVersion: v1.8.6
defaultVersion: v1.8.9
documentation: https://docs.appsmith.com/getting-started/setup/instance-configuration/
type: appsmith
name: Appsmith
@ -408,7 +408,7 @@
defaultValue: "true"
description: ""
- templateVersion: 1.0.0
defaultVersion: 0.56.2
defaultVersion: 0.57.4
documentation: https://hub.docker.com/r/zadam/trilium
description: "A hierarchical note taking application with focus on building large personal knowledge bases."
labels:
@ -428,7 +428,7 @@
- "8080"
variables: []
- templateVersion: 1.0.0
defaultVersion: 1.9.2
defaultVersion: 1.18.5
documentation: https://hub.docker.com/r/louislam/uptime-kuma
description: A free & fancy self-hosted monitoring tool.
labels:
@ -478,7 +478,7 @@
- "80"
variables: []
- templateVersion: 1.0.0
defaultVersion: 9.2.3
defaultVersion: 9.3.1
documentation: https://hub.docker.com/r/grafana/grafana
type: grafana
name: Grafana
@ -499,7 +499,7 @@
- "3000"
variables: []
- templateVersion: 1.0.0
defaultVersion: 1.0.3
defaultVersion: 1.1.2
documentation: https://appwrite.io/docs
type: appwrite
name: Appwrite
@ -1669,7 +1669,7 @@
defaultValue: weblate
description: ""
- templateVersion: 1.0.0
defaultVersion: 2022.10.14-1a5b0965
defaultVersion: 2022.12.12-966e9c3c
documentation: https://docs.searxng.org/
type: searxng
name: SearXNG
@ -1742,7 +1742,7 @@
defaultValue: $$generate_password
description: ""
- templateVersion: 1.0.0
defaultVersion: v2.0.6
defaultVersion: v3.0.0
documentation: https://glitchtip.com/documentation
type: glitchtip
name: GlitchTip
@ -1964,7 +1964,7 @@
defaultValue: glitchtip
description: ""
- templateVersion: 1.0.0
defaultVersion: v2.13.0
defaultVersion: v2.16.0
documentation: https://hasura.io/docs/latest/index/
type: hasura
name: Hasura
@ -2031,7 +2031,7 @@
defaultValue: hasura
description: ""
- templateVersion: 1.0.0
defaultVersion: postgresql-v1.38.0
defaultVersion: postgresql-v1.39.5
documentation: https://umami.is/docs/getting-started
type: umami-postgresql
name: Umami
@ -2238,7 +2238,7 @@
showOnConfiguration: true
- templateVersion: 1.0.0
ignore: true
defaultVersion: postgresql-v1.38.0
defaultVersion: postgresql-v1.39.5
documentation: https://umami.is/docs/getting-started
type: umami
name: Umami
@ -2444,7 +2444,7 @@
description: ""
showOnConfiguration: true
- templateVersion: 1.0.0
defaultVersion: v0.29.1
defaultVersion: v0.30.1
documentation: https://docs.meilisearch.com/learn/getting_started/quick_start.html
type: meilisearch
name: MeiliSearch
@ -2592,7 +2592,7 @@
defaultValue: $$generate_password
description: ""
- templateVersion: 1.0.0
defaultVersion: "5.22"
defaultVersion: "5.25.3"
documentation: https://docs.ghost.org
type: ghost-only
name: Ghost
@ -2656,7 +2656,7 @@
placeholder: "ghost_db"
required: true
- templateVersion: 1.0.0
defaultVersion: "5.22"
defaultVersion: "5.25.3"
documentation: https://docs.ghost.org
type: ghost-mysql
name: Ghost
@ -2897,7 +2897,7 @@
define('WP_DEBUG_DISPLAY', false);
@ini_set('display_errors', 0);
- templateVersion: 1.0.0
defaultVersion: 4.7.1
defaultVersion: 4.9.0
documentation: https://coder.com/docs/coder-oss/latest
type: vscodeserver
name: VSCode Server
@ -2928,7 +2928,7 @@
description: ""
showOnConfiguration: true
- templateVersion: 1.0.0
defaultVersion: RELEASE.2022-10-15T19-57-03Z
defaultVersion: RELEASE.2022-12-12T19-27-27Z
documentation: https://min.io/docs/minio
type: minio
name: MinIO
@ -3106,7 +3106,7 @@
defaultValue: $$generate_username
description: ""
- templateVersion: 1.0.0
defaultVersion: 0.198.1
defaultVersion: 0.207.0
documentation: https://docs.n8n.io
type: n8n
name: n8n.io
@ -3283,7 +3283,7 @@
defaultValue: plausible.js
description: This is the default script name.
- templateVersion: 1.0.0
defaultVersion: 0.98.1
defaultVersion: 0.99.1
documentation: https://docs.nocodb.com
type: nocodb
name: NocoDB

View File

@ -19,9 +19,10 @@ import { saveBuildLog, saveDockerRegistryCredentials } from './buildPacks/common
import { scheduler } from './scheduler';
import type { ExecaChildProcess } from 'execa';
export const version = '3.12.0';
export const version = '3.12.1';
export const isDev = process.env.NODE_ENV === 'development';
export const sentryDSN = 'https://409f09bcb7af47928d3e0f46b78987f3@o1082494.ingest.sentry.io/4504236622217216';
export const sentryDSN =
'https://409f09bcb7af47928d3e0f46b78987f3@o1082494.ingest.sentry.io/4504236622217216';
const algorithm = 'aes-256-ctr';
const customConfig: Config = {
dictionaries: [adjectives, colors, animals],
@ -92,7 +93,7 @@ export const asyncExecShellStream = async ({
line: `${line.replace('\n', '')}`,
buildId,
applicationId
}
};
logs.push(log);
if (debug) {
await saveBuildLog(log);
@ -109,7 +110,7 @@ export const asyncExecShellStream = async ({
line: `${line.replace('\n', '')}`,
buildId,
applicationId
}
};
logs.push(log);
if (debug) {
await saveBuildLog(log);
@ -393,7 +394,6 @@ export function generateTimestamp(): string {
return `${day().format('HH:mm:ss.SSS')}`;
}
export const supportedDatabaseTypesAndVersions = [
{
name: 'mongodb',
@ -509,20 +509,19 @@ export async function createRemoteEngineConfiguration(id: string) {
} = await prisma.destinationDocker.findFirst({ where: { id }, include: { sshKey: true } });
await fs.writeFile(sshKeyFile, decrypt(privateKey) + '\n', { encoding: 'utf8', mode: 400 });
const config = sshConfig.parse('');
const Host = `${remoteIpAddress}-remote`
const Host = `${remoteIpAddress}-remote`;
try {
await executeCommand({ command: `ssh-keygen -R ${Host}` });
await executeCommand({ command: `ssh-keygen -R ${remoteIpAddress}` });
await executeCommand({ command: `ssh-keygen -R localhost:${localPort}` });
} catch (error) { }
} catch (error) {}
const found = config.find({ Host });
const foundIp = config.find({ Host: remoteIpAddress });
if (found) config.remove({ Host })
if (foundIp) config.remove({ Host: remoteIpAddress })
if (found) config.remove({ Host });
if (foundIp) config.remove({ Host: remoteIpAddress });
config.append({
Host,
@ -543,15 +542,35 @@ export async function createRemoteEngineConfiguration(id: string) {
}
return await fs.writeFile(`${homedir}/.ssh/config`, sshConfig.stringify(config));
}
export async function executeCommand({ command, dockerId = null, sshCommand = false, shell = false, stream = false, buildId, applicationId, debug }: { command: string, sshCommand?: boolean, shell?: boolean, stream?: boolean, dockerId?: string, buildId?: string, applicationId?: string, debug?: boolean }): Promise<ExecaChildProcess<string>> {
const { execa, execaCommand } = await import('execa')
const { parse } = await import('shell-quote')
export async function executeCommand({
command,
dockerId = null,
sshCommand = false,
shell = false,
stream = false,
buildId,
applicationId,
debug
}: {
command: string;
sshCommand?: boolean;
shell?: boolean;
stream?: boolean;
dockerId?: string;
buildId?: string;
applicationId?: string;
debug?: boolean;
}): Promise<ExecaChildProcess<string>> {
const { execa, execaCommand } = await import('execa');
const { parse } = await import('shell-quote');
const parsedCommand = parse(command);
const dockerCommand = parsedCommand[0];
const dockerArgs = parsedCommand.slice(1);
if (dockerId) {
let { remoteEngine, remoteIpAddress, engine } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } })
let { remoteEngine, remoteIpAddress, engine } = await prisma.destinationDocker.findUnique({
where: { id: dockerId }
});
if (remoteEngine) {
await createRemoteEngineConfiguration(dockerId);
engine = `ssh://${remoteIpAddress}-remote`;
@ -591,7 +610,7 @@ export async function executeCommand({ command, dockerId = null, sshCommand = fa
line: `${line.replace('\n', '')}`,
buildId,
applicationId
}
};
logs.push(log);
if (debug) {
await saveBuildLog(log);
@ -608,7 +627,7 @@ export async function executeCommand({ command, dockerId = null, sshCommand = fa
line: `${line.replace('\n', '')}`,
buildId,
applicationId
}
};
logs.push(log);
if (debug) {
await saveBuildLog(log);
@ -628,7 +647,7 @@ export async function executeCommand({ command, dockerId = null, sshCommand = fa
reject(code);
}
});
})
});
} else {
if (shell) {
return await execaCommand(command, {
@ -640,7 +659,6 @@ export async function executeCommand({ command, dockerId = null, sshCommand = fa
});
}
}
} else {
if (shell) {
return execaCommand(command, { shell: true });
@ -650,8 +668,13 @@ export async function executeCommand({ command, dockerId = null, sshCommand = fa
}
export async function startTraefikProxy(id: string): Promise<void> {
const { engine, network, remoteEngine, remoteIpAddress } = await prisma.destinationDocker.findUnique({ where: { id } })
const { found } = await checkContainer({ dockerId: id, container: 'coolify-proxy', remove: true });
const { engine, network, remoteEngine, remoteIpAddress } =
await prisma.destinationDocker.findUnique({ where: { id } });
const { found } = await checkContainer({
dockerId: id,
container: 'coolify-proxy',
remove: true
});
const { id: settingsId, ipv4, ipv6 } = await listSettings();
if (!found) {
@ -768,9 +791,12 @@ export async function listSettings(): Promise<any> {
}
export function generateToken() {
return jsonwebtoken.sign({
nbf: Math.floor(Date.now() / 1000) - 30,
}, process.env['COOLIFY_SECRET_KEY'])
return jsonwebtoken.sign(
{
nbf: Math.floor(Date.now() / 1000) - 30
},
process.env['COOLIFY_SECRET_KEY']
);
}
export function generatePassword({
length = 24,
@ -790,109 +816,102 @@ export function generatePassword({
return password;
}
type DatabaseConfiguration = {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
MYSQL_DATABASE: string;
MYSQL_PASSWORD: string;
MYSQL_ROOT_USER: string;
MYSQL_USER: string;
MYSQL_ROOT_PASSWORD: string;
};
}
type DatabaseConfiguration =
| {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
MONGO_INITDB_ROOT_USERNAME?: string;
MONGO_INITDB_ROOT_PASSWORD?: string;
MONGODB_ROOT_USER?: string;
MONGODB_ROOT_PASSWORD?: string;
};
}
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
MYSQL_DATABASE: string;
MYSQL_PASSWORD: string;
MYSQL_ROOT_USER: string;
MYSQL_USER: string;
MYSQL_ROOT_PASSWORD: string;
};
}
| {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
MARIADB_ROOT_USER: string;
MARIADB_ROOT_PASSWORD: string;
MARIADB_USER: string;
MARIADB_PASSWORD: string;
MARIADB_DATABASE: string;
};
}
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
MONGO_INITDB_ROOT_USERNAME?: string;
MONGO_INITDB_ROOT_PASSWORD?: string;
MONGODB_ROOT_USER?: string;
MONGODB_ROOT_PASSWORD?: string;
};
}
| {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
POSTGRES_PASSWORD?: string;
POSTGRES_USER?: string;
POSTGRES_DB?: string;
POSTGRESQL_POSTGRES_PASSWORD?: string;
POSTGRESQL_USERNAME?: string;
POSTGRESQL_PASSWORD?: string;
POSTGRESQL_DATABASE?: string;
};
}
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
MARIADB_ROOT_USER: string;
MARIADB_ROOT_PASSWORD: string;
MARIADB_USER: string;
MARIADB_PASSWORD: string;
MARIADB_DATABASE: string;
};
}
| {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
REDIS_AOF_ENABLED: string;
REDIS_PASSWORD: string;
};
}
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
POSTGRES_PASSWORD?: string;
POSTGRES_USER?: string;
POSTGRES_DB?: string;
POSTGRESQL_POSTGRES_PASSWORD?: string;
POSTGRESQL_USERNAME?: string;
POSTGRESQL_PASSWORD?: string;
POSTGRESQL_DATABASE?: string;
};
}
| {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
COUCHDB_PASSWORD: string;
COUCHDB_USER: string;
};
}
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
REDIS_AOF_ENABLED: string;
REDIS_PASSWORD: string;
};
}
| {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
EDGEDB_SERVER_PASSWORD: string;
EDGEDB_SERVER_USER: string;
EDGEDB_SERVER_DATABASE: string;
EDGEDB_SERVER_TLS_CERT_MODE: string;
};
}
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
COUCHDB_PASSWORD: string;
COUCHDB_USER: string;
};
}
| {
volume: string;
image: string;
command?: string;
ulimits: Record<string, unknown>;
privatePort: number;
environmentVariables: {
EDGEDB_SERVER_PASSWORD: string;
EDGEDB_SERVER_USER: string;
EDGEDB_SERVER_DATABASE: string;
EDGEDB_SERVER_TLS_CERT_MODE: string;
};
};
export function generateDatabaseConfiguration(database: any, arch: string): DatabaseConfiguration {
const {
id,
dbUser,
dbUserPassword,
rootUser,
rootUserPassword,
defaultDatabase,
version,
type,
} = database;
const { id, dbUser, dbUserPassword, rootUser, rootUserPassword, defaultDatabase, version, type } =
database;
const baseImage = getDatabaseImage(type, arch);
if (type === 'mysql') {
const configuration = {
@ -972,7 +991,9 @@ export function generateDatabaseConfiguration(database: any, arch: string): Data
}
return configuration;
} else if (type === 'redis') {
const { settings: { appendOnly } } = database;
const {
settings: { appendOnly }
} = database;
const configuration: DatabaseConfiguration = {
privatePort: 6379,
command: undefined,
@ -986,8 +1007,9 @@ export function generateDatabaseConfiguration(database: any, arch: string): Data
};
if (isARM(arch)) {
configuration.volume = `${id}-${type}-data:/data`;
configuration.command = `/usr/local/bin/redis-server --appendonly ${appendOnly ? 'yes' : 'no'
} --requirepass ${dbUserPassword}`;
configuration.command = `/usr/local/bin/redis-server --appendonly ${
appendOnly ? 'yes' : 'no'
} --requirepass ${dbUserPassword}`;
}
return configuration;
} else if (type === 'couchdb') {
@ -1004,7 +1026,7 @@ export function generateDatabaseConfiguration(database: any, arch: string): Data
if (isARM(arch)) {
configuration.volume = `${id}-${type}-data:/opt/couchdb/data`;
}
return configuration
return configuration;
} else if (type === 'edgedb') {
const configuration: DatabaseConfiguration = {
privatePort: 5656,
@ -1018,7 +1040,7 @@ export function generateDatabaseConfiguration(database: any, arch: string): Data
volume: `${id}-${type}-data:/var/lib/edgedb/data`,
ulimits: {}
};
return configuration
return configuration;
}
}
export function isARM(arch: string) {
@ -1071,12 +1093,12 @@ export type ComposeFileService = {
command?: string;
ports?: string[];
build?:
| {
context: string;
dockerfile: string;
args?: Record<string, unknown>;
}
| string;
| {
context: string;
dockerfile: string;
args?: Record<string, unknown>;
}
| string;
deploy?: {
restart_policy?: {
condition?: string;
@ -1141,13 +1163,13 @@ export const createDirectories = async ({
repository: string;
buildId: string;
}): Promise<{ workdir: string; repodir: string }> => {
if (repository) repository = repository.replaceAll(' ', '')
if (repository) repository = repository.replaceAll(' ', '');
const repodir = `/tmp/build-sources/${repository}/`;
const workdir = `/tmp/build-sources/${repository}/${buildId}`;
let workdirFound = false;
try {
workdirFound = !!(await fs.stat(workdir));
} catch (error) { }
} catch (error) {}
if (workdirFound) {
await executeCommand({ command: `rm -fr ${workdir}` });
}
@ -1254,19 +1276,45 @@ export async function updatePasswordInDb(database, user, newPassword, isRoot) {
}
}
}
export async function checkExposedPort({ id, configuredPort, exposePort, engine, remoteEngine, remoteIpAddress }: { id: string, configuredPort?: number, exposePort: number, engine: string, remoteEngine: boolean, remoteIpAddress?: string }) {
export async function checkExposedPort({
id,
configuredPort,
exposePort,
engine,
remoteEngine,
remoteIpAddress
}: {
id: string;
configuredPort?: number;
exposePort: number;
engine: string;
remoteEngine: boolean;
remoteIpAddress?: string;
}) {
if (exposePort < 1024 || exposePort > 65535) {
throw { status: 500, message: `Exposed Port needs to be between 1024 and 65535.` };
}
if (configuredPort) {
if (configuredPort !== exposePort) {
const availablePort = await getFreeExposedPort(id, exposePort, engine, remoteEngine, remoteIpAddress);
const availablePort = await getFreeExposedPort(
id,
exposePort,
engine,
remoteEngine,
remoteIpAddress
);
if (availablePort.toString() !== exposePort.toString()) {
throw { status: 500, message: `Port ${exposePort} is already in use.` };
}
}
} else {
const availablePort = await getFreeExposedPort(id, exposePort, engine, remoteEngine, remoteIpAddress);
const availablePort = await getFreeExposedPort(
id,
exposePort,
engine,
remoteEngine,
remoteIpAddress
);
if (availablePort.toString() !== exposePort.toString()) {
throw { status: 500, message: `Port ${exposePort} is already in use.` };
}
@ -1277,25 +1325,33 @@ export async function getFreeExposedPort(id, exposePort, engine, remoteEngine, r
if (remoteEngine) {
const applicationUsed = await (
await prisma.application.findMany({
where: { exposePort: { not: null }, id: { not: id }, destinationDocker: { remoteIpAddress } },
where: {
exposePort: { not: null },
id: { not: id },
destinationDocker: { remoteIpAddress }
},
select: { exposePort: true }
})
).map((a) => a.exposePort);
const serviceUsed = await (
await prisma.service.findMany({
where: { exposePort: { not: null }, id: { not: id }, destinationDocker: { remoteIpAddress } },
where: {
exposePort: { not: null },
id: { not: id },
destinationDocker: { remoteIpAddress }
},
select: { exposePort: true }
})
).map((a) => a.exposePort);
const usedPorts = [...applicationUsed, ...serviceUsed];
if (usedPorts.includes(exposePort)) {
return false
return false;
}
const found = await checkPort(exposePort, { host: remoteIpAddress });
if (!found) {
return exposePort
return exposePort;
}
return false
return false;
} else {
const applicationUsed = await (
await prisma.application.findMany({
@ -1311,13 +1367,13 @@ export async function getFreeExposedPort(id, exposePort, engine, remoteEngine, r
).map((a) => a.exposePort);
const usedPorts = [...applicationUsed, ...serviceUsed];
if (usedPorts.includes(exposePort)) {
return false
return false;
}
const found = await checkPort(exposePort, { host: 'localhost' });
if (!found) {
return exposePort
return exposePort;
}
return false
return false;
}
}
export function generateRangeArray(start, end) {
@ -1330,38 +1386,54 @@ export async function getFreePublicPort({ id, remoteEngine, engine, remoteIpAddr
if (remoteEngine) {
const dbUsed = await (
await prisma.database.findMany({
where: { publicPort: { not: null }, id: { not: id }, destinationDocker: { remoteIpAddress } },
where: {
publicPort: { not: null },
id: { not: id },
destinationDocker: { remoteIpAddress }
},
select: { publicPort: true }
})
).map((a) => a.publicPort);
const wpFtpUsed = await (
await prisma.wordpress.findMany({
where: { ftpPublicPort: { not: null }, id: { not: id }, service: { destinationDocker: { remoteIpAddress } } },
where: {
ftpPublicPort: { not: null },
id: { not: id },
service: { destinationDocker: { remoteIpAddress } }
},
select: { ftpPublicPort: true }
})
).map((a) => a.ftpPublicPort);
const wpUsed = await (
await prisma.wordpress.findMany({
where: { mysqlPublicPort: { not: null }, id: { not: id }, service: { destinationDocker: { remoteIpAddress } } },
where: {
mysqlPublicPort: { not: null },
id: { not: id },
service: { destinationDocker: { remoteIpAddress } }
},
select: { mysqlPublicPort: true }
})
).map((a) => a.mysqlPublicPort);
const minioUsed = await (
await prisma.minio.findMany({
where: { publicPort: { not: null }, id: { not: id }, service: { destinationDocker: { remoteIpAddress } } },
where: {
publicPort: { not: null },
id: { not: id },
service: { destinationDocker: { remoteIpAddress } }
},
select: { publicPort: true }
})
).map((a) => a.publicPort);
const usedPorts = [...dbUsed, ...wpFtpUsed, ...wpUsed, ...minioUsed];
const range = generateRangeArray(minPort, maxPort)
const availablePorts = range.filter(port => !usedPorts.includes(port))
const range = generateRangeArray(minPort, maxPort);
const availablePorts = range.filter((port) => !usedPorts.includes(port));
for (const port of availablePorts) {
const found = await isReachable(port, { host: remoteIpAddress })
const found = await isReachable(port, { host: remoteIpAddress });
if (!found) {
return port
return port;
}
}
return false
return false;
} else {
const dbUsed = await (
await prisma.database.findMany({
@ -1371,32 +1443,44 @@ export async function getFreePublicPort({ id, remoteEngine, engine, remoteIpAddr
).map((a) => a.publicPort);
const wpFtpUsed = await (
await prisma.wordpress.findMany({
where: { ftpPublicPort: { not: null }, id: { not: id }, service: { destinationDocker: { engine } } },
where: {
ftpPublicPort: { not: null },
id: { not: id },
service: { destinationDocker: { engine } }
},
select: { ftpPublicPort: true }
})
).map((a) => a.ftpPublicPort);
const wpUsed = await (
await prisma.wordpress.findMany({
where: { mysqlPublicPort: { not: null }, id: { not: id }, service: { destinationDocker: { engine } } },
where: {
mysqlPublicPort: { not: null },
id: { not: id },
service: { destinationDocker: { engine } }
},
select: { mysqlPublicPort: true }
})
).map((a) => a.mysqlPublicPort);
const minioUsed = await (
await prisma.minio.findMany({
where: { publicPort: { not: null }, id: { not: id }, service: { destinationDocker: { engine } } },
where: {
publicPort: { not: null },
id: { not: id },
service: { destinationDocker: { engine } }
},
select: { publicPort: true }
})
).map((a) => a.publicPort);
const usedPorts = [...dbUsed, ...wpFtpUsed, ...wpUsed, ...minioUsed];
const range = generateRangeArray(minPort, maxPort)
const availablePorts = range.filter(port => !usedPorts.includes(port))
const range = generateRangeArray(minPort, maxPort);
const availablePorts = range.filter((port) => !usedPorts.includes(port));
for (const port of availablePorts) {
const found = await isReachable(port, { host: 'localhost' })
const found = await isReachable(port, { host: 'localhost' });
if (!found) {
return port
return port;
}
}
return false
return false;
}
}
@ -1502,11 +1586,11 @@ export async function getServiceFromDB({
serviceSecret: true,
serviceSetting: true,
wordpress: true,
plausibleAnalytics: true,
plausibleAnalytics: true
}
});
if (!body) {
return null
return null;
}
// body.type = fixType(body.type);
@ -1523,7 +1607,6 @@ export async function getServiceFromDB({
return { ...body, settings };
}
export function fixType(type) {
return type?.replaceAll(' ', '').toLowerCase() || null;
}
@ -1610,7 +1693,7 @@ export async function stopBuild(buildId, applicationId) {
}
}
count++;
} catch (error) { }
} catch (error) {}
}, 100);
});
}
@ -1640,16 +1723,22 @@ export async function cleanupDockerStorage(dockerId, lowDiskSpace, force) {
images = images.trim();
if (images) {
await executeCommand({ dockerId, command: `docker rmi -f ${images}" -q | xargs -r`, shell: true });
await executeCommand({
dockerId,
command: `docker rmi -f ${images}" -q | xargs -r`,
shell: true
});
}
} catch (error) { }
} catch (error) {}
if (lowDiskSpace || force) {
// Cleanup images that are not used
try {
await executeCommand({ dockerId, command: `docker image prune -f` });
} catch (error) { }
} catch (error) {}
const { numberOfDockerImagesKeptLocally } = await prisma.setting.findUnique({ where: { id: '0' } })
const { numberOfDockerImagesKeptLocally } = await prisma.setting.findUnique({
where: { id: '0' }
});
const { stdout: images } = await executeCommand({
dockerId,
command: `docker images|grep -v "<none>"|grep -v REPOSITORY|awk '{print $1, $2}'`,
@ -1657,18 +1746,17 @@ export async function cleanupDockerStorage(dockerId, lowDiskSpace, force) {
});
const imagesArray = images.trim().replaceAll(' ', ':').split('\n');
const imagesSet = new Set(imagesArray.map((image) => image.split(':')[0]));
let deleteImage = []
let deleteImage = [];
for (const image of imagesSet) {
let keepImage = []
let keepImage = [];
for (const image2 of imagesArray) {
if (image2.startsWith(image)) {
if (keepImage.length >= numberOfDockerImagesKeptLocally) {
deleteImage.push(image2)
deleteImage.push(image2);
} else {
keepImage.push(image2)
keepImage.push(image2);
}
}
}
}
for (const image of deleteImage) {
@ -1681,12 +1769,12 @@ export async function cleanupDockerStorage(dockerId, lowDiskSpace, force) {
dockerId,
command: `docker container prune -f --filter "label=coolify.managed=true"`
});
} catch (error) { }
} catch (error) {}
// Cleanup build caches
try {
await executeCommand({ dockerId, command: `docker builder prune -a -f` });
} catch (error) { }
} catch (error) {}
}
}
@ -1768,16 +1856,22 @@ export function decryptApplication(application: any) {
}
}
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}`
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 executeCommand({
dockerId: application.destinationDockerId,
command: tagCommand
})
});
await executeCommand({
dockerId: application.destinationDockerId,
command: pushCommand
})
}
});
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
{
"name": "coolify",
"description": "An open-source & self-hostable Heroku / Netlify alternative.",
"version": "3.12.0",
"version": "3.12.1",
"license": "Apache-2.0",
"repository": "github:coollabsio/coolify",
"scripts": {