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

4

142

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?

Quibbling answered 3/7, 2015 at 5:1 Comment(7)
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/runMongol
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 .Quibbling
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/builderMongol
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 solutionMongol
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.Quibbling
Please feel free to chime in at github.com/docker/docker/pull/9176 to add your requirements for something like this.Scrumptious
Does this answer your question? Get environment variable value in DockerfileTable
J
205

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.

Jabber answered 31/12, 2015 at 11:16 Comment(8)
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.Primordial
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 ENVSummit
@Summit 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.Tenebrific
@Tenebrific true but I sticked to the OP's questionSummit
@Summit 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.Worrell
@Worrell 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.Summit
Values passed via ARG will not be available at the time of container creation.Worrell
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.Ebeneser
D
54

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..
Downcomer answered 27/11, 2019 at 19:14 Comment(5)
WOW, dang, happened to me too! No one is speaking about this, nowhere in the docs a mention, warning etc! Thanks a lot!!!Hindgut
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...Downcomer
Saved me some nerves, thank you! I would never figured out that placement of ARGs matters..Withdrew
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 FROMBuxton
Thanks so much, what an annoying problem to track down, cheersDulse
L
5

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"]
Lagging answered 1/8, 2016 at 7:43 Comment(0)
S
3

To set multiple build arguments like in your case for http_proxy and https_proxy you've to do the following changes:

1). Dockerfile

FROM centos:latest

# Define ARG after FROM to indicate values coming from build arguments are part of the build stage.
ARG http_proxy 
ARG https_proxy

# Create the environment variables and assign the values from the build arguments.
ENV http_proxy=$http_proxy \
    https_proxy=$https_proxy \

# Print the values.
RUN echo "http_proxy: $http_proxy"
RUN echo "https_proxy: $https_proxy"

2). Command to run

sudo docker build \
--build-arg http_proxy=http://172.0.0.1 \
--build-arg https_proxy=https://10.20.30.2 \
.
Sprague answered 5/6, 2023 at 7:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.