SSD Nodes Learn Hosting plans →
मार्गदर्शक Matt Connorद्वारे Matt Connor · अपडेटेड 2026-08-29

Docker Compose: Bind mount आणि Named volume मधील फरक

Docker Compose मध्ये Bind mount आणि Named volume कधी वापरावे? डेटा आणि कॉन्फिगरेशनसाठी योग्य पर्याय निवडा. फाईल परमिशनच्या समस्या, बॅकअप आणि मायग्रेशनची संपूर्ण माहिती येथे वाचा.

Bind mount की named volume: थोडक्यात उत्तर

Docker Compose volumes दोन प्रकारचे असतात आणि त्यांची निवड फाईल्सच्या मालकीवर अवलंबून असते. ज्या फाईल्स तुम्ही स्वतः लिहिता किंवा वाचता, उदा. config, templates, static sites, त्यासाठी bind mount वापरा. ज्या डेटाची मालकी ॲप्लिकेशनकडे असते, उदा. database files, search indexes, uploaded media, त्यासाठी named volume वापरा. Bind mount होस्टवरील अशा पाथला निर्देशित करते जो तुम्ही एडिटरमध्ये उघडू शकता. Named volume हे Docker द्वारे तयार केलेले आणि व्यवस्थापित केलेले स्टोरेज असते, ज्यामध्ये तुम्ही Docker च्या माध्यमातून प्रवेश करता.

दोन्ही प्रकार service मधील एकाच volumes: की (key) अंतर्गत येतात, त्यामुळे गोंधळ होऊ शकतो. फरक कोलनच्या (:) डाव्या बाजूला असतो. जर डावी बाजू . किंवा / ने सुरू होत असेल, तर तो होस्ट पाथ आहे, म्हणजेच तो bind mount आहे. इतर कोणतेही नाव असल्यास तो named volume असतो आणि अशा नावाचा उल्लेख टॉप-लेव्हल volumes: ब्लॉक मध्ये करणे आवश्यक असते.

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 हे एक named volume आहे. ./nginx.conf:/etc/nginx/nginx.conf हे एक bind mount आहे आणि :ro ते read-only मोडमध्ये माउंट करते, जे अशा कॉन्फिगरेशनसाठी योग्य डिफॉल्ट आहे जे कंटेनरने कधीही बदलू नये. जर तुम्ही टॉप-लेव्हल volumes: एन्ट्री विसरलात, तर Compose service "db" refers to undefined volume pgdata एररसह थांबते.

ते सुरू करा आणि Docker ने काय तयार केले आहे याची यादी पहा:

docker compose up -d
docker volume ls

या व्हॉल्यूमचे नाव pgdata नाही. त्याचे नाव <project>_pgdata आहे, जिथे प्रोजेक्टचे नाव हे डिफॉल्टनुसार त्या डिरेक्टरीचे नाव असते ज्यामध्ये compose फाईल असते. myapp नावाची डिरेक्टरी असल्यास myapp_pgdata हे नाव मिळते. हे महत्त्वाचे आहे कारण डिरेक्टरीचे नाव बदलल्यास तुम्हाला एक नवीन रिकामे व्हॉल्यूम मिळते आणि ॲप्लिकेशनचा डेटा गहाळ झाल्यासारखे वाटते. डेटा गहाळ झालेला नसतो: जुने व्हॉल्यूम अजूनही docker volume ls द्वारे सूचीबद्ध असते. जर डिरेक्टरी हलवण्याची शक्यता असेल, तर compose फाईलमध्ये name: वापरून नाव निश्चित करा किंवा COMPOSE_PROJECT_NAME सेट करा. अशा प्रकारच्या सेटिंग्ज तुमच्या इतर Compose environment files and secrets सोबत ठेवल्या पाहिजेत.

परमिशन त्रुटी फक्त bind mounts मध्येच का येतात

हा सर्वात मोठा व्यावहारिक फरक आहे आणि तो एका नियमावर आधारित आहे: पहिल्या वापराच्या वेळी रिकामे असलेले named volume हे इमेजमधून तयार केले जाते, तर bind mount कधीही तसे केले जात नाही.

जेव्हा Docker एखाद्या इमेजमध्ये आधीपासून आशय असलेल्या डिरेक्टरीवर रिकामे named volume mount करते, तेव्हा ते तो आशय व्हॉल्यूममध्ये कॉपी करते, ज्यामध्ये इमेजने सेट केलेली मालकी (ownership) आणि मोड्स (modes) असतात. अधिकृत Postgres इमेज /var/lib/postgresql/data सोबत येते, जी त्याच्या स्वतःच्या postgres वापरकर्त्याच्या मालकीची असते, त्यामुळे व्हॉल्यूम देखील त्याच अंकीय आयडीच्या (numeric id) मालकीचा होतो आणि डेटाबेस सुरू होतो.

Bind mount याच्या अगदी उलट काम करते. होस्टवर जे काही आहे तेच कंटेनरला दिसते, ज्यामध्ये मालकीचाही समावेश असतो आणि त्या मार्गावरील इमेजचा आशय लपवला जातो. जर होस्ट डिरेक्टरी अस्तित्वात नसेल, तर Docker daemon ती तयार करते आणि daemon हे root म्हणून चालत असल्याने, तुम्हाला root:root च्या मालकीची डिरेक्टरी मिळते. अशा वेळी, non-root वापरकर्ता म्हणून चालणारी कंटेनर प्रक्रिया त्यात लिहू शकत नाही:

PermissionError: [Errno 13] Permission denied: '/data/app.db'

यावर उपाय म्हणजे दोन्ही बाजूंचे अंक जुळवणे. Bind mount मधील मालकीची तुलना नावाने नाही, तर अंकीय वापरकर्ता आयडीने (numeric user id) केली जाते, कारण कंटेनरचा स्वतःचा /etc/passwd असतो. कंटेनरच्या आत असलेला app नावाचा वापरकर्ता होस्टवर काहीही अर्थ ठेवत नाही. Uid 1000 म्हणजे दोन्ही बाजूंना uid 1000 असा अर्थ होतो.

id -u
mkdir -p ./data
docker compose exec web id
sudo chown -R 1000:1000 ./data

docker compose exec web id हे कंटेनर प्रक्रिया प्रत्यक्षात कोणत्या uid वर चालते हे दर्शवते. होस्ट डिरेक्टरी त्या क्रमांकाशी जुळवा, किंवा सेवेमध्ये user: "1000:1000" वापरून कंटेनरला तुमच्या क्रमांकावर पिन करा. तुम्ही स्वतः लिहिलेल्या ॲप्लिकेशनसाठी user: पिन करणे अधिक सोयीचे असते. तुम्ही न लिहिलेल्या इमेजसाठी होस्ट डिरेक्टरीचे chown करणे अधिक सुरक्षित असते, कारण काही इमेजेस root म्हणून entrypoint सुरू करतात, नंतर अधिकार कमी (drop privileges) करतात आणि त्यांना विशिष्ट मालकीची अपेक्षा असते.

आणखी दोन गोष्टी लक्षात ठेवण्यासारख्या आहेत. Fedora, RHEL आणि SELinux (security-enhanced Linux) लागू असलेल्या इतर सिस्टिम्सवर, bind mount जोपर्यंत relabel केले जात नाही तोपर्यंत नाकारले जाते, म्हणून कंटेनरमध्ये शेअर केलेल्या मार्गासाठी :z जोडा किंवा फक्त एका कंटेनरने वापरायच्या मार्गासाठी :Z जोडा, जे - ./data:/data:Z म्हणून लिहिले जाते. तसेच, डिरेक्टरीऐवजी एका फाईलचे bind mount तेव्हा बिघडते जेव्हा एखादा एडिटर फाईलमध्ये बदल करण्याऐवजी ती फाईल बदलून (replace) टाकतो, कारण mount मूळ inode चे अनुसरण करते. जोपर्यंत तुम्ही कंटेनर रीस्टार्ट करत नाही, तोपर्यंत कंटेनरला जुनाच आशय दिसतो. जर फाईलमध्ये वारंवार बदल करायचे असतील, तर तिची parent डिरेक्टरी mount करा.

कार्यक्षमता: जिथे तफावत प्रत्यक्ष जाणवते

Linux सर्व्हरवर दोन्ही प्रकार एकाच कर्नल पाथवरून जातात, त्यामुळे थ्रूपुटमधील फरक इतका कमी असतो की त्या आधारावर निवड करणे आवश्यक नसते. डीफॉल्ट local ड्रायव्हर वापरणारे Named volumes हे Docker च्या उर्वरित फाईलसिस्टमवर, /var/lib/docker/volumes/ अंतर्गत राहतात, तर bind mount तुम्ही निर्देशित केलेल्या ठिकाणी असते.

ही तफावत macOS आणि Windows साठीच्या Docker Desktop वर दिसून येते, जिथे कंटेनर एका व्हर्च्युअल मशीनमध्ये चालतात. तिथे bind mount होस्ट फाईलसिस्टममधून फाईल शेअरिंग लेयरद्वारे व्हर्च्युअल मशीनमध्ये प्रवेश करते. अशा वेळी Node.js डिपेंडन्सी ट्री किंवा PHP फ्रेमवर्क कॅशेसारखी अनेक लहान फाईल ऑपरेशन्स असलेली वर्कलोड्स लक्षणीयरीत्या मंदावतात. Named volumes व्हर्च्युअल मशीनच्या आतच राहतात आणि त्यांना हा फटका बसत नाही. म्हणूनच अनेक डेव्हलपमेंट compose फाईल्स सोर्स डिरेक्टरीला bind-mount करतात, परंतु node_modules वर named volume घोषित करतात.

दुसरा महत्त्वाचा फरक म्हणजे डेटा कुठे साठवला जातो. /mnt/backup वर केलेली bind mount त्या डिस्कवर डेटा ठेवते. Named volume हे /var/lib/docker ज्या फाईलसिस्टमवर आहे तिथे साठवले जाते, जे VPS वर सहसा रूट डिस्क असते. Named volume मध्ये वाढणारा डेटाबेस तुमच्या सिस्टम लॉग्स असलेल्या डिस्कला पूर्णपणे भरू शकतो. कोणतीही समस्या उद्भवण्यापूर्वी ते तपासा:

docker system df -v
df -h /var/lib/docker

docker system df -v प्रत्येक व्हॉल्यूमची माहिती त्याच्या आकारासह दर्शवते आणि ज्या व्हॉल्यूम्सचा वापर आता कोणताही कंटेनर करत नाही, त्यांना चिन्हांकित करते.

Named volume तपासणे

Named volume हे काही गूढ नसते. Docker ला त्याचा मार्ग (path) विचारा:

docker volume inspect myapp_pgdata

Mountpoint फील्डमध्ये होस्टवरील प्रत्यक्ष मार्ग मिळतो, जो सामान्यतः /var/lib/docker/volumes/myapp_pgdata/_data असतो. तुम्ही sudo ls वापरून तो वाचू शकता, जे त्वरित तपासणीसाठी उपयुक्त ठरते. या मार्गाचा वापर फाईल्समध्ये बदल करण्यासाठी करू नका. root वापरकर्ता म्हणून तिथे काहीही लिहिल्यास वर नमूद केलेली मालकी हक्काची (ownership) समस्या पुन्हा उद्भवू शकते. तसेच, हा मार्ग केवळ local ड्रायव्हरचा तपशील आहे, जो इतर volume ड्रायव्हर्समध्ये नसतो.

व्हॉल्यूमच्या आत पाहण्याचा सुरक्षित मार्ग म्हणजे एक तात्पुरता (throwaway) कंटेनर वापरणे, जो तो व्हॉल्यूम माउंट करतो:

docker run --rm -v myapp_pgdata:/vol alpine ls -la /vol

हे कोणत्याही ड्रायव्हरसाठी काम करते, प्रत्यक्ष कंटेनरला दिसणारे परवानग्यांचे नियमच यालाही दिसतात आणि --rm मुळे मागे कोणतीही अनावश्यक फाईल शिल्लक राहत नाही.

प्रत्येक प्रकारचा बॅकअप घेणे

Bind mount ही एक सामान्य डिरेक्टरी असते, त्यामुळे कोणत्याही फाईल-लेव्हल बॅकअप टूलद्वारे ती सहज हाताळता येते. बॅकअप टूलला फक्त होस्ट पाथ (host path) निर्देशित करा आणि तुमचे काम पूर्ण होईल. Named volume साठी एक अतिरिक्त पायरी आवश्यक असते, कारण बॅकअप टूलला त्या व्हॉल्यूमच्या आत प्रवेश करावा लागतो. व्हॉल्यूम आणि एक होस्ट डिरेक्टरी एका अल्पकालीन कंटेनरमध्ये माउंट करा आणि त्यानंतर एक आर्काइव्ह तयार करा:

docker run --rm \
  -v myapp_pgdata:/data:ro \
  -v "$PWD":/backup \
  alpine tar czf /backup/pgdata.tar.gz -C /data .

हे उलट क्रियेने (reversing) नवीन व्हॉल्यूममध्ये रिस्टोर करा:

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 /data

tar हे कंटेनरमध्ये root म्हणून चालताना numeric ownership जपून ठेवते, ज्यामुळे रिस्टोर केलेला व्हॉल्यूम ॲप्लिकेशनसाठी वापरण्यायोग्य राहतो.

दोन्ही प्रकारांसाठी एक इशारा लागू होतो. डेटाबेस चालू असताना त्याच्या फाईल्स कॉपी केल्यास तुम्हाला एका 'moving target' चे आर्काइव्ह मिळेल, जे रिस्टोर करताना करप्ट (corrupt) होऊ शकते. त्यामुळे आधी सर्व्हिस थांबवा किंवा docker compose exec -T db pg_dump -U postgres appdb > appdb.sql मध्ये दर्शविल्याप्रमाणे डेटाबेसच्या स्वतःच्या टूलचा वापर करून डंप (dump) घ्या. यामुळे एक साधी फाईल तयार होईल, जी तुम्ही तुमच्या compose फाईल्ससोबत encrypted restic backup routine मध्ये समाविष्ट करू शकता.

bind mount चे named volume मध्ये स्थलांतर

ही प्रक्रिया म्हणजे कॉपी आहे, नाव बदलणे नव्हे, आणि याला साधारण एक मिनिट लागतो.

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 मुळे मालकी हक्क (ownership), मोड्स आणि टाइमस्टॅम्प जसेच्या तसे राहतात, त्यामुळे ज्या कंटेनर युजरला जुनी डिरेक्टरी वाचता येत होती, तोच युजर नवीन व्हॉल्यूमही वाचू शकतो. त्यानंतर सर्व्हिसमध्ये बदल करून pgdata:/var/lib/postgresql/data वापरा, टॉप-लेव्हल volumes: ब्लॉक मध्ये pgdata जोडा, docker compose up -d चालवा आणि जुनी डिरेक्टरी हटवण्यापूर्वी ॲप्लिकेशनचे लॉग्स तपासा. उलट प्रक्रियेसाठी याच कमांडमध्ये /from आणि /to ची अदलाबदल करा.

चाचणी करताना एक गोष्ट लक्षात ठेवा. docker compose down मुळे named volumes सुरक्षित राहतात, परंतु docker compose down -v मुळे प्रोजेक्टमध्ये घोषित केलेले सर्व named volumes हटवले जातात आणि ही कृती पूर्ववत करता येत नाही. bind mount दोन्ही प्रक्रियांमध्ये सुरक्षित राहते, कारण ती डिरेक्टरी Docker च्या मालकीची नसते. जर तुम्हाला लाइफसायकल कमांड्स नवीन असतील, तर VPS साठी Docker Compose मूलभूत मार्गदर्शक मध्ये त्या सविस्तर स्पष्ट केल्या आहेत.

सेवा-दर-सेवा निवड

फाईल कोण लिहित आहे हे तपासा. तुम्ही टेक्स्ट एडिटरमध्ये एडिट करता आणि git मध्ये कमिट करता ते कॉन्फिगरेशन bind mount मध्ये असावे, जे :ro वर माउंट केलेले असते, कारण तुम्हाला ते दृश्यमान आणि व्हर्जन केलेले हवे असते. ॲप्लिकेशन स्टेट, जी तुम्ही कधीही हाताने उघडत नाही, ती named volume मध्ये असावी, कारण Docker परवानग्या योग्यरित्या सेट करते आणि डेटा होस्ट पाथवर अवलंबून नसतो.

मिश्र स्थिती म्हणजे मीडिया. फोटो लायब्ररी ॲप्लिकेशनद्वारे लिहिली जाते पण ती तुम्ही व्यवस्थापित देखील करता, आणि ती बऱ्याचदा इतकी मोठी असते की त्यासाठी विशिष्ट डिस्कची गरज असते. तिला त्या डिस्कवरील एका पाथवर bind mount करा आणि मालकी हक्क (ownership) एकदाच जाणीवपूर्वक सेट करा. बहुतेक self-hosted स्टॅक्स याच पॅटर्नचा वापर करतात: डेटाबेस आणि कॅशेसाठी named volumes, आणि कॉन्फिगरेशन तसेच मोठ्या डिरेक्टरीसाठी bind mounts. VPS वर चालणारे Chatwoot सारखे सपोर्ट डेस्क याच रचनेवर आधारित असतात, जिथे Postgres एका named volume मध्ये असते आणि अपलोड केलेले अटॅचमेंट्स अशा पाथवर असतात जिथे तुम्ही बॅकअप घेऊ शकता.

FAQ

bind mount आणि named volume यामध्ये काय फरक आहे?

bind mount होस्टवरील एक पाथ कंटेनरमध्ये मॅप करते, ज्यामुळे दोन्ही बाजूंना तीच डिरेक्टरी दिसते आणि तुम्ही सामान्य टूल्स वापरून ती एडिट करू शकता. named volume हे Docker द्वारे तयार केलेले आणि व्यवस्थापित केलेले स्टोरेज आहे, ज्याला नावाने ओळखले जाते आणि ते टॉप-लेव्हल volumes: ब्लॉक मध्ये घोषित केले जाते. व्यावहारिक फरक मालकीचा आहे: तुम्ही मेंटेन करत असलेल्या कॉन्फिगरेशनसाठी bind mounts वापरा, आणि ॲप्लिकेशन मेंटेन करत असलेल्या डेटासाठी named volumes वापरा.

bind mount वापरताना "permission denied" एरर का येते, पण named volume मध्ये का येत नाही?

रिकामे named volume इमेजमधून तयार होते, त्यामुळे ते इमेजने सेट केलेली मालकी घेते आणि कंटेनर युजर त्यात लिहू शकतो. bind mount होस्ट डिरेक्टरी जशी आहे तशी दाखवते, आणि जर Docker ला ती डिरेक्टरी तयार करावी लागली, तर ती root च्या मालकीची बनते. कंटेनर कोणता numeric id वापरतो हे पाहण्यासाठी docker compose exec <service> id चालवा, त्यानंतर होस्ट डिरेक्टरीवर sudo chown -R <uid>:<gid> करा, किंवा सर्व्हिसवर user: "1000:1000" सेट करा.

Docker named volumes डिस्कवर कुठे साठवते?

डिफॉल्ट local ड्रायव्हरसह ते /var/lib/docker/volumes/<volume>/_data अंतर्गत राहतात आणि docker volume inspect <volume> अचूक Mountpoint प्रिंट करते. जर तुम्हाला काही तपासायचे असेल तर ते वाचा, परंतु फक्त कंटेनरद्वारेच त्यात लिहा, कारण होस्टवर root म्हणून एडिट केल्यास मालकी अशा प्रकारे बदलते जी कंटेनरला अपेक्षित नसते.

मी named volume चा बॅकअप कसा घेऊ शकतो?

व्हॉल्यूम आणि होस्ट डिरेक्टरी दोन्ही माउंट असलेला एक अल्पकालीन कंटेनर चालवा, त्यानंतर docker run --rm -v myvol:/data:ro -v "$PWD":/backup alpine tar czf /backup/myvol.tar.gz -C /data . वापरून एका ठिकाणाहून दुसऱ्या ठिकाणी आर्काइव्ह करा. डेटाबेससाठी, थेट फाईल्स कॉपी करण्याऐवजी डेटाबेसच्या स्वतःच्या टूलने डंप घ्या, कारण लिहिण्याची प्रक्रिया सुरू असताना घेतलेली फाईल कॉपी रिस्टोर करताना करप्ट होऊ शकते.

docker compose down केल्याने माझे व्हॉल्यूम्स डिलीट होतात का?

docker compose down कंटेनर आणि नेटवर्क्स काढून टाकते आणि named volumes तसेच ठेवते. docker compose down -v प्रोजेक्टमध्ये घोषित केलेले प्रत्येक named volume कायमस्वरूपी डिलीट करते. bind mounts कोणत्याही कमांडने काढले जात नाहीत, कारण ती डिरेक्टरी होस्टची असते, Docker ची नाही.