From 64e4efeb363381ccabfc584ba6123f133e923056 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 8 Aug 2022 11:54:05 +0000 Subject: [PATCH] feat: persistent storage for all services --- apps/api/src/lib/common.ts | 26 +++ .../src/routes/api/v1/services/handlers.ts | 201 ++++++++---------- 2 files changed, 110 insertions(+), 117 deletions(-) diff --git a/apps/api/src/lib/common.ts b/apps/api/src/lib/common.ts index de6fa47a9..3a06d1d69 100644 --- a/apps/api/src/lib/common.ts +++ b/apps/api/src/lib/common.ts @@ -1622,4 +1622,30 @@ export async function cleanupDockerStorage(dockerId, lowDiskSpace, force) { //console.log(error); } } +} + +export function persistentVolumes(id, persistentStorage, config) { + const persistentVolume = + persistentStorage?.map((storage) => { + return `${id}${storage.path.replace(/\//gi, '-')}:${storage.path}`; + }) || []; + + const volumes = [config.volume, ...persistentVolume] + const composeVolumes = volumes.map((volume) => { + return { + [`${volume.split(':')[0]}`]: { + name: volume.split(':')[0] + } + }; + }); + const volumeMounts = Object.assign( + {}, + { + [config.volume.split(':')[0]]: { + name: config.volume.split(':')[0] + } + }, + ...composeVolumes + ); + return { volumes, volumeMounts } } \ No newline at end of file diff --git a/apps/api/src/routes/api/v1/services/handlers.ts b/apps/api/src/routes/api/v1/services/handlers.ts index 2af8baf0b..1dec25c54 100644 --- a/apps/api/src/routes/api/v1/services/handlers.ts +++ b/apps/api/src/routes/api/v1/services/handlers.ts @@ -2,7 +2,7 @@ import type { FastifyReply, FastifyRequest } from 'fastify'; import fs from 'fs/promises'; import yaml from 'js-yaml'; 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, persistentVolumes } from '../../../../lib/common'; import { day } from '../../../../lib/dayjs'; import { checkContainer, isContainerExited, removeContainer } from '../../../../lib/docker'; import cuid from 'cuid'; @@ -374,7 +374,7 @@ export async function checkService(request: FastifyRequest) { } if (otherFqdns && otherFqdns.length > 0) { for (const ofqdn of otherFqdns) { - found = await isDomainConfigured({ id, fqdn: ofqdn,remoteIpAddress }); + found = await isDomainConfigured({ id, fqdn: ofqdn, remoteIpAddress }); if (found) { throw { status: 500, message: `Domain ${getDomain(ofqdn).replace('www.', '')} is already in use!` } } @@ -685,6 +685,7 @@ async function startPlausibleAnalyticsService(request: FastifyRequest) { const { id } = request.params; const teamId = request.user.teamId; const service = await getServiceFromDB({ id, teamId }); - const { type, version, destinationDockerId, destinationDocker, serviceSecret, exposePort } = + const { type, version, destinationDockerId, destinationDocker, serviceSecret, exposePort, persistentStorage } = service; const network = destinationDockerId && destinationDocker.network; const port = getServiceMainPort('nocodb'); @@ -916,6 +922,7 @@ async function startNocodbService(request: FastifyRequest) { config.environmentVariables[secret.name] = secret.value; }); } + const { volumes, volumeMounts } = persistentVolumes(id, persistentStorage, config) const composeFile: ComposeFile = { version: '3.8', services: { @@ -923,7 +930,7 @@ async function startNocodbService(request: FastifyRequest) { container_name: id, image: config.image, networks: [network], - volumes: [config.volume], + volumes, environment: config.environmentVariables, restart: 'always', ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), @@ -943,15 +950,11 @@ async function startNocodbService(request: FastifyRequest) { external: true } }, - volumes: { - [config.volume.split(':')[0]]: { - name: config.volume.split(':')[0] - } - } + volumes: volumeMounts }; const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); - //await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up --build -d` }) return {} } catch ({ status, message }) { @@ -987,6 +990,7 @@ async function startMinioService(request: FastifyRequest) { fqdn, destinationDockerId, destinationDocker, + persistentStorage, exposePort, minio: { rootUser, rootUserPassword }, serviceSecret @@ -1016,6 +1020,7 @@ async function startMinioService(request: FastifyRequest) { config.environmentVariables[secret.name] = secret.value; }); } + const { volumes, volumeMounts } = persistentVolumes(id, persistentStorage, config) const composeFile: ComposeFile = { version: '3.8', services: { @@ -1025,7 +1030,7 @@ async function startMinioService(request: FastifyRequest) { command: `server /data --console-address ":${consolePort}"`, environment: config.environmentVariables, networks: [network], - volumes: [config.volume], + volumes, restart: 'always', ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), labels: makeLabelForServices('minio'), @@ -1044,15 +1049,11 @@ async function startMinioService(request: FastifyRequest) { external: true } }, - volumes: { - [config.volume.split(':')[0]]: { - name: config.volume.split(':')[0] - } - } + volumes: volumeMounts }; const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); - //await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up --build -d` }) await prisma.minio.update({ where: { serviceId: id }, data: { publicPort } }); return {} @@ -1113,28 +1114,8 @@ async function startVscodeService(request: FastifyRequest) { config.environmentVariables[secret.name] = secret.value; }); } + const { volumes, volumeMounts } = persistentVolumes(id, persistentStorage, config) - const volumes = - persistentStorage?.map((storage) => { - return `${id}${storage.path.replace(/\//gi, '-')}:${storage.path}`; - }) || []; - - const composeVolumes = volumes.map((volume) => { - return { - [`${volume.split(':')[0]}`]: { - name: volume.split(':')[0] - } - }; - }); - const volumeMounts = Object.assign( - {}, - { - [config.volume.split(':')[0]]: { - name: config.volume.split(':')[0] - } - }, - ...composeVolumes - ); const composeFile: ComposeFile = { version: '3.8', services: { @@ -1143,7 +1124,7 @@ async function startVscodeService(request: FastifyRequest) { image: config.image, environment: config.environmentVariables, networks: [network], - volumes: [config.volume, ...volumes], + volumes, restart: 'always', ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), labels: makeLabelForServices('vscodeServer'), @@ -1167,7 +1148,7 @@ async function startVscodeService(request: FastifyRequest) { const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); - //await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up --build -d` }) const changePermissionOn = persistentStorage.map((p) => p.path); @@ -1212,6 +1193,7 @@ async function startWordpressService(request: FastifyRequest) destinationDockerId, serviceSecret, destinationDocker, + persistentStorage, exposePort, wordpress: { mysqlDatabase, @@ -1260,6 +1242,9 @@ async function startWordpressService(request: FastifyRequest) config.wordpress.environmentVariables[secret.name] = secret.value; }); } + + const { volumes, volumeMounts } = persistentVolumes(id, persistentStorage, config.wordpress) + let composeFile: ComposeFile = { version: '3.8', services: { @@ -1267,7 +1252,7 @@ async function startWordpressService(request: FastifyRequest) container_name: id, image: config.wordpress.image, environment: config.wordpress.environmentVariables, - volumes: [config.wordpress.volume], + volumes, networks: [network], restart: 'always', ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), @@ -1287,11 +1272,7 @@ async function startWordpressService(request: FastifyRequest) external: true } }, - volumes: { - [config.wordpress.volume.split(':')[0]]: { - name: config.wordpress.volume.split(':')[0] - } - } + volumes: volumeMounts }; if (!ownMysql) { composeFile.services[id].depends_on = [`${id}-mysql`]; @@ -1319,7 +1300,7 @@ async function startWordpressService(request: FastifyRequest) const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); - //await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up --build -d` }) return {} @@ -1380,7 +1361,7 @@ async function startVaultwardenService(request: FastifyRequest const { id } = request.params; const teamId = request.user.teamId; const service = await getServiceFromDB({ id, teamId }); - const { type, version, destinationDockerId, destinationDocker, serviceSecret, exposePort } = + const { type, version, destinationDockerId, destinationDocker, serviceSecret, exposePort, persistentStorage } = service; const network = destinationDockerId && destinationDocker.network; @@ -1399,6 +1380,7 @@ async function startVaultwardenService(request: FastifyRequest config.environmentVariables[secret.name] = secret.value; }); } + const { volumes, volumeMounts } = persistentVolumes(id, persistentStorage, config) const composeFile: ComposeFile = { version: '3.8', services: { @@ -1407,7 +1389,7 @@ async function startVaultwardenService(request: FastifyRequest image: config.image, environment: config.environmentVariables, networks: [network], - volumes: [config.volume], + volumes, restart: 'always', ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), labels: makeLabelForServices('vaultWarden'), @@ -1426,16 +1408,12 @@ async function startVaultwardenService(request: FastifyRequest external: true } }, - volumes: { - [config.volume.split(':')[0]]: { - name: config.volume.split(':')[0] - } - } + volumes: volumeMounts }; const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); - //await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up --build -d` }) return {} @@ -1470,7 +1448,7 @@ async function startLanguageToolService(request: FastifyRequest) { const { id } = request.params; const teamId = request.user.teamId; const service = await getServiceFromDB({ id, teamId }); - const { type, version, destinationDockerId, destinationDocker, serviceSecret, exposePort } = + const { type, version, destinationDockerId, destinationDocker, serviceSecret, exposePort, persistentStorage } = service; const network = destinationDockerId && destinationDocker.network; const port = getServiceMainPort('n8n'); @@ -1580,6 +1555,7 @@ async function startN8nService(request: FastifyRequest) { config.environmentVariables[secret.name] = secret.value; }); } + const { volumes, volumeMounts } = persistentVolumes(id, persistentStorage, config) const composeFile: ComposeFile = { version: '3.8', services: { @@ -1587,7 +1563,7 @@ async function startN8nService(request: FastifyRequest) { container_name: id, image: config.image, networks: [network], - volumes: [config.volume], + volumes, environment: config.environmentVariables, restart: 'always', labels: makeLabelForServices('n8n'), @@ -1607,16 +1583,12 @@ async function startN8nService(request: FastifyRequest) { external: true } }, - volumes: { - [config.volume.split(':')[0]]: { - name: config.volume.split(':')[0] - } - } + volumes: volumeMounts }; const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); - //await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up --build -d` }) return {} @@ -1651,7 +1623,7 @@ async function startUptimekumaService(request: FastifyRequest) const { id } = request.params; const teamId = request.user.teamId; const service = await getServiceFromDB({ id, teamId }); - const { type, version, destinationDockerId, destinationDocker, serviceSecret, exposePort } = + const { type, version, destinationDockerId, destinationDocker, serviceSecret, exposePort, persistentStorage } = service; const network = destinationDockerId && destinationDocker.network; const port = getServiceMainPort('uptimekuma'); @@ -1669,6 +1641,7 @@ async function startUptimekumaService(request: FastifyRequest) config.environmentVariables[secret.name] = secret.value; }); } + const { volumes, volumeMounts } = persistentVolumes(id, persistentStorage, config) const composeFile: ComposeFile = { version: '3.8', services: { @@ -1676,7 +1649,7 @@ async function startUptimekumaService(request: FastifyRequest) container_name: id, image: config.image, networks: [network], - volumes: [config.volume], + volumes, environment: config.environmentVariables, restart: 'always', ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), @@ -1696,16 +1669,12 @@ async function startUptimekumaService(request: FastifyRequest) external: true } }, - volumes: { - [config.volume.split(':')[0]]: { - name: config.volume.split(':')[0] - } - } + volumes: volumeMounts }; const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); - //await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up --build -d` }) return {} @@ -1746,6 +1715,7 @@ async function startGhostService(request: FastifyRequest) { destinationDockerId, destinationDocker, serviceSecret, + persistentStorage, exposePort, fqdn, ghost: { @@ -1799,6 +1769,8 @@ async function startGhostService(request: FastifyRequest) { config.ghost.environmentVariables[secret.name] = secret.value; }); } + + const { volumes, volumeMounts } = persistentVolumes(id, persistentStorage, config.ghost) const composeFile: ComposeFile = { version: '3.8', services: { @@ -1806,7 +1778,7 @@ async function startGhostService(request: FastifyRequest) { container_name: id, image: config.ghost.image, networks: [network], - volumes: [config.ghost.volume], + volumes, environment: config.ghost.environmentVariables, restart: 'always', ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), @@ -1844,9 +1816,7 @@ async function startGhostService(request: FastifyRequest) { } }, volumes: { - [config.ghost.volume.split(':')[0]]: { - name: config.ghost.volume.split(':')[0] - }, + ...volumeMounts, [config.mariadb.volume.split(':')[0]]: { name: config.mariadb.volume.split(':')[0] } @@ -1855,7 +1825,7 @@ async function startGhostService(request: FastifyRequest) { const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); - //await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up --build -d` }) return {} @@ -1897,7 +1867,7 @@ async function startMeilisearchService(request: FastifyRequest const { meiliSearch: { masterKey } } = service; - const { type, version, destinationDockerId, destinationDocker, serviceSecret, exposePort } = + const { type, version, destinationDockerId, destinationDocker, serviceSecret, exposePort, persistentStorage } = service; const network = destinationDockerId && destinationDocker.network; const port = getServiceMainPort('meilisearch'); @@ -1918,6 +1888,7 @@ async function startMeilisearchService(request: FastifyRequest config.environmentVariables[secret.name] = secret.value; }); } + const { volumes, volumeMounts } = persistentVolumes(id, persistentStorage, config) const composeFile: ComposeFile = { version: '3.8', services: { @@ -1928,7 +1899,7 @@ async function startMeilisearchService(request: FastifyRequest environment: config.environmentVariables, restart: 'always', ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), - volumes: [config.volume], + volumes, labels: makeLabelForServices('meilisearch'), deploy: { restart_policy: { @@ -1945,19 +1916,12 @@ async function startMeilisearchService(request: FastifyRequest external: true } }, - volumes: { - [config.volume.split(':')[0]]: { - name: config.volume.split(':')[0] - } - } + volumes: volumeMounts }; const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); - - - //await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up --build -d` }) - return {} } catch ({ status, message }) { return errorHandler({ status, message }) @@ -1996,6 +1960,7 @@ async function startUmamiService(request: FastifyRequest) { destinationDockerId, destinationDocker, serviceSecret, + persistentStorage, exposePort, umami: { umamiAdminPassword, @@ -2119,6 +2084,7 @@ async function startUmamiService(request: FastifyRequest) { FROM ${config.postgresql.image} COPY ./schema.postgresql.sql /docker-entrypoint-initdb.d/schema.postgresql.sql`; await fs.writeFile(`${workdir}/Dockerfile`, Dockerfile); + const { volumes, volumeMounts } = persistentVolumes(id, persistentStorage, config.umami) const composeFile: ComposeFile = { version: '3.8', services: { @@ -2127,7 +2093,7 @@ async function startUmamiService(request: FastifyRequest) { image: config.umami.image, environment: config.umami.environmentVariables, networks: [network], - volumes: [], + volumes, restart: 'always', ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), labels: makeLabelForServices('umami'), @@ -2164,6 +2130,7 @@ async function startUmamiService(request: FastifyRequest) { } }, volumes: { + ...volumeMounts, [config.postgresql.volume.split(':')[0]]: { name: config.postgresql.volume.split(':')[0] } @@ -2171,11 +2138,8 @@ async function startUmamiService(request: FastifyRequest) { }; const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); - - - //await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up --build -d` }) - return {} } catch ({ status, message }) { return errorHandler({ status, message }) @@ -2221,6 +2185,7 @@ async function startHasuraService(request: FastifyRequest) { version, destinationDockerId, destinationDocker, + persistentStorage, serviceSecret, exposePort, hasura: { postgresqlUser, postgresqlPassword, postgresqlDatabase } @@ -2254,6 +2219,7 @@ async function startHasuraService(request: FastifyRequest) { }); } + const { volumes, volumeMounts } = persistentVolumes(id, persistentStorage, config.hasura) const composeFile: ComposeFile = { version: '3.8', services: { @@ -2262,7 +2228,7 @@ async function startHasuraService(request: FastifyRequest) { image: config.hasura.image, environment: config.hasura.environmentVariables, networks: [network], - volumes: [], + volumes, restart: 'always', labels: makeLabelForServices('hasura'), ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), @@ -2299,6 +2265,7 @@ async function startHasuraService(request: FastifyRequest) { } }, volumes: { + ...volumeMounts, [config.postgresql.volume.split(':')[0]]: { name: config.postgresql.volume.split(':')[0] } @@ -2307,7 +2274,7 @@ async function startHasuraService(request: FastifyRequest) { const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); - //await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up --build -d` }) return {} @@ -2357,6 +2324,7 @@ async function startFiderService(request: FastifyRequest) { destinationDockerId, destinationDocker, serviceSecret, + persistentStorage, exposePort, fider: { postgresqlUser, @@ -2412,7 +2380,7 @@ async function startFiderService(request: FastifyRequest) { config.fider.environmentVariables[secret.name] = secret.value; }); } - + const { volumes, volumeMounts } = persistentVolumes(id, persistentStorage, config.fider) const composeFile: ComposeFile = { version: '3.8', services: { @@ -2421,7 +2389,7 @@ async function startFiderService(request: FastifyRequest) { image: config.fider.image, environment: config.fider.environmentVariables, networks: [network], - volumes: [], + volumes, restart: 'always', labels: makeLabelForServices('fider'), ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), @@ -2458,6 +2426,7 @@ async function startFiderService(request: FastifyRequest) { } }, volumes: { + ...volumeMounts, [config.postgresql.volume.split(':')[0]]: { name: config.postgresql.volume.split(':')[0] } @@ -2466,7 +2435,7 @@ async function startFiderService(request: FastifyRequest) { const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); - //await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up --build -d` }) return {} @@ -2516,6 +2485,7 @@ async function startMoodleService(request: FastifyRequest) { destinationDockerId, destinationDocker, serviceSecret, + persistentStorage, exposePort, moodle: { defaultUsername, @@ -2565,7 +2535,7 @@ async function startMoodleService(request: FastifyRequest) { config.moodle.environmentVariables[secret.name] = secret.value; }); } - + const { volumes, volumeMounts } = persistentVolumes(id, persistentStorage, config.moodle) const composeFile: ComposeFile = { version: '3.8', services: { @@ -2574,7 +2544,7 @@ async function startMoodleService(request: FastifyRequest) { image: config.moodle.image, environment: config.moodle.environmentVariables, networks: [network], - volumes: [], + volumes, restart: 'always', labels: makeLabelForServices('moodle'), ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), @@ -2613,9 +2583,7 @@ async function startMoodleService(request: FastifyRequest) { } }, volumes: { - [config.moodle.volume.split(':')[0]]: { - name: config.moodle.volume.split(':')[0] - }, + ...volumeMounts, [config.mariadb.volume.split(':')[0]]: { name: config.mariadb.volume.split(':')[0] } @@ -2625,11 +2593,9 @@ async function startMoodleService(request: FastifyRequest) { const composeFileDestination = `${workdir}/docker-compose.yaml`; await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); - - //await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) + await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` }) await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up --build -d` }) - return {} } catch ({ status, message }) { return errorHandler({ status, message }) @@ -2762,9 +2728,10 @@ export async function activateWordpressFtp(request: FastifyRequest