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.