Keep the app source archive with the app instance data dir

This commit is contained in:
Johannes Zellner
2026-01-27 12:06:40 +01:00
parent ef2a94c2c8
commit fd0d65b8ce
4 changed files with 57 additions and 20 deletions

View File

@@ -25,6 +25,7 @@ const apps = require('./apps.js'),
docker = require('./docker.js'),
ejs = require('ejs'),
fs = require('node:fs'),
fsPromises = require('node:fs').promises,
iputils = require('./iputils.js'),
manifestFormat = require('@cloudron/manifest-format'),
os = require('node:os'),
@@ -226,11 +227,35 @@ async function downloadImage(manifest) {
if (diskUsage.available < (1024*1024*1024)) throw new BoxError(BoxError.DOCKER_ERROR, `Not enough disk space to pull docker image. available: ${diskUsage.available}`);
if (manifest.dockerImage.indexOf('local/') === 0) {
await docker.buildImage(manifest);
} else {
await docker.downloadImage(manifest);
await docker.downloadImage(manifest);
}
async function buildLocalImage(app) {
assert.strictEqual(typeof app, 'object');
// TODO some precondition checks like downloadImage maybe
const sourceFilePath = path.join(paths.APPS_DATA_DIR, app.id, 'source.tar.gz');
// if we have a newly uploaded source archive, use that
const uploadedSourceArchiveFilePath = `/tmp/${app.id}.tar.gz`;
if (fs.existsSync(uploadedSourceArchiveFilePath)) {
const [renameError] = await safe(fsPromises.rename(uploadedSourceArchiveFilePath, sourceFilePath));
if (renameError) {
if (renameError.code === 'EXDEV') {
// Cross-device rename not permitted, so copy and remove
let [error] = await safe(fsPromises.copyFile(uploadedSourceArchiveFilePath, sourceFilePath));
if (error) throw new BoxError(BoxError.FS_ERROR, error);
[error] = await safe(fsPromises.unlink(uploadedSourceArchiveFilePath));
if (error) throw new BoxError(BoxError.FS_ERROR, error);
} else {
throw new BoxError(BoxError.FS_ERROR, renameError);
}
}
}
await docker.buildImage(app.manifest.dockerImage, sourceFilePath);
}
async function updateChecklist(app, newChecks, acknowledged = false) {
@@ -321,8 +346,11 @@ async function installCommand(app, args, progressCallback) {
await dns.registerLocations([ { subdomain: app.subdomain, domain: app.domain }].concat(app.secondaryDomains).concat(app.redirectDomains).concat(app.aliasDomains), { overwriteDns }, progressCallback);
}
await progressCallback({ percent: 40, message: 'Downloading image' });
await downloadImage(app.manifest);
// only download non-local images, local ones are built after restore
if (app.manifest.dockerImage.indexOf('local/') !== 0) {
await progressCallback({ percent: 40, message: 'Downloading image' });
await downloadImage(app.manifest);
}
await progressCallback({ percent: 50, message: 'Creating app data directory' });
await createAppDir(app);
@@ -360,6 +388,12 @@ async function installCommand(app, args, progressCallback) {
await services.restoreAddons(app, app.manifest.addons);
}
// now we have the local package tarball, so lets build
if (app.manifest.dockerImage.indexOf('local/') === 0) {
await progressCallback({ percent: 75, message: 'Building image' });
await buildLocalImage(app);
}
await progressCallback({ percent: 80, message: 'Creating container' });
await createContainer(app);