jorence jovin
jorence jovin

Reputation: 211

how to pass argument to dockerfile from a file

I am trying to pass an argument from a file to docker file.

I tried to the copy the file into docker container and use source command.

Dockerfile

COPY docker.env .
RUN /bin/bash -c "source docker.env"

Docker.env

BuildMode="release"

another try which also did not work

export BuildMode="release"

There is no error but when I tried to print ECHO $BuildMode, it is not printing the value inside it, it is like it did not get the value inside of it.

But if I create a docker container and try the same codes inside docker container, then it is working.

Upvotes: 12

Views: 27087

Answers (6)

Kamrus
Kamrus

Reputation: 364

Dockerfile

FROM ubuntu:16.04

ARG BuildMode
ENV BuildMode=${BuildMode}

RUN echo $BuildMode

docker.env

BuildMode=value

You can add many variables in docker.env

docker build $(cat docker.env | awk -F "=" '{ print "--build-arg " $1"="$2;}' | xargs) -t image_name:latest .

Upvotes: -2

Sachin Nikumbh
Sachin Nikumbh

Reputation: 1059

in file docker-compose.yml

  my-service:
    build:
      dockerfile: ./Dockerfile
      context: ./python/
      args:
        ARGS_1: aamazonaws.com
        ARGS_2: ggoogle.com

in Dockerfile

FROM base:latest

ARG ARGS_1
ARG ARGS_2

COPY . /app/$ARGS_1

VOLUME [ "/configs/" ]

ENTRYPOINT [ "" ]

CMD [ "" ]

Upvotes: 1

confiq
confiq

Reputation: 2928

I had a problem with whitespaces and with old macOS bash version 3. Since I had to make work for everybody with macOS, I had to make a workaround and came up with this solution

while IFS= read -r line; do
  echo $line
  opts+=(--build-arg "$line")
done < ".ENV.FILE"

docker build "${opts[@]}" -t ${IMAGE_NAME}:${DTAG} -t ${IMAGE_NAME}:${K8S_NS} .

Where .ENV.FILE looks like this:

APP_PORT=3030
APP_HOST=0.0.0.0
APP_API_URL=FOO
APP_API_WHITE=S P A C E

I hope it helps somebody

Upvotes: 6

atline
atline

Reputation: 31664

Then you can use --build-arg, it will pass parameters with --build-arg key=value to dockerfile when build, refer to this.

You just need to use sed to get from your env file & combine them to the format --build-arg key=value when build the dockerfile, example as next:

Dockefile:

FROM ubuntu:16.04

ARG BuildMode
ENV BuildMode=${BuildMode}

RUN echo $BuildMode

docker.env:

BuildMode="release"

Command:

docker build -t abc:1 $(cat docker.env | sed 's@^@--build-arg @g' | paste -s -d " ") . --no-cache

Output:

shubuntu1@shubuntu1:~/1$ docker build -t abc:1 $(cat docker.env | sed 's@^@--build-arg @g' | paste -s -d " ") . --no-cache
Sending build context to Docker daemon  3.072kB
Step 1/4 : FROM ubuntu:16.04
 ---> 13c9f1285025
Step 2/4 : ARG BuildMode
 ---> Running in 3bc49fbb0af4
Removing intermediate container 3bc49fbb0af4
Step 3/4 : ENV BuildMode=${BuildMode}
 ---> Running in 4c253fba0b36
Removing intermediate container 4c253fba0b36
 ---> c70f7f535d1f
Step 4/4 : RUN echo $BuildMode
 ---> Running in 5fef72f28975
"release"
Removing intermediate container 5fef72f28975
 ---> 4b5555223b5b
Successfully built 4b5555223b5b
Successfully tagged abc:1

Upvotes: 15

David Maze
David Maze

Reputation: 159865

Every Dockerfile RUN command launches a new container in a new shell. No export command you run there will ever have an effect in a later layer. If you use . or non-standard vendor extensions like bash's source to read in a script that sets variables, again, that will never have any effect in a later layer.

FROM busybox
RUN export FOO=foo
CMD echo FOO is $FOO # doesn't actually print a value

If you want to set environment variables, you need to use the Dockerfile ENV directive.

FROM busybox
ENV FOO=foo
CMD echo FOO is $FOO
# Compare: docker run -e FOO=bar myimage

If it absolutely must be in a file, then you have to read it in on every RUN command that depends on variables set there. You also need to arrange for it to be read in when the container starts; the usual way is to write an ENTRYPOINT that reads the environment file and then runs whatever the image's CMD is.

#!/bin/sh
# I am entrypoint.sh

# Read in the environment file
. /env.sh

# Run the CMD, as the main container process
exec "$@"
# I am Dockerfile
FROM busybox
COPY env.sh entrypoint.sh /
RUN chmod +x /entrypoint.sh

# Example: Do something that depends on the variable value
RUN . /env.sh && echo FOO is $FOO
# Need to repeat "." in every RUN line
RUN . /env.sh && echo BAR is $BAR

# Startup-time instructions
ENTRYPOINT ["/env.sh"]  # must use JSON syntax
CMD echo FOO is $FOO
# Compare: docker run -v $PWD/env.sh:/env.sh myimage

(For the same reasons, you need to use Docker WORKDIR over shell cd to persistently switch directories; and you shouldn't use environment managers Python virtual environments, Node's nvm, or Ruby's rvm in Docker because managing the environment variables is irritating and Docker already provides an isolated execution environment.)

Upvotes: 0

jorence jovin
jorence jovin

Reputation: 211

final I found the issue, the issue was docker was removing the intermediate container while building so the variable was not stored this happens if the docker build was run using -rm flag. So the remedy I made was to execute the code in the previous code itself

RUN /bin/bash -c 'source docker.env; echo $Environment'

I know it was not a good idea if the code is big but this is the only way if you are using -rm and bash code
------------------------------------------------------(OR)----------------------------------------------------------------

set --rm=false flag and try, but I have not tried that because I have to run with -rm flag as it is the default code in visual code I should not alter it

Upvotes: 0

Related Questions