0

I see most tutorials/online sources advice using either source or . (a bash built-in) to activate a python venv. For example, this page suggests to do the following in Linux:

cd ~/<proj_name>

. bin/activate

(whereas in Windows, it's just cd\<proj_name> and activate)

But I need to activate a venv inside a docker/Dockerfile, and bash may not be available (e.g. with podman OCI images). As underlying distros such as Debian-based ones adopt PEP 668, pip commands without the venv in old Dockerfiles cause an error that "This environment is externally managed". The suggested way now seems to be use venv.

Considering the fact that source is specific to certain shells, my questions are:

Is it always necessary to use source to activate a venv in Linux?

If so, why and what's the proper way to activate venv in a general non-bash shell?

In particular, what's the proper way to use venv on pip commands in generic Dockerfiles?

2
  • Any POSIX compliant shell should understand . - the source bash shell builtin is just a non-portable synonym Jun 15, 2023 at 15:35
  • Also, there's not much sense to making a virtual env in a Docker container. The container itself is a virtual env of sorts.
    – muru
    Jun 15, 2023 at 17:04

1 Answer 1

2

bin/activate is to be sourced (with ., though some shells also support the csh source as an alias) by any Bourne-like shell (the sh or any system since the late 70s and all of ash, dash, busybox sh (ash or mush), ksh, pdksh, mksh, oksh, bosh, yash, zsh...), it is not in any way bash-specific.

There's also a bin/activate.csh for csh or tcsh shells, and a bin/activate.fish for the fish shell.

If you use any other shell you're on your own, but that shouldn't be too difficult to adapt as it's just a matter of defining or updating the VIRTUAL_ENV, PYTHONHOME and PATH environment variables.

Or you could always re-execute your shell from within a sh instead where the bin/activate has been sourced. For instance, from the rc shell or derivative which don't seem to be supported by python-venv:

exec sh -c '. /path/to/bin/activate && exec rc'

Would re-exec rc with the environment updated by sh.

In any case, your container will likely have a /bin/sh that is Bourne-like whether that's busybox, mksh or bash.

And to run some command in that container that uses that virtual env, similarly to the above, you'd run:

sh -c '. /path/to/venv/bin/active && exec "$0" "$@"' python3 /path/to/whatever.py

That's assuming you need to have different virtual envs in a single container for some reason. Most likely you'd be able to use different containers with different sets or python modules or versions of python instead, bearing in mind that containers are some form of virtualisation already.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .