I\'m creating an image that has a similar problem like the following docker project:
FROM alpine:3.9.3
COPY ./env.sh /env.sh
RUN source
Each Dockerfile RUN step runs a new container and a new shell. If you try to set an environment variable in one shell, it will not be visible later on. For example, you might experiment with this Dockerfile:
FROM busybox
ENV FOO=foo1
RUN export FOO=foo2
RUN export BAR=bar
CMD echo FOO is $FOO, BAR is $BAR
# Prints "FOO is foo1, BAR is "
There are three good solutions to this. In order from easiest/best to hardest/most complex:
Avoid needing the environment variables at all. Install software into “system” locations like /usr; it will be isolated inside the Docker image anyways. (Don’t use an additional isolation tool like Python virtual environments, or a version manager like nvm or rvm; just install the specific thing you need.)
Use ENV. This will work:
FROM busybox
ENV FOO=foo2
ENV BAR=bar
CMD echo FOO is $FOO, BAR is $BAR
# Prints "FOO is foo2, BAR is bar"
Use an entrypoint script. This typically looks like:
#!/bin/sh
# Read in the file of environment settings
. /opt/wherever/env
# Then run the CMD
exec "$@"
COPY this script into your Dockerfile. Make it be the ENTRYPOINT; make the CMD be the thing you’re actually running.
FROM busybox
WORKDIR /app
COPY entrypoint.sh .
COPY more_stuff .
ENTRYPOINT ["/app/entrypoint.sh"]
CMD ["/app/more_stuff/my_app"]
If you care about such things, environment variables you set via this approach won’t be visible in docker inspect or a docker exec debug shell; but if you docker run -it ... sh they will be visible. This is a useful and important enough pattern that I almost always use CMD in my Dockerfiles unless I’m specifically trying to do first-time setup like this.