2025, Oct 16 04:32

Docker में bind mount है, फिर भी .env क्यों नहीं मिलती: WORKDIR mismatch का हल

Windows पर सब ठीक, पर कंटेनर में .env गायब? वजह bind mount नहीं, WORKDIR और relative path का mismatch. दो समाधान: mounts बदलें या WORKDIR /app करें. अभी पढ़ें

Docker bind mount मौजूद है, फिर भी Python फाइलें नहीं देख पा रहा है। एप्लिकेशन Windows पर ठीक चलता है, लेकिन कंटेनर के अंदर यह .env और tg_token.env के लिए “missing” त्रुटि देता है। Docker Desktop में माउंट्स सही दिखते हैं, फिर भी कोड उन्हें पढ़ नहीं पाता। असली वजह न तो permissions हैं, न ही फाइलों का गायब होना; समस्या working directory और mount path के मेल न खाने की है।

समस्या का प्रदर्शन

एप्लिकेशन relative resources डायरेक्टरी में .env फाइलें ढूंढता है और उनके न मिलने पर बंद हो जाता है।

env_file_path = "resources/.env"
if os.path.exists(env_file_path):
    load_dotenv(env_file_path)
else:
    raise ResourcesMissing('.env missing')
token_env_path = "resources/tg_token.env"
if os.path.exists(token_env_path):
    load_dotenv(token_env_path)
else:
    raise ResourcesMissing('tg_token.env missing')

कंटेनर को निम्न कॉन्फ़िगरेशन के साथ बनाया और चलाया जाता है।

# docker-compose.yml
services:
  bot:
    build: .
    volumes:
      - ./media:/app/media:ro
      - ./resources:/app/resources:rw
# Dockerfile
FROM python:3.13.5-slim
WORKDIR /usr/src/app
ENV CONTAINER=docker
RUN mkdir -p /app/media
RUN mkdir -p /app/resources
RUN apt-get update
RUN pip install --upgrade pip
COPY . .
# [निर्भरताएँ स्थापित करना]
CMD ["python", "bot.py"]

इसके अलावा, build context होस्ट-साइड की payload डायरेक्टरीज़ को अनदेखा करता है:

# .dockerignore
media/*
resources/*

असल में टूट क्या रहा है

प्रोग्राम /usr/src/app में चलता है क्योंकि Dockerfile में WORKDIR यही सेट है। इसलिए resources/.env जैसे relative path /usr/src/app के संदर्भ में सुलझते हैं; यानी कोड /usr/src/app/resources/.env और /usr/src/app/resources/tg_token.env ढूंढ रहा होता है।

लेकिन docker-compose.yml में bind mounts होस्ट की डायरेक्टरीज़ को /app के नीचे लगाते हैं (खासकर /app/resources और /app/media)। नतीजा: एक तरह का दो हिस्सों में बँटा लेआउट—ऐप /usr/src/app से चल रहा है, जबकि माउंट किया हुआ डेटा /app में है। एप्लिकेशन के नजरिए से resources/.env मौजूद ही नहीं है; यही वजह है कि Docker Desktop में माउंट्स दिखाई देने के बावजूद missing-file exception उठती है।

अगर आप यह दोबारा परखना चाहें कि ऐप किस directory को current working directory मान रहा है, तो runtime पर इसे प्रिंट करें:

print(os.getcwd())

इसे कैसे ठीक करें

इसे सही करने के दो सीधे तरीके हैं। या तो mounts को /usr/src/app के नीचे ले आएँ ताकि वे मौजूदा WORKDIR से मेल खाएँ, या WORKDIR को /app कर दें ताकि वह पहले से इस्तेमाल हो रहे mounts से मैच हो जाए।

विकल्प A. WORKDIR को /usr/src/app ही रखें और bind mounts ऐसे अपडेट करें कि resources और media वहीं दिखें जहाँ ऐप वास्तव में चलता है।

# docker-compose.yml (सुधारे गए माउंट्स)
services:
  bot:
    build: .
    volumes:
      - ./media:/usr/src/app/media:ro
      - ./resources:/usr/src/app/resources:rw

विकल्प B. mounts जस के तस रखें और एप्लिकेशन की working directory को /app कर दें। इससे runtime CWD bind‑mount targets के साथ संरेखित हो जाएगा जो पहले से docker-compose.yml में इस्तेमाल हो रहे हैं।

# Dockerfile (WORKDIR ठीक किया गया)
FROM python:3.13.5-slim
WORKDIR /app
ENV CONTAINER=docker
RUN mkdir -p /app/media
RUN mkdir -p /app/resources
RUN apt-get update
RUN pip install --upgrade pip
COPY . .
# [निर्भरताएँ स्थापित करना]
CMD ["python", "bot.py"]

इनमें से किसी भी तरीके से path mismatch खत्म हो जाता है, और resources/.env तथा resources/tg_token.env वही relative path इस्तेमाल करके उपलब्ध हो जाती हैं, जिन्हें आपका Python कोड पहले से प्रयोग करता है।

यह क्यों मायने रखता है

Relative path उस process की current working directory के संदर्भ में सुलझते हैं। Docker में WORKDIR यही संदर्भ build और runtime पर तय करता है। अगर आपका runtime WORKDIR और bind-mount के लक्ष्य मेल नहीं खाते, तो relative path इस्तेमाल करने वाला कोड उन फाइलों को “खो” देता है जो वास्तव में सही तरह से माउंट हुई होती हैं। अक्सर यह आपके अपने missing-file exception के रूप में सामने आता है, न कि mount या permission error के रूप में—और सिर्फ कंटेनर के file browser को देखकर बात साफ नहीं होती।

निष्कर्ष

working directory और bind mounts को एक जैसा रखें। या तो resources और media को /usr/src/app में माउंट करें, या WORKDIR को /app सेट करें ताकि current directory /app/resources के साथ लाइन में आ जाए। आगे कभी ऐसा संदेह हो तो current directory प्रिंट करें और देखें कि volumes कहाँ माउंट हैं। इन्हें sync में रखने से “file not found” जैसी उलझनें खत्म होती हैं और आपका Python कोड व Docker कॉन्फ़िगरेशन सादा व भरोसेमंद रहता है।

यह लेख StackOverflow के एक प्रश्न (लेखक: Eji Sarmat) और J Earls के उत्तर पर आधारित है।