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.