Izabrani projekti
flotsam
Čišćenje Docker diska koje zna iz kog projekta je ostao svaki objekat — indeks „projekat → direktorijum", pošten obračun slojeva i dry run podrazumevano.
- Go 1.25
- Docker SDK v28
- SQLite (modernc.org)
- Cobra
- Vue 3 + Vite
- GitHub Actions
- ghcr.io multi-arch
Problem
docker system df rado će vam reći da je nestalo 84 GB. Ali ne odgovara na jedino pitanje koje je bitno pre brisanja:
Ovaj volume — iz kog je projekta i smem li da ga uklonim bez gubitka podataka?
Čim se kontejneri projekta uklone, njegovi volume-i postaju siročići. Na njima i dalje stoji labela com.docker.compose.project, ali nigde nije zapisano gde je taj projekat živeo na disku — i Docker tu vezu više ne može da rekonstruiše. Izbor se svodi na docker system prune -a (obriši sve i nadaj se) ili na to da desetine gigabajta stoje godinama.
Flotsam je ono što ispliva nakon što brod potone. Upravo to ovaj alat i sakuplja.
Šta zna, a Docker ne
flotsam vodi sopstveni indeks: projekat → direktorijum, u SQLite-u (čist Go, bez CGO), punjen pasivno pri svakom pokretanju iz labele com.docker.compose.project.working_dir — dakle dok kontejneri još postoje. Mesecima kasnije, kada kontejnera odavno nema, indeks i dalje odgovara:
🟢 legacy-crm 12.4 GB ⚠ direktorijum ne postoji
/home/v/work/legacy-crm (poslednji put 2025-11-03, izvor: index)
├─ volume legacy-crm_pgdata 8.1 GB postgresql 🟡 sadrži podatke baze
├─ volume legacy-crm_uploads 3.9 GB unknown-data 🟢 direktorijum projekta obrisan
└─ image legacy-crm-app:latest 340 MB 🟢 direktorijum projekta obrisan
Razrešavanje imena je lanac sa eksplicitnim „nepoznato” na kraju: živa labela → indeks → skeniranje fajl sistema → unknown. A read-only proba montira volume da kaže šta je zaista unutra — postgres, mysql, mongo, redis ili neprepoznati podaci. Jer „8 GB nečega” nije osnov za odluku.
Pošten obračun oslobođenog prostora
Brisanje pet imidža ne oslobađa zbir njihovih veličina: dele slojeve. flotsam gradi graf slojeva i sloj računa kao oslobodiv samo kada sve reference na njega leže unutar skupa koji brišete, dok se imidži zakačeni za pokrenute kontejnere isključuju.
Najzanimljiviji deo bilo je poklapanje ImageHistory zapisa sa slojevima iz RootFS.Layers. Očigledno pravilo — uzeti zapise sa Size > 0 — dalo je na stvarnoj mašini svega 55 % poklapanja. Razlog: WORKDIR pravi pravi sloj nulte veličine. Klasifikacija zapisa po CreatedBy (RUN/COPY/ADD/WORKDIR prave sloj; ENV/CMD/ENTRYPOINT ne; #(nop) ne), uz relaxed prolaz za imidže od bazel/ko, podigla je cifru na 99,4 % — 333 od 335 imidža poklopilo se tačno.
Model rizika
Klasifikacija je 18 uređenih pravila, pobeđuje prvo koje se poklopi, a sve što se ne poklopi ni sa čim podrazumevano dobija risky, a ne „verovatno je u redu”:
| Nivo | Značenje | |
|---|---|---|
| 🟢 | safe | Direktorijum projekta obrisan, dangling imidž, prazan volume, davno zaustavljen kontejner |
| 🟡 | probably-safe | Projekat miruje > 30 dana, skorašnji nekorišćen imidž, skorašnji build cache |
| 🔴 | risky | Volume sadrži podatke baze, projekat je aktivan, poreklo nepoznato, putanja dvosmislena |
| ⛔ | never | Zaštićen konfiguracijom, volume zakačen za kontejner, imidž pokrenutog kontejnera |
risky i never nikada ne ulaze u plan, bez obzira na flagove. Crveni objekat se briše samo pojedinačno, po punom imenu, uz --force-risky.
Bezbednosne garancije
applyje podrazumevano dry run; stvarno brisanje traži--no-dry-run.- Volume sa
RefCount > 0nikada se ne briše — ni sa--force-risky. - Inventar se ponovo prikuplja neposredno pre brisanja; sve što se u međuvremenu promenilo preskače se uz upozorenje.
- Nikakav
docker system prune -a— samo ciljana brisanja po ID-u. - Ništa van Docker-a se ne dira: ni direktorijumi projekata, ni disk imidž VM-a.
flotsam hostispisuje komande za sažimanjeDocker.raw/ext4.vhdx; vi ih pokrećete. - Svaka operacija se dopisuje u
~/.local/share/flotsam/history.jsonl. - Direktorijum se smatra „nestalim” samo kada je njegov roditelj vidljiv — nemontirano podstablo se nikada ne pomeša sa obrisanim projektom.
To poslednje pravilo nije teorijsko. Na macOS-u i Windows-u -v /:/host:ro montira koren virtuelne mašine Docker Desktop-a, a ne vaš disk: /host/Users postoji i prazan je. Bez pravila o vidljivom roditelju, kontejnerski build je 8 od 12 živih projekata proglasio siročićima. Sada flotsam prepoznaje situaciju, označava host fajl sistem kao neproverljiv, odbija da bilo šta nazove siročetom i to jasno kaže — umesto da vas poziva da obrišete žive podatke.
Isporuka
Po jedan statički binarni fajl po platformi, ukupno šest (linux/darwin/windows × amd64/arm64), koje GitHub Actions gradi na v* tagu, sa checksums.txt uz release; multi-arch imidž od 22 MB na ghcr.io; i Vue 3 SPA ugrađen u binarni fajl, pa go build ne traži Node — CI pada ako komitovan bundle odstupi od izvora. Sve što CLI ume dostupno je i u browseru na 127.0.0.1:7333: uz token, sa validacijom Host/Origin i bez kolačića.
Pouke
- Vredni podaci nikada nisu bili u Docker-u: to je veza „projekat → direktorijum”, i morala je da se uhvati pre nego što zatreba. Pasivan indeks ne košta ništa po pokretanju — a u njemu je cela funkcija.
- Benchmark iz specifikacije je hipoteza. Opisana heuristika za poklapanje slojeva na stvarnim imidžima radila je na 55 %; cifru „koliko će se zaista osloboditi” poštenom je učinila tek klasifikacija po
CreatedBy. - Kada alat nešto ne može da proveri — na primer, ne vidi host fajl sistem — ispravan izlaz je odbijanje, a ne najbolja pretpostavka. Alati za brisanje nemaju pravo na optimizam.