fix(deploy): discover workspace source via container inspect (not mountinfo)

This commit is contained in:
chenxing
2026-08-04 22:56:08 +08:00
parent 1619e41c20
commit f0bd70ff6e
+26 -18
View File
@@ -19,6 +19,15 @@ const fs = require('fs');
const SOCKET = '/var/run/docker.sock'; const SOCKET = '/var/run/docker.sock';
const HOST_STATIC = '/data/www/userbase'; const HOST_STATIC = '/data/www/userbase';
const HELPER_IMAGE = 'node:20'; // already cached on host (used by the job) const HELPER_IMAGE = 'node:20'; // already cached on host (used by the job)
const WS_MOUNT = '/workspace/admin/userbase';
// The job container's ID, derived from its cgroup (robust regardless of hostname).
function getContainerId() {
const cg = fs.readFileSync('/proc/self/cgroup', 'utf8');
const m = cg.match(/[0-9a-f]{64}/);
if (!m) throw new Error('cannot determine container id from cgroup');
return m[0];
}
function dockerReq(method, path, bodyObj) { function dockerReq(method, path, bodyObj) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@@ -42,29 +51,28 @@ function dockerReq(method, path, bodyObj) {
}); });
} }
// Locate the host path backing the workspace mountpoint (a docker volume _data dir). // Locate the host path backing the workspace mount by inspecting THIS container
function findWorkspaceSource(mountpoint) { // via the Docker daemon (docker.sock). This is far more reliable than parsing
const txt = fs.readFileSync('/proc/self/mountinfo', 'utf8'); // /proc/self/mountinfo (which reports the underlying block device, not the bind
for (const line of txt.split('\n')) { // source). The job container's hostname is its short ID.
const parts = line.trim().split(/\s+/); async function findWorkspaceSource() {
if (parts.length < 5) continue; const id = getContainerId();
const mp = parts[4]; const r = await dockerReq('GET', `/containers/${id}/json`);
if (mp === mountpoint || mp.endsWith(mountpoint)) { if (r.status >= 400) {
const dash = parts.indexOf('-'); throw new Error('inspect self failed: ' + r.status + ' ' + r.body);
if (dash !== -1 && parts.length > dash + 2) { }
return parts[dash + 2]; const info = JSON.parse(r.body);
} const mounts = info.Mounts || [];
for (const m of mounts) {
if (m.Destination === WS_MOUNT) {
return m.Source; // host path of the docker volume _data dir
} }
} }
return null; throw new Error('workspace mount ' + WS_MOUNT + ' not found in container inspect');
} }
async function main() { async function main() {
const wsMount = '/workspace/admin/userbase'; const wsSource = await findWorkspaceSource();
const wsSource = findWorkspaceSource(wsMount);
if (!wsSource) {
throw new Error('Could not find workspace source in /proc/self/mountinfo');
}
console.log('workspace source (host path):', wsSource); console.log('workspace source (host path):', wsSource);
// Inside the helper, the workspace is bound at /src (see Binds below). // Inside the helper, the workspace is bound at /src (see Binds below).