Bind mount vs named volume: Ipi bora kwa Docker Compose?
Jifunze tofauti kati ya bind mount na named volume katika Docker Compose. Pata mwongozo wa kuchagua kati ya faili za usanidi na data ya database ili kuepuka makosa ya ruhusa.
Bind mount au named volume: jibu fupi
Docker Compose volumes zipo za aina mbili, na chaguo hutegemea nani anayemiliki faili hizo. Tumia bind mount kwa faili unazozisoma na kuzihariri mwenyewe, kama vile configuration, templates, na tovuti tuli. Tumia named volume kwa data inayomilikiwa na programu, kama vile faili za database, search indexes, na media zilizopakiwa. Bind mount huelekeza kwenye njia (path) ya seva pangishi (host) ambayo unaweza kuifungua kwa kihariri. Named volume ni hifadhi ambayo Docker inakuundia na kuisimamia, na unaifikia kupitia Docker.
Zote huonekana chini ya ufunguo uleule wa volumes: ndani ya service, ndiyo maana watu huchanganya matumizi yake. Tofauti iko upande wa kushoto wa koloni. Upande wa kushoto unaoanza na . au / ni njia ya kwenye seva pangishi, kwa hiyo huo ni bind mount. Kitu kingine chochote ni jina, kwa hiyo huo ni named volume, na jina hilo lazima litangazwe pia kwenye block ya ngazi ya juu ya volumes:.
Sintaksia mbili katika faili la compose
services:
db:
image: postgres:17
environment:
POSTGRES_PASSWORD: changeme
volumes:
- pgdata:/var/lib/postgresql/data
web:
image: nginx:1.27
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./site:/usr/share/nginx/html:ro
volumes:
pgdata:pgdata:/var/lib/postgresql/data ni volume yenye jina. ./nginx.conf:/etc/nginx/nginx.conf ni bind mount, na :ro huipandisha (mount) ikiwa na ruhusa ya kusoma pekee, ambayo ndiyo chaguo-msingi sahihi kwa usanidi ambao container haipaswi kuubadilisha. Sahau sehemu ya volumes: katika ngazi ya juu na Compose itasimama na kutoa service "db" refers to undefined volume pgdata.
Iwashe huduma hiyo na uorodheshe kile ambacho Docker imekitengeneza:
docker compose up -d
docker volume lsVolume hiyo haijaitwa pgdata. Inaitwa <project>_pgdata, ambapo jina la mradi huwa ni jina la saraka (directory) iliyohifadhi faili la compose. Saraka inayoitwa myapp inatoa myapp_pgdata. Hili ni muhimu kwa sababu kubadilisha jina la saraka kutakupa volume mpya tupu, na programu itaonekana kama imepoteza data zake. Haikupoteza: volume ya zamani bado imeorodheshwa na docker volume ls. Funga jina hilo kwa kutumia name: ndani ya faili la compose, au weka COMPOSE_PROJECT_NAME, ikiwa saraka hiyo inaweza kuhama. Mipangilio kama hiyo inapaswa kuwekwa pamoja na faili za mazingira na siri za Compose.
Kwa nini makosa ya ruhusa (permission errors) mara nyingi huathiri bind mounts
Huu ndio utofauti mkubwa wa kiutendaji, na unatokana na kanuni moja: named volume ambayo haina kitu mwanzoni hujazwa data kutoka kwenye image, lakini bind mount haifanyi hivyo kamwe.
Wakati Docker inapopachika (mount) named volume tupu juu ya saraka (directory) ambayo tayari ina maudhui ndani ya image, hunakili maudhui hayo kwenye volume hiyo, ikiwa na umiliki na ruhusa zilizowekwa na image hiyo. Image rasmi ya Postgres husafirisha /var/lib/postgresql/data inayomilikiwa na mtumiaji wake wa postgres, kwa hivyo volume hiyo hutokea ikiwa na umiliki wa namba hiyo hiyo ya kitambulisho (numeric id), na database huanza kufanya kazi.
Ujazaji huo wa awali ndio faida pekee ambayo named volume hupata. Docker husimamia mahali ambapo volume hiyo inapoishi, lakini container husoma na kuandika humo kwa kutumia shughuli za kawaida za mfumo wa faili (filesystem operations), kwa hivyo umiliki na ruhusa hutekelezwa kama ilivyo kwenye bind mount. Named volume inayopachikwa kwenye njia (path) ambayo image haina, au ile inayojazwa kwanza na image au mtumiaji tofauti, haipati umiliki wowote kutoka kwenye image, na mchakato usio wa root unaweza kukataliwa huko pia. Ukaguzi wa id hapa chini hufanya kazi kwa aina zote mbili.
Bind mount hufanya kinyume chake. Chochote kilichopo kwenye host ndicho container inachokiona, ikiwemo umiliki, na maudhui ya image kwenye njia hiyo hufichwa. Ikiwa saraka ya host haipo, Docker daemon huiumba, na daemon hiyo huendeshwa kama root, kwa hivyo unapata saraka inayomilikiwa na root:root. Mchakato wa container unaoendeshwa kama mtumiaji asiye root basi hauwezi kuandika humo:
PermissionError: [Errno 13] Permission denied: '/data/app.db'Suluhisho ni kufanya namba hizo zilingane. Umiliki kwenye bind mount hulinganishwa kwa namba ya kitambulisho cha mtumiaji (numeric user id), si kwa jina, kwa sababu container ina /etc/passwd yake yenyewe. Mtumiaji anayeitwa app ndani ya container haimaanishi chochote kwenye host. Uid 1000 inamaanisha uid 1000 pande zote mbili, isipokuwa kama daemon inaendeshwa na user-namespace remapping (userns-remap, iliyowekwa kwenye /etc/docker/daemon.json au kwenye mstari wa amri wa dockerd). Remapping hubadilisha kila kitambulisho cha container kuwa safu ndogo (subordinate range) kwenye host. Katika safu ya mfano ya Docker inayoanzia 231072, container uid 0 ni host uid 231072, kwa hivyo container uid 1000 ni host uid 232072.
id -u
mkdir -p ./data
docker compose exec web id
sudo chown -R 1000:1000 ./datadocker compose exec web id huchapisha uid ambayo mchakato wa container huendeshwa kwayo. Bila remapping, linganisha saraka ya host na namba hiyo, au funga (pin) container kwenye namba yako na user: "1000:1000" katika huduma hiyo. Remapping ikiwa imewashwa, user: haiwezi kufunga container kwenye namba yako ya host, kwa sababu kitambulisho ulichoweka hubadilishwa pia: user: "1000:1000" bado hutua kwenye host uid 232072 katika safu hiyo ya mfano. Fanya chown kwenye saraka ya host ili iwe na host id iliyopangwa (safu yako mwenyewe iko kwenye /etc/subuid na /etc/subgid). Nyaraka za Docker hutaja tu --userns=host kwenye docker container create, run au exec kama njia ya kuzima remapping kwa container moja. Kufunga user: ni safi zaidi kwa programu uliyoiandika wewe mwenyewe. Kufanya chown kwenye saraka ya host ni salama zaidi kwa image ambayo hukuandika wewe, kwa sababu baadhi ya image huanzisha entrypoint kama root, huacha marupurupu (drop privileges), na kutarajia umiliki maalum chini yake.
Mitego mingine miwili inafaa kujulikana. Kwenye Fedora, RHEL na mifumo mingine yenye SELinux (security-enhanced Linux) inayotekelezwa, bind mount hukataliwa hadi iwekewe lebo upya, kwa hivyo ongeza :z kwa njia inayoshirikiwa kati ya container au :Z kwa njia ambayo container moja tu inapaswa kutumia, iliyoandikwa kama - ./data:/data:Z. Na bind mount ya faili moja, badala ya saraka, huvunjika wakati kihariri (editor) kinapobadilisha faili badala ya kuandika mahali pale pale, kwa sababu mount hufuata inode ya asili. Container huendelea kuona maudhui ya zamani hadi utakapoiwasha upya. Pachika saraka kuu (parent directory) wakati faili inahaririwa mara kwa mara.
Utendaji: pale ambapo tofauti ni ya kweli
Kwenye seva ya Linux, aina zote mbili hupitia njia ile ile ya kernel, kwa hivyo tofauti ya throughput ni ndogo kiasi kwamba hupaswi kuchagua kwa msingi huo. Named volumes zinazotumia driver ya default ya local huishi kwenye filesystem ile ile kama sehemu nyingine ya Docker, chini ya /var/lib/docker/volumes/, na bind mount huishi popote ulipoelekeza.
Tofauti huonekana kwenye Docker Desktop kwa macOS na Windows, ambapo containers huendeshwa ndani ya virtual machine. Bind mount huko huvuka kutoka filesystem ya host kuingia kwenye virtual machine hiyo kupitia safu ya kushiriki faili (file sharing layer), na workloads zenye operesheni nyingi ndogo za faili, kama vile Node.js dependency tree au cache ya PHP framework, hupungua kasi kwa kiasi kinachoonekana. Named volumes hubaki ndani ya virtual machine na hazilipi gharama hiyo. Hii ndiyo sababu compose files nyingi za maendeleo hufanya bind-mount ya source directory lakini hutangaza named volume juu ya node_modules.
Tofauti nyingine ya kweli ni mahali ambapo bytes hutua. Bind mount kwenda /mnt/backup huweka data kwenye diski hiyo. Named volume hutua kwenye filesystem yoyote inayoshikilia /var/lib/docker, ambayo kwenye VPS kwa kawaida ni root disk. Database inayokua ndani ya named volume hujaza diski ile ile ambayo system logs zako zipo. Iangalie kabla haijawa tukio:
docker system df -v
df -h /var/lib/dockerdocker system df -v huorodhesha kila volume pamoja na ukubwa wake, na huashiria zile ambazo hakuna container inayozirejelea tena.
Kukagua named volume
Named volume si kisanduku cheusi. Iulize Docker mahali ilipo:
docker volume inspect myapp_pgdataSehemu ya Mountpoint inatoa njia halisi ya host, kwa kawaida /var/lib/docker/volumes/myapp_pgdata/_data. Unaweza kuisoma kwa kutumia sudo ls, na hiyo ni muhimu kwa ukaguzi wa haraka. Usiichukulie kama mahali pa kuhariri faili. Kuandika hapo ukiwa root kunarejesha tatizo la umiliki lililoelezwa hapo juu, na njia hiyo ni maelezo ya dereva wa local ambayo madereva wengine wa volume hawashiriki.
Njia salama ya kuangalia ndani ni kutumia container ya muda inayopachika (mount) volume hiyo:
docker run --rm -v myapp_pgdata:/vol alpine ls -la /volHiyo inafanya kazi kwa dereva yeyote, inaona ruhusa zilezile ambazo container halisi inaona, na haiachi kitu chochote nyuma kwa sababu ya --rm.
Kuhifadhi nakala za kila aina
Bind mount ni saraka ya kawaida, kwa hivyo zana yoyote ya kuhifadhi nakala za faili inaweza kuishughulikia. Elekeza hifadhi hiyo kwenye njia ya host na umemaliza. Named volume inahitaji hatua moja ya ziada, kwa sababu zana hiyo lazima iingie ndani yake. Mount volume hiyo na saraka ya host kwenye container ya muda mfupi, kisha andika archive:
docker run --rm \
-v myapp_pgdata:/data:ro \
-v "$PWD":/backup \
alpine tar czf /backup/pgdata.tar.gz -C /data .Rejesha kwa kubadilisha mchakato huo kwenye volume mpya:
docker volume create myapp_pgdata_restored
docker run --rm \
-v myapp_pgdata_restored:/data \
-v "$PWD":/backup \
alpine tar xzf /backup/pgdata.tar.gz -C /datatar huhifadhi umiliki wa nambari (numeric ownership) inapoendeshwa kama root ndani ya container, jambo ambalo hufanya volume iliyorejeshwa iweze kutumiwa na programu.
Onyo moja linahusu aina zote mbili. Kunakili faili za database wakati database inaendeshwa hukupa archive ya data inayobadilika, na inaweza kurejeshwa ikiwa katika hali ya uharibifu. Simamisha huduma kwanza, au fanya dump kupitia zana ya database yenyewe, kama ilivyo katika docker compose exec -T db pg_dump -U postgres appdb > appdb.sql. Hiyo hutengeneza faili ya kawaida ambayo unaweza kuiingiza kwenye utaratibu wa kawaida wa kuhifadhi nakala kwa kutumia restic pamoja na faili zako za compose.
Kuhama kutoka bind mount kwenda named volume
Uhamishaji huu ni nakala, si kubadilisha jina, na huchukua takriban dakika moja.
docker compose down
docker volume create myapp_pgdata
docker run --rm \
-v "$PWD/data":/from \
-v myapp_pgdata:/to \
alpine sh -c 'cp -a /from/. /to/'cp -a huhifadhi umiliki, modes na timestamps, hivyo mtumiaji wa container aliyeweza kusoma saraka ya zamani ataweza kusoma volume mpya. Kisha badilisha huduma ili itumie pgdata:/var/lib/postgresql/data, ongeza pgdata kwenye block ya volumes: ya ngazi ya juu, endesha docker compose up -d, na usome logi za programu kabla ya kufuta saraka ya zamani. Kufanya kinyume chake hutumia amri ileile huku /from na /to zikibadilishwa nafasi.
Kumbuka jambo moja wakati wa majaribio. docker compose down haigusi named volumes, lakini docker compose down -v hufuta kila named volume inayotangazwa na mradi, na hakuna njia ya kutendua. Bind mount hubaki salama katika hali zote mbili, kwa sababu Docker haijawahi kumiliki saraka hiyo. Ikiwa amri za lifecycle bado ni ngeni kwako, mwongozo wa misingi ya Docker Compose kwa VPS unaelezea hatua hizo.
Kuchagua, huduma kwa huduma
Uliza ni nani anayeandika faili hiyo. Configuration unayohariri kwenye text editor na kuifanyia commit kwenye git inapaswa kuwekwa kwenye bind mount, iliyopachikwa :ro, kwa sababu unataka ionekane na iwe na version control. Hali ya programu (application state) ambayo huifungui kamwe kwa mkono inapaswa kuwekwa kwenye named volume, kwa sababu Docker huweka ruhusa (permissions) kutoka kwenye image na data haitegemei njia ya host (host path).
Kesi mchanganyiko ni media. Maktaba ya picha huandikwa na programu lakini pia husimamiwa na wewe, na mara nyingi huwa kubwa kiasi cha kuhitaji diski maalum. Ipachike (bind mount) kwenye njia (path) iliyo kwenye diski hiyo, na uweke umiliki (ownership) kwa makusudi mara moja. Huo ndio muundo ambao stack nyingi za self-hosted hufuata: named volumes kwa ajili ya database na cache, bind mounts kwa ajili ya config na saraka kubwa unayojali. Huduma ya usaidizi kama Chatwoot inayofanya kazi kwenye VPS huishia hapo hapo, ikiwa na Postgres kwenye named volume na viambatisho vilivyopakiwa kwenye njia unayoweza kuielekeza kwenye backup.
FAQ
Kuna tofauti gani kati ya bind mount na named volume?
Bind mount hupanga njia kwenye host ndani ya container, kwa hivyo pande zote mbili huona saraka moja na unaweza kuihariri kwa zana za kawaida. Named volume ni hifadhi ambayo Docker huiumba na kuisimamia, inayorejelewa kwa jina na kutangazwa katika block ya ngazi ya juu ya volumes:. Mgawanyiko wa kiutendaji ni umiliki: bind mounts kwa ajili ya usanidi unaodumisha, named volumes kwa ajili ya data ambayo programu inaidumisha.
Kwa nini napata "permission denied" na bind mount lakini si na named volume?
Named volume tupu hujazwa data kutoka kwenye image, kwa hivyo kwa kawaida hurithi umiliki uliowekwa na image na mtumiaji wa container anaweza kuandika humo. Bado hutekeleza ruhusa, kwa hivyo inaweza kushindwa kwa njia ile ile ikiwa image haina kitu kwenye njia hiyo. Bind mount huonyesha saraka ya host kama ilivyo, na ikiwa Docker ililazimika kuiumba saraka hiyo, iliifanya imilikiwe na root. Endesha docker compose exec <service> id ili kuona namba ya kitambulisho (numeric id) ambayo container inatumia, kisha fanya sudo chown -R <uid>:<gid> kwenye saraka ya host, au, wakati daemon haifanyi remapping ya user namespaces, weka user: "1000:1000" kwenye huduma. Ikiwa daemon inatumia user-namespace remapping, fanya chown kwenye host id iliyopangwa badala yake, kwa sababu vitambulisho vya container hubadilishwa kwenye host na user: haibadilishi hilo.
Docker huhifadhi named volumes wapi kwenye diski?
Kwa kutumia driver ya kawaida ya local, huishi chini ya /var/lib/docker/volumes/<volume>/_data, na docker volume inspect <volume> huchapisha Mountpoint kamili. Isome ikiwa unahitaji kukagua kitu, lakini andika humo kupitia container pekee, kwa sababu kuhariri kama root kwenye host hubadilisha umiliki kwa njia ambazo container haitatarajia.
Ninawezaje kuhifadhi nakala (backup) ya named volume?
Endesha container ya muda mfupi ikiwa na volume na saraka ya host zote zimepachikwa, kisha hifadhi kutoka moja kwenda nyingine na docker run --rm -v myvol:/data:ro -v "$PWD":/backup alpine tar czf /backup/myvol.tar.gz -C /data .. Kwa database, fanya dump na zana ya database yenyewe badala ya kunakili faili zilizopo, kwa sababu nakala ya faili iliyochukuliwa wakati uandikaji unaendelea inaweza kurejesha hali ya uharibifu.
Je, docker compose down hufuta volumes zangu?
docker compose down huondoa container na mitandao na kuacha named volumes mahali pake. docker compose down -v pia hufuta kila named volume ambayo mradi hutangaza, kabisa. Bind mounts haziondolewi kamwe na amri yoyote kati ya hizo, kwa sababu saraka hiyo ni ya host na si ya Docker.