5

I have an environment.yml in my applications folder

I have this in my dockerfile:

RUN conda env create
RUN source activate myenvfromymlfile

When I run the container though the env is not activated. If I do conda env list Is see /opt/conda is activated:

root@9c7181cf86aa:/app# conda env list
# conda environments:
#
myenvfromymlfile         /opt/conda/envs/myenvfromymlfile
root                  *  /opt/conda

If I attach to the container I can manually run source activate myenvfromymlfile and it works, but why doesn't that work in the RUN directive??

In examples, I see this often in dockerfiles that require conda:

CMD [ "source activate your-environment && exec python application.py" ]

Can someone explain why it is necessary to use && to make it a single command? And why running "source activate" in a RUN directive does not work? I want to have my dockerfile look like this:

RUN conda env create
RUN source activate myenvfromymlfile
ENTRYPOINT ["python"]
CMD ["application.py"]
red888
  • 27,709
  • 55
  • 204
  • 392
  • I'm not an expert on dockerfiles but I think what you're looking for is here: https://docs.docker.com/engine/userguide/eng-image/multistage-build/. see the paragraph titled, `Before multi-stage builds` – J'e Oct 11 '17 at 19:39
  • That doesn't have anything to do with my question. "source activate myenvfromymlfile" needs to be run as a single command with "python application.py" using && in order to work and I dont understand why – red888 Oct 11 '17 at 19:42
  • regarding the "&& to make it a single command", each layer add additional overhead and environment variables do not get passed between layers. – J'e Oct 11 '17 at 20:42
  • You can refer [here](https://stackoverflow.com/q/67059518/6503329) for a detailed explanation for the issue. – Shreyesh Desai Apr 12 '21 at 13:46

1 Answers1

5

Consider the below Dockerfile

RUN conda env create
RUN source activate myenvfromymlfile
ENTRYPOINT ["python"]
CMD ["application.py"]

Statement #1 conda env create. Create the environment and changes files on the disk.

Statement #2 source activate myenvfromymlfile. Loads some stuff in the bash sessions. No disk changes done here

Statement #3 and #4 specifies what happens when you run the container

ENTRYPOINT ["python"]
CMD ["application.py"]

So now when you run the container. Anything that you did in step#2 is not there, because a shell was launched to run step #2, when it completed the shell was closed. Now when you run the image a new shell is started and it is brand new shell with now no knowledge that in past inside your dockerfile you ran source activate myenvfromymlfile

Now you want to run this application.py in the environment you created. The default shell of docker is sh -c. So when you set CMD as below

CMD [ "source activate your-environment && exec python application.py" ]

The final command executed at start of container becomes

sh -c "source activate your-environment && exec python application.py"

Which activates the environment in current shell and then runs your program.

Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265
  • So that makes perfect sense, I thought it was the same session for ALL the run commands but I guess not! This kinda stinks though because I'd really like to have a generic image that can execute any python application you pass it (like you can do with an ENTRYPOINT of "python" and CMD of someApp.py). How can I make this conda container behave this way? – red888 Oct 11 '17 at 20:28
  • 1
    You need to make a shell script and use that as the ENTRYPOINT, so any CMD actually goes as parameter to the shell script and then in the script you can do whatever you want – Tarun Lalwani Oct 11 '17 at 20:51