5

I am trying to build an image using dockerfile. The commands in the dockerfile looks something like these:

FROM ubuntu:16.04
:
:
RUN pip3 install virtualenvwrapper  
RUN echo '# Python virtual environment wrapper' >> ~/.bashrc
RUN echo 'export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3' >> ~/.bashrc
RUN echo 'export WORKON_HOME=$HOME/.virtualenvs' >> ~/.bashrc
RUN echo 'source /usr/local/bin/virtualenvwrapper.sh' >> ~/.bashrc

After these commands, I will use virtualenvwrapper commands to make some virtualenvs.

If I had only environment variables to deal with in ~/.bashrc, I would have used ARG or ENV to set them up.

But now I also have other shell script files like virtualenvwrapper.sh the will be setting some of their own variables.

Also, RUN source ~/.bashrc is not working (source not found).

What should I do?

scipsycho
  • 527
  • 2
  • 4
  • 13

3 Answers3

3

You shouldn't try to edit shell dotfiles like .bash_profile in a Dockerfile. There are many common paths that don't go via a shell (e.g., CMD ["python", "myapp.py"] won't launch any sort of shell and won't read a .bash_profile). If you need to globally set an environment variable in an image, use the Dockerfile ENV directive.

For a Python application, you should just install your application into the image's "global" Python using pip install. You don't specifically need a virtual environment; Docker provides a lot of the same isolation capabilities (something you pip install in a Dockerfile won't affect your host system's globally installed packages).

A typical Python application Dockerfile (copied from https://hub.docker.com/_/python/) might look like

FROM python:3
WORKDIR /usr/src/app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "./your-daemon-or-script.py"]

On your last question, source is a vendor extension that only some shells provide; the POSIX standard doesn't require it and the default /bin/sh in Debian and Ubuntu doesn't provide it. In any case since environment variables get reset on every RUN command, RUN source ... (or more portably RUN . ...) is a no-op if nothing else happens in that RUN line.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • You are saying that the environment variables get reset with every `RUN..` Does that use the `~/.bashrc` file to set their variables. In that case I might not need to use source anyways right? – scipsycho Sep 26 '18 at 05:24
  • Even if `/bin/sh` happens to be bash, running `sh -c ...` (which is what RUN usually does) [doesn't read any dotfiles](https://www.gnu.org/software/bash/manual/bash.html#Bash-Startup-Files). – David Maze Sep 26 '18 at 10:27
  • so, there is no way except ENV to set environment variables in /bin/sh . But ENV will only set just one variable at a time, or can I attach a script file to it for setting the environment variables? – scipsycho Sep 26 '18 at 15:29
0
  1. avoid using ~ => put your bashrc in a specific path
  2. put source bashrc and your command on the same RUN line with ;

the RUN lines are totally independent from each others for the environment

Eric
  • 517
  • 2
  • 7
  • I used `RUN echo 'source /usr/local/bin/virtualenvwrapper.sh' >> bashForIndy. RUN source bashForIndy; mkvirtualenv dharmesh`. It says **/bin/sh: 1: source: not found /bin/sh: 1: mkvirtualenv: not found** – scipsycho Sep 25 '18 at 08:55
  • Needs to be `.`, not `source`, for compatibility with `/bin/sh`. That is to say: `. ~/.bashrc` (assuming the file is otherwise written for compatibility with baseline-POSIX shells) – Charles Duffy Mar 10 '19 at 17:58
  • 1
    Alternately, one can `RUN ["/bin/bash", "-c", "source ~/.bashrc; mkvirtualenv dharmesh"]` to explicitly specify bash. – Charles Duffy Mar 10 '19 at 18:00
0

It may be easier to do this from the command line, and avoid messing with the dockerfile entirely. Simply use the -l or --login option to force the shell opened in the Docker image to be a login variant, which will source /etc/profile and the first of the files ~/.bash_profile, ~/.bash_login, or ~/.profile that is found.

docker run -it --rm docker_image /bin/bash -l

Spokes
  • 59
  • 1
  • 3