简体   繁体   中英

dotenv won't load in docker container

I'm trying to run a python app in a docker container. The python app takes it's secrets from a .env file and uses dotenv.load_dotenv in python to pull the secrets in. Works absolutely fine when I run locally.. so I assumed it HAD to be to do with the version of Python running on the base image, however.. I've tried it with the exact same version as I'm running locally and it's still failing.

Docker file:

FROM python:latest
WORKDIR /casp
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . /casp
ENTRYPOINT [ "python3" ]
CMD [ "main.py" ]

In my python app:

from pathlib import Path
from dotenv import load_dotenv

env_path = Path('.') / '.env'
load_dotenv(dotenv_path=env_path)

I actually tried abandoning this idea completely, and reverting to passing the environment variables in using docker run -e but, it turns out Flask relies on dot_env also, and as such it fails there also.

I've done a fair amount of looking already and it seems a lot of people do have Docker / Dotenv issues, but none seem to directly match this.

Previous posts suggest it could be related to the location, but the path here is literally just ./env which matches the container, since the WORKDIR is created then the entire app directory is copied into it, which includes .env and main.py .

Error I'm seeing is:

ImportError: cannot import name 'load_dotenv' from 'dotenv' (/usr/local/lib/python3.9/site-packages/dotenv/__init__.py)

Current test is using Python 3.9 . Locally I'm running Python 3.85 - I have tried changing the Dockerfile to match this version... same error.

EDIT:

(venv) root@jon-Blade:/home/jon/PycharmProjects/caspv2# pip freeze | grep dotenv
python-dotenv==0.14.0
(venv) root@jon-Blade:/home/jon/PycharmProjects/caspv2# grep dotenv requirements.txt 
python-dotenv==0.14.0

EDIT EDIT:

root@jon-Blade:~# docker exec 2ce1ff67d74f pip list | grep dotenv
python-dotenv  0.14.0

EDIT EDIT EDIT:

From within the container :

>>> import dotenv
>>> dir(dotenv)
['__author__', '__builtins__', '__cached__', '__doc__', '__email__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', '_get_line_', 'ast', 'get', 'load', 'os', 'save']

From within the venv in my terminal :

>>> import dotenv
>>> dir(dotenv)
['IS_TYPE_CHECKING', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'compat', 'dotenv_values', 'find_dotenv', 'get_cli_string', 'get_key', 'load_dotenv', 'load_ipython_extension', 'main', 'parser', 'set_key', 'unset_key']

As we can see, in the container it's load and in the terminal it's load_dotenv . More importantly, it's different! Using the exact same version in requirements.txt

Terminal:

(venv) jon@jon-Blade:~/PycharmProjects/caspv2$ pip freeze | grep dotenv
python-dotenv==0.14.0

Container:

root@2476f65ffa10:/casp# pip freeze | grep dotenv
python-dotenv==0.14.0

Version from Terminal :

(venv) jon@jon-Blade:~/PycharmProjects/caspv2$ python --version
Python 3.8.5

Version from Container :

root@3aa5c393846e:~# python --version
Python 3.8.5

Running pip show python-dotenv on both also confirms the exact same details, line for line!

This is certainly a fun one, it's confusing... but there has to be something funny going on.

EDIT EDIT EDIT EDIT :)

In the container I upgraded python-dotenv to 0.15.0 :

root@8a94c1e22b8a:~# pip show python-dotenv | grep -i version
Version: 0.15.0

However:

>>> import dotenv
>>> dir(dotenv)
['__author__', '__builtins__', '__cached__', '__doc__', '__email__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', '_get_line_', 'ast', 'get', 'load', 'os', 'save']

It's still giving me the wrong package.

Is dotenv in your requirement.txt with a version? I would have left a comment under the question but I'm unable to need more rep

python-dotenv==0.15.0

Update: Looking at your dir(dotenv) you should see it's not giving you the right package so firstly update your python-dotenv to 0.15.0 in your requirement.txt like I've shown above. Then update

FROM python:3.8.5
ENV VIRTUAL_ENV=/opt/venv
RUN python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"

# Install dependencies:
WORKDIR /casp
COPY requirements.txt /casp/
RUN pip install -r /casp/requirements.txt

# Run the application:
COPY . /casp /casp
CMD ["python3", "main.py"]

The Main problem is your container isn't accessing python-dotenv even though you are installing it. If this doesn't work either docker destroy and rebuild your container. I've done this locally and I have a working docker container. If it speeds up your development you could add your ENV variables this way.

ENV ADMIN="jack"

You can access it using

import os
admin_name = os.environ['ADMIN']

Well, I'm not sure how much of an answer this is.. but I've just got it working.

If I install python-dotenv by using the upgrade switch, it shows the correct results from dir(dotenv)

My workaround for this was to remove python-dotenv from requirements.txt and then add another line in my Dockerfile :

RUN pip install -r requirements.txt
RUN pip install -U python-dotenv

It now works and the app runs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM