Reputation: 761
I have a python package I have installed and modified to my needs stored in a venv folder. I thought using:
RUN source venv/bin/activate
in my Dockerfile (after copying it into the container of course) would solve my problems but the comments to this answer revealed that it doesn't. Afterwards, I came across this article that shows how to set up a new venv inside a docker container but doesn't answer my question. Many other answers sent me on a neverending wild chase so I decided to ask here. Hopefully a good answer will solve my problem and serve those who will face this problem in the future for custom python packages in docker containers.
My question:
How to use a venv copied into a docker container?
Upvotes: 6
Views: 10249
Reputation: 160051
In general you can't copy virtual environments anywhere, Docker or otherwise. They tend to be tied to a very specific filesystem path and a pretty specific Python installation. If you knew you had the exact same Python binary, and you copied it to the exact same filesystem path, you could probably COPY it in as-is, but the build system would be extremely fragile.
It's also the case that you usually don't need virtual environments in Docker. A Docker image provides the same sort of isolated Python installation that you'd use a virtual environment for in a non-Docker context. If you'd ordinarily set up a virtual environment by running
python3 -m venv vpy
. vpy/bin/activate
pip install -r requirements.txt
then you can get an equivalent installation with a Dockerfile like
FROM python:3
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
In comments you hint at hand-modifying installed packages. This isn't usually a best practice (what if there's a critical security update in a package you've changed? what if your colleague needs to work on your project but not on your computer?). You can use a tool like diff(1) to make a patch file describing what's changed, comparing your modified file with the original. If you have that, then you can do something like
COPY local.patch /app/
RUN cd $(python3 -c 'import sysconfig; print(sysconfig.get_path("platlib"))') \
&& patch -p0 < /app/local.patch
It's important to note that each RUN command starts a new shell in a new container. So the cd
command in this last example only affects this RUN command and nothing later. In your proposed RUN source ...
command, the environment variables set by this will be lost at the end of that RUN command. (Also note that source
is not a standard shell command and won't work on, for instance, Alpine-based images, but .
is equivalent and is standard.)
Upvotes: 4