fix a lot

This commit is contained in:
Andras Bacsai
2022-07-25 12:42:10 +00:00
parent 101694c998
commit 576aa97694
8 changed files with 38 additions and 85 deletions

View File

@@ -1,6 +1,5 @@
import { parentPort } from 'node:worker_threads'; import { parentPort } from 'node:worker_threads';
import { asyncExecShell, cleanupDockerStorage, executeDockerCmd, isDev, prisma, version } from '../lib/common'; import { asyncExecShell, cleanupDockerStorage, executeDockerCmd, isDev, prisma, version } from '../lib/common';
import { getEngine } from '../lib/docker';
(async () => { (async () => {
if (parentPort) { if (parentPort) {

View File

@@ -5,7 +5,6 @@ import yaml from 'js-yaml';
import { copyBaseConfigurationFiles, makeLabelForStandaloneApplication, saveBuildLog, setDefaultConfiguration } from '../lib/buildPacks/common'; import { copyBaseConfigurationFiles, makeLabelForStandaloneApplication, saveBuildLog, setDefaultConfiguration } from '../lib/buildPacks/common';
import { createDirectories, decrypt, executeDockerCmd, getDomain, prisma } from '../lib/common'; import { createDirectories, decrypt, executeDockerCmd, getDomain, prisma } from '../lib/common';
import Dockerode from 'dockerode';
import * as importers from '../lib/importers'; import * as importers from '../lib/importers';
import * as buildpacks from '../lib/buildPacks'; import * as buildpacks from '../lib/buildPacks';

View File

@@ -13,7 +13,7 @@ import cuid from 'cuid';
import os from 'os'; import os from 'os';
import sshConfig from 'ssh-config' import sshConfig from 'ssh-config'
import { checkContainer, getEngine, removeContainer } from './docker'; import { checkContainer, removeContainer } from './docker';
import { day } from './dayjs'; import { day } from './dayjs';
import * as serviceFields from './serviceFields' import * as serviceFields from './serviceFields'
@@ -326,7 +326,7 @@ export async function isDomainConfigured({
dockerId: string; dockerId: string;
}): Promise<boolean> { }): Promise<boolean> {
console.log({checkOwn, dockerId}) console.log({ checkOwn, dockerId })
const domain = getDomain(fqdn); const domain = getDomain(fqdn);
const nakedDomain = domain.replace('www.', ''); const nakedDomain = domain.replace('www.', '');
const foundApp = await prisma.application.findFirst({ const foundApp = await prisma.application.findFirst({
@@ -387,7 +387,7 @@ export async function getContainerUsage(dockerId: string, container: string): Pr
export async function checkDomainsIsValidInDNS({ hostname, fqdn, dualCerts }): Promise<any> { export async function checkDomainsIsValidInDNS({ hostname, fqdn, dualCerts }): Promise<any> {
const { isIP } = await import('is-ip'); const { isIP } = await import('is-ip');
const domain = getDomain(fqdn); const domain = getDomain(fqdn);
console.log({hostname, fqdn, dualCerts }) console.log({ hostname, fqdn, dualCerts })
const domainDualCert = domain.includes('www.') ? domain.replace('www.', '') : `www.${domain}`; const domainDualCert = domain.includes('www.') ? domain.replace('www.', '') : `www.${domain}`;
dns.setServers(['1.1.1.1', '8.8.8.8']); dns.setServers(['1.1.1.1', '8.8.8.8']);
let resolves = []; let resolves = [];
@@ -506,25 +506,24 @@ export async function createRemoteEngineConfiguration(id: string) {
} }
export async function executeDockerCmd({ dockerId, command }: { dockerId: string, command: string }) { export async function executeDockerCmd({ dockerId, command }: { dockerId: string, command: string }) {
let { remoteEngine, remoteIpAddress, remoteUser, engine } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } }) let { remoteEngine, remoteIpAddress, remoteUser, engine } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } })
if (remoteEngine) engine = `ssh://${remoteUser}@${remoteIpAddress}` if (remoteEngine) {
const host = getEngine(engine) engine = `ssh://${remoteUser}@${remoteIpAddress}`
if (engine.startsWith('ssh://')) {
await createRemoteEngineConfiguration(dockerId) await createRemoteEngineConfiguration(dockerId)
} else {
engine = 'unix:///var/run/docker.sock'
} }
return await asyncExecShell( return await asyncExecShell(
`DOCKER_BUILDKIT=1 DOCKER_HOST="${host}" ${command}` `DOCKER_BUILDKIT=1 DOCKER_HOST="${engine}" ${command}`
); );
} }
export async function startTraefikProxy(id: string): Promise<void> { export async function startTraefikProxy(id: string): Promise<void> {
const { engine, network, remoteEngine, remoteIpAddress } = await prisma.destinationDocker.findUnique({ where: { id } }) const { engine, network, remoteEngine, remoteIpAddress } = await prisma.destinationDocker.findUnique({ where: { id } })
const found = await checkContainer({ dockerId: id, container: 'coolify-proxy', remove: true }); const found = await checkContainer({ dockerId: id, container: 'coolify-proxy', remove: true });
const { id: settingsId, ipv4, ipv6 } = await listSettings(); const { id: settingsId, ipv4, ipv6 } = await listSettings();
if (!found) { if (!found) {
const { stdout: Config } = await executeDockerCmd({ dockerId: id, command: `docker network inspect ${network} --format '{{json .IPAM.Config }}'` }) const { stdout: Config } = await executeDockerCmd({ dockerId: id, command: `docker network inspect ${network} --format '{{json .IPAM.Config }}'` })
const ip = JSON.parse(Config)[0].Gateway; const ip = JSON.parse(Config)[0].Gateway;
const { publicIp } = await import('public-ip')
let traefikUrl = mainTraefikEndpoint let traefikUrl = mainTraefikEndpoint
if (remoteEngine) { if (remoteEngine) {
let ip = null let ip = null
@@ -619,21 +618,6 @@ export async function stopTraefikProxy(
} }
} }
export async function configureNetworkCoolifyProxy(engine: string): Promise<void> {
const host = getEngine(engine);
const destinations = await prisma.destinationDocker.findMany({ where: { engine } });
const { stdout: networks } = await asyncExecShell(
`DOCKER_HOST="${host}" docker ps -a --filter name=coolify-haproxy --format '{{json .Networks}}'`
);
const configuredNetworks = networks.replace(/"/g, '').replace('\n', '').split(',');
for (const destination of destinations) {
if (!configuredNetworks.includes(destination.network)) {
await asyncExecShell(
`DOCKER_HOST="${host}" docker network connect ${destination.network} coolify-haproxy`
);
}
}
}
export async function listSettings(): Promise<any> { export async function listSettings(): Promise<any> {
const settings = await prisma.setting.findFirst({}); const settings = await prisma.setting.findFirst({});
if (settings.proxyPassword) settings.proxyPassword = decrypt(settings.proxyPassword); if (settings.proxyPassword) settings.proxyPassword = decrypt(settings.proxyPassword);
@@ -1526,7 +1510,6 @@ export async function stopBuild(buildId, applicationId) {
await new Promise<void>(async (resolve, reject) => { await new Promise<void>(async (resolve, reject) => {
const { destinationDockerId, status } = await prisma.build.findFirst({ where: { id: buildId } }); const { destinationDockerId, status } = await prisma.build.findFirst({ where: { id: buildId } });
const { engine, id: dockerId } = await prisma.destinationDocker.findFirst({ where: { id: destinationDockerId } }); const { engine, id: dockerId } = await prisma.destinationDocker.findFirst({ where: { id: destinationDockerId } });
const host = getEngine(engine);
let interval = setInterval(async () => { let interval = setInterval(async () => {
try { try {
if (status === 'failed') { if (status === 'failed') {
@@ -1537,10 +1520,7 @@ export async function stopBuild(buildId, applicationId) {
clearInterval(interval); clearInterval(interval);
return reject(new Error('Build canceled')); return reject(new Error('Build canceled'));
} }
const { stdout: buildContainers } = await executeDockerCmd({ dockerId, command: `docker container ls--filter "label=coolify.buildId=${buildId}" --format '{{json .}}'` })
const { stdout: buildContainers } = await asyncExecShell(
`DOCKER_HOST = ${host} docker container ls--filter "label=coolify.buildId=${buildId}" --format '{{json .}}'`
);
if (buildContainers) { if (buildContainers) {
const containersArray = buildContainers.trim().split('\n'); const containersArray = buildContainers.trim().split('\n');
for (const container of containersArray) { for (const container of containersArray) {

View File

@@ -1,17 +1,4 @@
import { executeDockerCmd } from './common'; import { executeDockerCmd } from './common';
import Dockerode from 'dockerode';
export function getEngine(engine: string): string {
return engine === '/var/run/docker.sock' ? 'unix:///var/run/docker.sock' : engine;
}
export function dockerInstance({ destinationDocker }): { engine: Dockerode; network: string } {
return {
engine: new Dockerode({
socketPath: destinationDocker.engine
}),
network: destinationDocker.network
};
}
export async function checkContainer({ dockerId, container, remove = false }: { dockerId: string, container: string, remove?: boolean }): Promise<boolean> { export async function checkContainer({ dockerId, container, remove = false }: { dockerId: string, container: string, remove?: boolean }): Promise<boolean> {
let containerFound = false; let containerFound = false;
try { try {

View File

@@ -6,7 +6,7 @@ import { FastifyReply } from 'fastify';
import { day } from '../../../../lib/dayjs'; import { day } from '../../../../lib/dayjs';
import { setDefaultBaseImage, setDefaultConfiguration } from '../../../../lib/buildPacks/common'; import { setDefaultBaseImage, setDefaultConfiguration } from '../../../../lib/buildPacks/common';
import { checkDomainsIsValidInDNS, checkDoubleBranch, decrypt, encrypt, errorHandler, executeDockerCmd, generateSshKeyPair, getContainerUsage, getDomain, getFreeExposedPort, isDev, isDomainConfigured, prisma, stopBuild, uniqueName } from '../../../../lib/common'; import { checkDomainsIsValidInDNS, checkDoubleBranch, decrypt, encrypt, errorHandler, executeDockerCmd, generateSshKeyPair, getContainerUsage, getDomain, getFreeExposedPort, isDev, isDomainConfigured, prisma, stopBuild, uniqueName } from '../../../../lib/common';
import { checkContainer, dockerInstance, isContainerExited, removeContainer } from '../../../../lib/docker'; import { checkContainer, isContainerExited, removeContainer } from '../../../../lib/docker';
import { scheduler } from '../../../../lib/scheduler'; import { scheduler } from '../../../../lib/scheduler';
import type { FastifyRequest } from 'fastify'; import type { FastifyRequest } from 'fastify';
@@ -731,16 +731,19 @@ export async function getPreviews(request: FastifyRequest<OnlyId>) {
secret.value = decrypt(secret.value); secret.value = decrypt(secret.value);
return secret; return secret;
}); });
const applicationSecrets = secrets.filter((secret) => !secret.isPRMRSecret); const applicationSecrets = secrets.filter((secret) => !secret.isPRMRSecret);
const PRMRSecrets = secrets.filter((secret) => secret.isPRMRSecret); const PRMRSecrets = secrets.filter((secret) => secret.isPRMRSecret);
const destinationDocker = await prisma.destinationDocker.findFirst({ const application = await prisma.application.findUnique({ where: { id }, include: { destinationDocker: true } })
where: { application: { some: { id } }, teams: { some: { id: teamId } } } const { stdout } = await executeDockerCmd({ dockerId: application.destinationDocker.id, command: `docker container ls --filter 'name=${id}-' --format "{{json .}}"` })
}); if (!stdout) {
const docker = dockerInstance({ destinationDocker }); return {
const listContainers = await docker.engine.listContainers({ containers: [],
filters: { network: [destinationDocker.network], name: [id] } applicationSecrets: [],
}); PRMRSecrets: []
const containers = listContainers.filter((container) => { }
}
const containers = JSON.parse(stdout).filter((container) => {
return ( return (
container.Labels['coolify.configuration'] && container.Labels['coolify.configuration'] &&
container.Labels['coolify.type'] === 'standalone-application' container.Labels['coolify.type'] === 'standalone-application'

View File

@@ -5,7 +5,7 @@ import fs from 'fs/promises'
import os from 'os'; import os from 'os';
import { asyncExecShell, decrypt, errorHandler, executeDockerCmd, listSettings, prisma, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common'; import { asyncExecShell, decrypt, errorHandler, executeDockerCmd, listSettings, prisma, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common';
import { checkContainer, dockerInstance, getEngine } from '../../../../lib/docker'; import { checkContainer } from '../../../../lib/docker';
import type { OnlyId } from '../../../../types'; import type { OnlyId } from '../../../../types';
import type { CheckDestination, ListDestinations, NewDestination, Proxy, SaveDestinationSettings } from './types'; import type { CheckDestination, ListDestinations, NewDestination, Proxy, SaveDestinationSettings } from './types';
@@ -79,19 +79,17 @@ export async function newDestination(request: FastifyRequest<NewDestination>, re
let { name, network, engine, isCoolifyProxyUsed, remoteIpAddress, remoteUser, remotePort } = request.body let { name, network, engine, isCoolifyProxyUsed, remoteIpAddress, remoteUser, remotePort } = request.body
console.log({ name, network, engine, isCoolifyProxyUsed, remoteIpAddress, remoteUser, remotePort }) console.log({ name, network, engine, isCoolifyProxyUsed, remoteIpAddress, remoteUser, remotePort })
if (id === 'new') { if (id === 'new') {
console.log(engine)
if (engine) { if (engine) {
const host = getEngine(engine); const { stdout } = await asyncExecShell(`DOCKER_HOST=unix:///var/run/docker.sock docker network ls --filter 'name=^${network}$' --format '{{json .}}'`);
const docker = dockerInstance({ destinationDocker: { engine, network } }); if (stdout === '') {
const found = await docker.engine.listNetworks({ filters: { name: [`^${network}$`] } }); await asyncExecShell(`DOCKER_HOST=unix:///var/run/docker.sock docker network create --attachable ${network}`);
if (found.length === 0) {
await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable ${network}`);
} }
await prisma.destinationDocker.create({ await prisma.destinationDocker.create({
data: { name, teams: { connect: { id: teamId } }, engine, network, isCoolifyProxyUsed } data: { name, teams: { connect: { id: teamId } }, engine, network, isCoolifyProxyUsed }
}); });
const destinations = await prisma.destinationDocker.findMany({ where: { engine } }); const destinations = await prisma.destinationDocker.findMany({ where: { engine } });
const destination = destinations.find((destination) => destination.network === network); const destination = destinations.find((destination) => destination.network === network);
if (destinations.length > 0) { if (destinations.length > 0) {
const proxyConfigured = destinations.find( const proxyConfigured = destinations.find(
(destination) => destination.network !== network && destination.isCoolifyProxyUsed === true (destination) => destination.network !== network && destination.isCoolifyProxyUsed === true
@@ -102,10 +100,7 @@ export async function newDestination(request: FastifyRequest<NewDestination>, re
await prisma.destinationDocker.updateMany({ where: { engine }, data: { isCoolifyProxyUsed } }); await prisma.destinationDocker.updateMany({ where: { engine }, data: { isCoolifyProxyUsed } });
} }
if (isCoolifyProxyUsed) { if (isCoolifyProxyUsed) {
const settings = await prisma.setting.findFirst(); await startTraefikProxy(destination.id);
if (settings?.isTraefikUsed) {
await startTraefikProxy(id);
}
} }
return reply.code(201).send({ id: destination.id }); return reply.code(201).send({ id: destination.id });
} else { } else {
@@ -120,9 +115,8 @@ export async function newDestination(request: FastifyRequest<NewDestination>, re
} }
} catch ({ status, message }) { } catch ({ status, message }) {
console.log({ status, message })
return errorHandler({ status, message }) return errorHandler({ status, message })
} finally {
await fs.rm('./id_rsa')
} }
} }
export async function deleteDestination(request: FastifyRequest<OnlyId>) { export async function deleteDestination(request: FastifyRequest<OnlyId>) {

View File

@@ -4,7 +4,7 @@ import yaml from 'js-yaml';
import bcrypt from 'bcryptjs'; import bcrypt from 'bcryptjs';
import { prisma, uniqueName, asyncExecShell, getServiceImage, configureServiceType, getServiceFromDB, getContainerUsage, removeService, isDomainConfigured, saveUpdateableFields, fixType, decrypt, encrypt, getServiceMainPort, createDirectories, ComposeFile, makeLabelForServices, getFreePublicPort, getDomain, errorHandler, generatePassword, isDev, stopTcpHttpProxy, supportedServiceTypesAndVersions, executeDockerCmd, listSettings, getFreeExposedPort, checkDomainsIsValidInDNS } from '../../../../lib/common'; import { prisma, uniqueName, asyncExecShell, getServiceImage, configureServiceType, getServiceFromDB, getContainerUsage, removeService, isDomainConfigured, saveUpdateableFields, fixType, decrypt, encrypt, getServiceMainPort, createDirectories, ComposeFile, makeLabelForServices, getFreePublicPort, getDomain, errorHandler, generatePassword, isDev, stopTcpHttpProxy, supportedServiceTypesAndVersions, executeDockerCmd, listSettings, getFreeExposedPort, checkDomainsIsValidInDNS } from '../../../../lib/common';
import { day } from '../../../../lib/dayjs'; import { day } from '../../../../lib/dayjs';
import { checkContainer, dockerInstance, isContainerExited, removeContainer } from '../../../../lib/docker'; import { checkContainer, isContainerExited, removeContainer } from '../../../../lib/docker';
import cuid from 'cuid'; import cuid from 'cuid';
import type { OnlyId } from '../../../../types'; import type { OnlyId } from '../../../../types';
@@ -350,7 +350,7 @@ export async function checkServiceDomain(request: FastifyRequest<CheckServiceDom
try { try {
const { id } = request.params const { id } = request.params
const { domain } = request.query const { domain } = request.query
const { fqdn, dualCerts } = await prisma.service.findUnique({ where: { id }}) const { fqdn, dualCerts } = await prisma.service.findUnique({ where: { id } })
return await checkDomainsIsValidInDNS({ hostname: domain, fqdn, dualCerts }); return await checkDomainsIsValidInDNS({ hostname: domain, fqdn, dualCerts });
} catch ({ status, message }) { } catch ({ status, message }) {
return errorHandler({ status, message }) return errorHandler({ status, message })

View File

@@ -1,6 +1,5 @@
import { FastifyRequest } from "fastify"; import { FastifyRequest } from "fastify";
import { asyncExecShell, errorHandler, getDomain, isDev, listServicesWithIncludes, prisma, supportedServiceTypesAndVersions, include } from "../../../lib/common"; import { errorHandler, getDomain, isDev, prisma, supportedServiceTypesAndVersions, include, executeDockerCmd } from "../../../lib/common";
import { getEngine } from "../../../lib/docker";
import { TraefikOtherConfiguration } from "./types"; import { TraefikOtherConfiguration } from "./types";
function configureMiddleware( function configureMiddleware(
@@ -185,7 +184,7 @@ export async function traefikConfiguration(request, reply) {
settings: { previews, dualCerts } settings: { previews, dualCerts }
} = application; } = application;
if (destinationDockerId) { if (destinationDockerId) {
const { engine, network } = destinationDocker; const { network, id: dockerId } = destinationDocker;
const isRunning = true; const isRunning = true;
if (fqdn) { if (fqdn) {
const domain = getDomain(fqdn); const domain = getDomain(fqdn);
@@ -206,10 +205,7 @@ export async function traefikConfiguration(request, reply) {
}); });
} }
if (previews) { if (previews) {
const host = getEngine(engine); const { stdout } = await executeDockerCmd({ dockerId, command: `docker container ls --filter="status=running" --filter="network=${network}" --filter="name=${id}-" --format="{{json .Names}}"` })
const { stdout } = await asyncExecShell(
`DOCKER_HOST=${host} docker container ls --filter="status=running" --filter="network=${network}" --filter="name=${id}-" --format="{{json .Names}}"`
);
const containers = stdout const containers = stdout
.trim() .trim()
.split('\n') .split('\n')
@@ -253,7 +249,6 @@ export async function traefikConfiguration(request, reply) {
plausibleAnalytics plausibleAnalytics
} = service; } = service;
if (destinationDockerId) { if (destinationDockerId) {
const { engine } = destinationDocker;
const found = supportedServiceTypesAndVersions.find((a) => a.name === type); const found = supportedServiceTypesAndVersions.find((a) => a.name === type);
if (found) { if (found) {
const port = found.ports.main; const port = found.ports.main;
@@ -546,7 +541,7 @@ export async function remoteTraefikConfiguration(request: FastifyRequest) {
settings: { previews, dualCerts } settings: { previews, dualCerts }
} = application; } = application;
if (destinationDockerId) { if (destinationDockerId) {
const { engine, network } = destinationDocker; const { id: dockerId, network } = destinationDocker;
const isRunning = true; const isRunning = true;
if (fqdn) { if (fqdn) {
const domain = getDomain(fqdn); const domain = getDomain(fqdn);
@@ -567,10 +562,7 @@ export async function remoteTraefikConfiguration(request: FastifyRequest) {
}); });
} }
if (previews) { if (previews) {
const host = getEngine(engine); const { stdout } = await executeDockerCmd({ dockerId, command: `docker container ls --filter="status=running" --filter="network=${network}" --filter="name=${id}-" --format="{{json .Names}}"` })
const { stdout } = await asyncExecShell(
`DOCKER_HOST=${host} docker container ls --filter="status=running" --filter="network=${network}" --filter="name=${id}-" --format="{{json .Names}}"`
);
const containers = stdout const containers = stdout
.trim() .trim()
.split('\n') .split('\n')
@@ -614,7 +606,6 @@ export async function remoteTraefikConfiguration(request: FastifyRequest) {
plausibleAnalytics plausibleAnalytics
} = service; } = service;
if (destinationDockerId) { if (destinationDockerId) {
const { engine } = destinationDocker;
const found = supportedServiceTypesAndVersions.find((a) => a.name === type); const found = supportedServiceTypesAndVersions.find((a) => a.name === type);
if (found) { if (found) {
const port = found.ports.main; const port = found.ports.main;