| 157 | |
| 158 | // Sample container RSS from `docker stats --no-stream`. |
| 159 | async function dockerStats(cids) { |
| 160 | const { stdout } = await execFileP("docker", [ |
| 161 | "stats", |
| 162 | "--no-stream", |
| 163 | "--format", |
| 164 | "{{.ID}} {{.MemUsage}}", |
| 165 | ...cids.map((c) => c.slice(0, 12)), |
| 166 | ]); |
| 167 | const result = {}; |
| 168 | for (const line of stdout.trim().split("\n")) { |
| 169 | const [id, mem] = line.split(" ", 2); |
| 170 | // mem looks like "12.5MiB / 7.756GiB"; take the left side. |
| 171 | const usage = mem.split(" / ")[0]; |
| 172 | result[id] = usage; |
| 173 | } |
| 174 | return result; |
| 175 | } |
| 176 | |
| 177 | // Connect a capnweb HTTP batch client to /api. Each call is |
| 178 | // its own session; we accept the cost (one round-trip per |