How to get pipenv running in docker?
DockerPipenvDocker Problem Overview
Im installing pipenv in my docker:
RUN pip install pipenv
RUN cd /my/app/path/ && pipenv install
RUN cd /my/app/path/ && pipenv shell
Im getting the error:
Traceback (most recent call last):
File "/usr/local/bin/pipenv", line 11, in <module>
sys.exit(cli())
File "/usr/local/lib/python2.7/dist-packages/pipenv/vendor/click/core.py", line 722, in __call__
return self.main(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/pipenv/vendor/click/core.py", line 697, in main
rv = self.invoke(ctx)
File "/usr/local/lib/python2.7/dist-packages/pipenv/vendor/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/local/lib/python2.7/dist-packages/pipenv/vendor/click/core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/local/lib/python2.7/dist-packages/pipenv/vendor/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/pipenv/cli.py", line 2057, in shell
do_shell(three=three, python=python, fancy=fancy, shell_args=shell_args)
File "/usr/local/lib/python2.7/dist-packages/pipenv/cli.py", line 1952, in do_shell
shell = os.path.abspath(PIPENV_SHELL)
File "/usr/lib/python2.7/posixpath.py", line 360, in abspath
if not isabs(path):
File "/usr/lib/python2.7/posixpath.py", line 54, in isabs
return s.startswith('/')
AttributeError: 'NoneType' object has no attribute 'startswith'
If I run
RUN cd /my/app/path/ && pipenv install --system
instead, im getting another error:
build 30-Sep-2017 16:50:45 Step 5/9 : RUN cd /my/app/path && pipenv install --system
build 30-Sep-2017 16:50:45 ---> Running in cffd31633074
build 30-Sep-2017 16:50:46 [91mPipfile.lock not found, creating…
build 30-Sep-2017 16:50:46 [0m[91mLocking [dev-packages] dependencies…
build 30-Sep-2017 16:50:46 [0m[91mLocking [packages] dependencies…
build 30-Sep-2017 16:50:49 [0m[91mCRITICAL:pip.utils:Error [Errno 2] No such file or directory while executing command python setup.py egg_info
build 30-Sep-2017 16:50:49 [0m[91mTraceback (most recent call last):
build 30-Sep-2017 16:50:49 File "/usr/local/bin/pipenv", line 11, in <module>
build 30-Sep-2017 16:50:49 sys.exit(cli())
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/vendor/click/core.py", line 722, in __call__
build 30-Sep-2017 16:50:49 [0m[91m return self.main(*args, **kwargs)
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/vendor/click/core.py", line 697, in main
build 30-Sep-2017 16:50:49 [0m[91m rv = self.invoke(ctx)
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/vendor/click/core.py", line 1066, in invoke
build 30-Sep-2017 16:50:49 [0m[91m return _process_result(sub_ctx.command.invoke(sub_ctx))
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/vendor/click/core.py", line 895, in invoke
build 30-Sep-2017 16:50:49 [0m[91m return ctx.invoke(self.callback, **ctx.params)
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/vendor/click/core.py", line 535, in invoke
build 30-Sep-2017 16:50:49 return callback(*args, **kwargs)
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/cli.py", line 1782, in install
build 30-Sep-2017 16:50:49 [0m[91m do_init(dev=dev, allow_global=system, ignore_pipfile=ignore_pipfile, system=system, skip_lock=skip_lock, verbose=verbose, concurrent=concurrent, deploy=deploy)
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/cli.py", line 1290, in do_init
build 30-Sep-2017 16:50:49 [0m[91m do_lock(system=system)
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/cli.py", line 1080, in do_lock
build 30-Sep-2017 16:50:49 [0m[91m pre=pre
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/utils.py", line 421, in resolve_deps
build 30-Sep-2017 16:50:49 [0m[91m resolved_tree.update(resolver.resolve())
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/patched/piptools/resolver.py", line 101, in resolve
build 30-Sep-2017 16:50:49 [0m[91m has_changed, best_matches = self._resolve_one_round()
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/patched/piptools/resolver.py", line 199, in _resolve_one_round
build 30-Sep-2017 16:50:49 [0m[91m for dep in self._iter_dependencies(best_match):
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/patched/piptools/resolver.py", line 293, in _iter_dependencies
build 30-Sep-2017 16:50:49 dependencies = self.repository.get_dependencies(ireq)
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/patched/piptools/repositories/pypi.py", line 171, in get_dependencies
build 30-Sep-2017 16:50:49 result = reqset._prepare_file(self.finder, ireq)
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/patched/pip/req/req_set.py", line 639, in _prepare_file
build 30-Sep-2017 16:50:49 [0m[91m abstract_dist.prep_for_dist()
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/patched/pip/req/req_set.py", line 134, in prep_for_dist
build 30-Sep-2017 16:50:49 [0m[91m self.req_to_install.run_egg_info()
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/patched/pip/req/req_install.py", line 438, in run_egg_info
build 30-Sep-2017 16:50:49 [0m[91m command_desc='python setup.py egg_info')
build 30-Sep-2017 16:50:49 File "/usr/local/lib/python2.7/dist-packages/pipenv/patched/pip/utils/__init__.py", line 667, in call_subprocess
build 30-Sep-2017 16:50:49 [0m[91m cwd=cwd, env=env)
build 30-Sep-2017 16:50:49 File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
build 30-Sep-2017 16:50:49 [0m[91m errread, errwrite)
build 30-Sep-2017 16:50:49 File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child
build 30-Sep-2017 16:50:49 [0m[91m raise child_exception
build 30-Sep-2017 16:50:49 OSError: [Errno 2] No such file or directory
error 30-Sep-2017 16:50:49 The command '/bin/sh -c cd /opt/supercrunch/function-service/lib && pipenv install --system' returned a non-zero code: 1
build 30-Sep-2017 16:50:49 [0mSending build context to Docker daemon 40.96 kB
But when I instead do the following:
RUN pip install pipenv
RUN cd /my/app/path && pipenv install
RUN cd /my/app/path && pipenv install --system
It is working...
So two question: First: Why is pipenv shell
giving me this error and Second: Why do I have to do pipenv install
before pipenv install --system
to get it working?
I would like to use pipenv to create virtual environments with different python versions and differne dependency versions.
Docker Solutions
Solution 1 - 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
Solution 2 - Docker
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.
Solution 3 - Docker
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
Solution 4 - Docker
Following alternative turned out to be the best for me:
RUN pip install pipenv \
&& pipenv lock --keep-outdated --requirements > requirements.txt \
&& pip install -r requirements.txt
Since this does not install the dependencies in pipenv'a virtualenv, no need to worry about pipenv in docker-compose command.
command: >
- sh
- -c
- |
python myscript.py
python myapp.py
Following reference helped me, includes poetry,pip-tools Reference P.S. I am not the author
Solution 5 - Docker
The best thing is not to use pipenv directly, as you usually don't need a virtualenv in your container.
There is a tool called micropipenv that you can use in your container instead of pipenv.
https://github.com/thoth-station/micropipenv
micropipenv use cases
Why should I use micropipenv
instead of Pipenv
or Poetry
?
-
I would like to have a tool that "rules them all" - one lightweight tool to support all Python dependency lock file managers (pip-tools, Poetry, Pipenv) and lets users decide what they want to use when deploying Python applications in containerized environments (e.g. Kubernetes, OpenShift, ...).
-
I would like to have a fast and minimalistic tool to install software packages in CI.
-
I would like to have containerized Python applications as small as possible with minimum software shipped and required to build and run the Python application in production.
-
I would like to convert files produced by Pipenv/Poetry to a pip-tools compatible output.
-
I don't want to install Pipenv/Poetry, but I would like to run a project that uses Pipenv/Poetry for dependency management (e.g. restricted environments).
-
My Pipenv installation is broken and
Pipenv upstream did not issue any new Pipenv release <https://github.com/pypa/pipenv/issues/4058>
_. -
I would like to deploy my application into a production environment and my application dependencies are managed by Pipenv/Poetry (dependencies are already resolved), but I don't want to run Pipenv/Poetry in production (e.g. OpenShift's s2i build process).