Can we pass ENV variables through cmd line while building a docker image through dockerfile?

86,981

Solution 1

Containers can be built using build arguments (in Docker 1.9+) which work like environment variables.

Here is the method:

FROM php:7.0-fpm
ARG APP_ENV=local
ENV APP_ENV ${APP_ENV}
RUN cd /usr/local/etc/php && ln -sf php.ini-${APP_ENV} php.ini

and then build a production container:

docker build --build-arg APP_ENV=prod .

For your particular problem:

FROM debian
ENV http_proxy ${http_proxy}

and then run:

docker build --build-arg http_proxy=10.11.24.31 .

Note that if you build your containers with docker-compose, you can specify these build-args in the docker-compose.yml file, but not on the command-line. However, you can use variable substitution in the docker-compose.yml file, which uses environment variables.

Solution 2

So I had to hunt this down by trial and error as many people explain that you can pass ARG -> ENV but it doesn't always work as it highly matters whether the ARG is defined before or after the FROM tag.

The below example should explain this clearly. My main problem originally was that all of my ARGS were defined prior to FROM which resulted all the ENV to be undefined always.

# ARGS PRIOR TO FROM TAG ARE AVAIL ONLY TO FROM for dynamic a FROM tag
ARG NODE_VERSION
FROM node:${NODE_VERSION}-alpine

# ARGS POST FROM can bond/link args to env to make the containers environment dynamic
ARG NPM_AUTH_TOKEN
ARG EMAIL
ARG NPM_REPO

ENV NPM_AUTH_TOKEN ${NPM_AUTH_TOKEN}
ENV EMAIL ${EMAIL}
ENV NPM_REPO ${NPM_REPO}

# for good measure, what do we really have
RUN echo NPM_AUTH_TOKEN: $NPM_AUTH_TOKEN && \
  echo EMAIL: $EMAIL && \
  echo NPM_REPO: $NPM_REPO && \
  echo $HI_5
# remember to change HI_5 every build to break `docker build`'s cache if you want to debug the stdout

..... # rest of whatever you want RUN, CMD, ENTRYPOINT etc..

Solution 3

I faced the same situation.

According to Sin30's answer pretty solution is using shell,

CMD ["sh", "-c", "cd /usr/local/etc/php && ln -sf php.ini-$APP_ENV php.ini"]
Share:
86,981

Related videos on Youtube

Aniketh
Author by

Aniketh

In my 3+ years software career, I have relevant experience in developing Backend services, REST API's, building Data Infrastructure Pipelines and monitoring tools for services operating in the AWS Cloud Environment Here is the summary of my experience. Expertise in application development and automation right from design phase to deployment in production. My work primarily involved using technologies and frameworks like Java, JavaScript, HTML, CSS SQL, Shell, Spring, Hibernate, Apache Thrift, Hadoop, Oozie, Pig Latin. On the DevOps front I was independently responsible for developing automated test suites and creating a CICD pipeline using Jenkins and Chef for all the applications I have worked on. Knowledgeable of back-end development best practices, with hands-on software troubleshooting experience. Good understanding of data structures and algorithms

Updated on November 28, 2020

Comments

  • Aniketh
    Aniketh over 3 years

    I am working on a task that involves building a docker image with centOs as its base using a Dockerfile . One of the steps inside the dockerfile needs http_proxy and https_proxy ENV variables to be set in order to work behind the proxy.

    As this Dockerfile will be used by multiple teams having different proxies, I want to avoid having to edit the Dockerfile for each team. Instead I am looking for a solution which allows me to pass ENV variables at build time, e.g.,

    sudo docker build -e http_proxy=somevalue .

    I'm not sure if there is already an option that provides this. Am I missing something?

    • user2915097
      user2915097 almost 9 years
      what is the problem with passing those at run time? Something like docker run -e http_proxy http://1.2.3.4:3128 -e https_proxy 1.2.3.4:3129? The doc of docker run docs.docker.com/reference/commandline/run
    • Aniketh
      Aniketh almost 9 years
      The problem is that one of the steps inside docker file invovles yum installation and it fails if i dont set the http/https ENV variables and without proper installation i can't build the image .so docker run doesnt help me here .
    • user2915097
      user2915097 almost 9 years
      I am afraid you will have to build specific images, the only difference being the values of http_proxy(s) ONBUILD may help, but I am afraid it is not suited here, see the doc docs.docker.com/reference/builder
    • user2915097
      user2915097 almost 9 years
      This have been discussed here github.com/docker/docker/issues/4962 and again here github.com/docker/docker/pull/9176 and closed, so at the moment, it seems you have no solution
    • Aniketh
      Aniketh almost 9 years
      Thank you user2915097 for your comments .I have already gone through the above github links ,I asked this question with a tiny hope that someone on Stackoverflow might have faced this similar situation.
    • nwinkler
      nwinkler almost 9 years
      Please feel free to chime in at github.com/docker/docker/pull/9176 to add your requirements for something like this.
    • Michael Freidgeim
      Michael Freidgeim over 3 years
      Does this answer your question? Get environment variable value in Dockerfile
  • Markus Bruckner
    Markus Bruckner over 7 years
    Because I overlooked it: You need ARG to tell docker that a build argument can be passed to the builder. Without specifying ARG <name> it doesn't work.
  • ElmoVanKielmo
    ElmoVanKielmo over 6 years
    This ENV APP_ENV ${APP_ENV} is not needed. It's enough to have ARG APP_ENV without =local and it will grab build argument and use it as any variable set by ENV
  • DuckPuppy
    DuckPuppy about 6 years
    @ElmoVanKielmo That's true during the build, but ARG isn't persisted as an environment variable when the docker image is ran. Using ENV APP_ENV ${APP_ENV} ensures that the environment variable is still available when the container is running.
  • ElmoVanKielmo
    ElmoVanKielmo about 6 years
    @DuckPuppy true but I sticked to the OP's question
  • haridsv
    haridsv about 6 years
    @ElmoVanKielmo OP's question is about passing ENV from command-line, so how does having ARG alone help? You need ARG so that you can pass one via --build-arg and then you need ENV to copy it to an environment variable to be persisted with the image.
  • ElmoVanKielmo
    ElmoVanKielmo about 6 years
    @haridsv OP's question is about passing http_proxy and https_proxy urls at build time and providing ready to use Dokcer images for different teams using different proxies. Value passed via ARG would be stored in a proper configuration file in the image without the need to take it again from ENV on container creation. Normally you would use ENV for configuration which is intended to be set on container creation, and a combination of ARG and ENV for settings with default values which can be overriden on container creation.
  • haridsv
    haridsv about 6 years
    Values passed via ARG will not be available at the time of container creation.
  • chrizzler
    chrizzler over 4 years
    WOW, dang, happened to me too! No one is speaking about this, nowhere in the docs a mention, warning etc! Thanks a lot!!!
  • Chris
    Chris over 4 years
    yes, yes, 1000 time yes. This was the exact answer i needed. I know it's pointed out in the other comments about, but YOU MUST SPECIFIC THE ARGUMENT IN THE DOCKERFILE. Don't forget that.
  • Nick
    Nick over 3 years
    Might I mention this was critical if your deployment environment is from automatic CI. IE I found this when I was trying to make gitlab CI to scale across project domains. IE One project might be settling one different node versions etc...
  • Nikita Zavyalov
    Nikita Zavyalov over 3 years
    Saved me some nerves, thank you! I would never figured out that placement of ARGs matters..
  • andras
    andras about 3 years
    I think this is actually explained here: An ARG declared before a FROM is outside of a build stage, so it can’t be used in any instruction after a FROM
  • Peroxy
    Peroxy over 2 years
    Thanks so much, what an annoying problem to track down, cheers