How to get pipenv running in docker?
Considering your problem, as I know it the easiest way is to update to the latest version of pipenv
. It is still in development, so problems are fixed very soon.
We are using pipenv
with docker
in production. And we really like it.
There are several things to keep in mind:
- You need to use
--system
flag, so it will install all packages into the system python, and not into thevirtualenv
. Sincedocker
containers do not need to havevirtualenv
s - You need to use
--deploy
flag, so your build will fail if yourPipfile.lock
is out of date - You need to use
--ignore-pipfile
, so it won't mess with our setup
Check the official docs to be sure that this information is up-to-date.
All in all:
pipenv install --system --deploy --ignore-pipfile
There's also one more thing. If you are using the same Dockerfile
for both development and production it would be very nice to also use --dev
flag for the development environment only.
Also, check out our django
project template to see the full example: wemake-django-template
The pipenv documentation no longer officially recommends using the --system
flag in docker instances. Instead, they suggest using virtual environments, as "it is for deployment onto a full-fledged OS". This is with the caveat:
...most containers are deployed without virtualenvs as I believe you both note, I believe the purpose is to stay slim and reduce attack surface area by installing as little as possible
As stated in https://github.com/pypa/pipenv/pull/2762.
Instead, the solution would be to run (as stated in a different answer here):
RUN pipenv install --deploy --ignore-pipfile
And then prefix all calls to python with pipenv run
, e.g. CMD ["pipenv", "run", "python", "hello.py"]
Ps. I would have wanted to put this as a comment to the accepted answer, but I don't have the reputation.
The direct answer to this question is to not use shell
, but rather run
:
CMD ["pipenv", "run", "python", "my/app.py"]
If you need more flexibility, you could also pipenv run sh init.sh
, which would create a shell initialized with all the pipenv
environment variables.
I actually prefer the approach C. Sweet mentions. If you can get away with prebuilding your virtual environment and simply copying it over (setting PIPENV_VENV_IN_PROJECT
then using a nested FROM
followed by COPY --from=builder-image
), you don't need python
nor pipenv
nor pipenv
dependencies in your final container. This greatly reduces the size of the final image.
Dockerfile
:
WORKDIR /etc/service/
CMD ["sh", "/etc/service/init.sh"]
init.sh
:
source /etc/service/my/.venv/bin/activate
python my/app.py