7

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.

1
  • Updated my Answer hope it helps Commented Oct 29, 2020 at 23:17

2 Answers 2

3

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'] 
Sign up to request clarification or add additional context in comments.

8 Comments

Yes, I populated requirements.txt with pip freeze > requirements.txt from a working venv. I see it install also when the image is built.
Your error is suggesting that the load_dotenv isn’t in your dotenv library you are installing share your requirement’s.txt in the question please. Also run docker exec <container ID> pip list In the cmd line
You wan’t to check with the ‘docker exec {container ID} pip list’ you don’t have dotenv and python-dotenv @jonnybinthemix
I've added the requirements info into the question. The container won't, so I'll remove the entrypoint and then check pip list without the program running, since it causes the container to fail to start.
I've added the output of docker exec {container ID} pip list to the bottom of the question.
|
2

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.