adiciona método para obter mounts do container e source do bind para helper

This commit is contained in:
Alexander Sabino 2026-05-07 12:37:23 +01:00
parent e174af1be7
commit b66ebda525
2 changed files with 48 additions and 1 deletions

View File

@ -467,7 +467,17 @@ class BackupService {
pushLog('Container sem GNU tar: usando helper com GNU tar para gerar archive.', 'gerando-tar');
updateFileProgress();
const helperBinds = [`${backupRoot}:/backuproot`];
// Quando rodando dentro do Docker, backupRoot é um path interno do container da app.
// Precisamos do source real (host path ou volume name) para passar ao helper container.
const backupRootSource = await this.dockerService.getSelfBindSource(backupRoot);
if (!backupRootSource) {
throw new Error(
`Nao foi possivel determinar o source do diretorio de backup (${backupRoot}) para o helper. ` +
'Verifique se o diretorio de backup esta montado via volume ou bind no container da app.'
);
}
const helperBinds = [`${backupRootSource}:/backuproot`];
const helperRelPaths = [];
for (const [index, mount] of activeMounts.entries()) {
const src = mount.type === 'volume' ? mount.name : mount.source;

View File

@ -63,12 +63,49 @@ class DockerService {
this.docker = new Docker({ socketPath });
this.helperImage = helperImage;
this.runningInContainer = detectRunningInContainer();
this._selfMounts = null; // cache dos mounts do próprio container
}
isRunningInDocker() {
return this.runningInContainer;
}
// Retorna os mounts do container da própria aplicação.
// Lê /etc/hostname para obter o short ID, busca o container na lista e inspeciona.
async _getSelfMounts() {
if (this._selfMounts !== null) return this._selfMounts;
try {
const hostname = fs.readFileSync('/etc/hostname', 'utf8').trim();
const all = await this.docker.listContainers({ all: true });
const self = all.find((c) => c.Id.startsWith(hostname));
if (!self) { this._selfMounts = []; return []; }
const info = await this.docker.getContainer(self.Id).inspect();
this._selfMounts = info.Mounts || [];
} catch {
this._selfMounts = [];
}
return this._selfMounts;
}
// Dado um caminho absoluto dentro do container da app (ex: /app/data/backups),
// retorna o source do bind/volume que o cobre (para usar em helper binds).
// Se não encontrar mount correspondente, retorna null.
async getSelfBindSource(containerPath) {
const mounts = await this._getSelfMounts();
const normalized = containerPath.replace(/\/+$/, '');
// Ordena do mais específico para o mais genérico
const sorted = [...mounts].sort(
(a, b) => (b.Destination || '').length - (a.Destination || '').length
);
for (const mount of sorted) {
const dest = (mount.Destination || '').replace(/\/+$/, '');
if (normalized === dest || normalized.startsWith(dest + '/')) {
return mount.Type === 'volume' ? mount.Name : mount.Source;
}
}
return null;
}
async listContainers() {
const containers = await this.docker.listContainers({ all: true });
return containers