Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dockerfile Overwrite ARG values

I have a Dockerfile that has Scala and SBT as below:

# Scala and sbt Dockerfile
# Scala and SBT forked from: https://github.com/hseeberger/scala-sbt
# Adds Docker client installation additionally

# Pull base image
FROM  openjdk:$JAVA_VERSION

ARG SCALA_VERSION
ARG SBT_VERSION

# Scala expects this file
RUN touch /usr/lib/jvm/java-$JAVA_VERSION-openjdk-amd64/release

# Install Scala
## Piping curl directly in tar
RUN \
  curl -fsL http://downloads.typesafe.com/scala/$SCALA_VERSION/scala-$SCALA_VERSION.tgz | tar xfz - -C /root/ && \
  echo >> /root/.bashrc && \
  echo 'export PATH=~/scala-$SCALA_VERSION/bin:$PATH' >> /root/.bashrc

# Install sbt
RUN \
  curl -L -o sbt-$SBT_VERSION.deb http://dl.bintray.com/sbt/debian/sbt-$SBT_VERSION.deb && \
  dpkg -i sbt-$SBT_VERSION.deb && \
  rm sbt-$SBT_VERSION.deb && \
  apt-get update && \
  apt-get install sbt && \
  sbt sbtVersion

Now if I want to use this as my base image, I have the following question:

  1. Can I overwrite the ARG parameters in my new Dockerfile which will use the one above as a base image?
like image 867
joesan Avatar asked Jul 18 '17 05:07

joesan


People also ask

How do I set ARG values in a dockerfile?

relevant docs. When building a Docker image from the commandline, you can set ARG values using –build-arg: $ docker build --build-arg some_variable_name=a_value. Running that command, with the above Dockerfile, will result in the following line being printed (among others): Oh dang look at that a_value.

What is Arg and env in Docker?

ARG and ENV Availability When using Docker, we distinguish between two different types of variables - ARG and ENV. ARG are also known as build-time variables. They are only available from the moment they are ‘announced’ in the Dockerfile with an ARG instruction up to the moment when the image is built.

Does Docker build overwrite a file it has previously copied?

It seems that docker build won't overwrite a file it has previously copied. I have a dockerfile with several copy instructions, and files touched in earlier COPY directives don't get overwritten by later ones. A simplified example (although it also happens if the first copy is an entire directory that happens to contain the file in question):

How to change the default value of a parameter in dockerfile?

You can use the ARG command inside a Dockerfile to define the name of a parameter and its default value. This default value can also be overridden using a simple option with the Docker build command.


2 Answers

Each Dockerfile produces an immutable image. So you need first build an specific base image, and then build your own FROM it.

You can take this approach:

Dockerfile.base:

# Scala and sbt Dockerfile
# Scala and SBT forked from: https://github.com/hseeberger/scala-sbt
# Adds Docker client installation additionally

# Pull base image
ARG JAVA_VERSION
FROM  openjdk:$JAVA_VERSION

ARG SCALA_VERSION
ARG SBT_VERSION

# Scala expects this file
RUN touch /usr/lib/jvm/java-$JAVA_VERSION-openjdk-amd64/release

# Install Scala
## Piping curl directly in tar
RUN \
  curl -fsL http://downloads.typesafe.com/scala/$SCALA_VERSION/scala-$SCALA_VERSION.tgz | tar xfz - -C /root/ && \
  echo >> /root/.bashrc && \
  echo 'export PATH=~/scala-$SCALA_VERSION/bin:$PATH' >> /root/.bashrc

# Install sbt
RUN \
  curl -L -o sbt-$SBT_VERSION.deb http://dl.bintray.com/sbt/debian/sbt-$SBT_VERSION.deb && \
  dpkg -i sbt-$SBT_VERSION.deb && \
  rm sbt-$SBT_VERSION.deb && \
  apt-get update && \
  apt-get install sbt && \
  sbt sbtVersion

Your child Dockerfile Dockerfile.mine:

ARG JAVA_VERSION
ARG SCALA_VERSION
ARG SBT_VERSION
FROM basejava:java-$JAVA_VERSION-scala-$SCALA_VERSION-sbt-$SBT_VERSION
# Your app stuf here
# ...
# ...

Build example:

 export JAVA_VERSION=latest
 export SCALA_VERSION=1.8
 export SBT_VERSION=0.13.9
 docker build . \
   -f Dockerfile.base \
   --build-arg JAVA_VERSION=$JAVA_VERSION \
   --build-arg SCALA_VERSION=$SCALA_VERSION \
   --build-arg SBT_VERSION=$SBT_VERSION \
   -t basejava:java-$JAVA_VERSION-scala-$SCALA_VERSION-sbt-$SBT_VERSION

 docker build . \
   -f Dockerfile.mine \
   --build-arg JAVA_VERSION=latest \
   --build-arg SCALA_VERSION=1.8 \
   --build-arg SBT_VERSION=0.13.9
   -t myjava:java-$JAVA_VERSION-scala-$SCALA_VERSION-sbt-$SBT_VERSION

Approach 2, ONBUILD, mentioned by zigarn.

Dockerfile.base:

# Scala and sbt Dockerfile
# Scala and SBT forked from: https://github.com/hseeberger/scala-sbt
# Adds Docker client installation additionally

# Pull base image
ONBUILD ARG JAVA_VERSION
FROM  openjdk:$JAVA_VERSION

ONBUILD ARG SCALA_VERSION
ONBUILD ARG SBT_VERSION

# Scala expects this file
ONBUILD RUN touch /usr/lib/jvm/java-$JAVA_VERSION-openjdk-amd64/release

# Install Scala
## Piping curl directly in tar
ONBUILD RUN \
  curl -fsL http://downloads.typesafe.com/scala/$SCALA_VERSION/scala-$SCALA_VERSION.tgz | tar xfz - -C /root/ && \
  echo >> /root/.bashrc && \
  echo 'export PATH=~/scala-$SCALA_VERSION/bin:$PATH' >> /root/.bashrc

# Install sbt
ONBUILD RUN \
  curl -L -o sbt-$SBT_VERSION.deb http://dl.bintray.com/sbt/debian/sbt-$SBT_VERSION.deb && \
  dpkg -i sbt-$SBT_VERSION.deb && \
  rm sbt-$SBT_VERSION.deb && \
  apt-get update && \
  apt-get install sbt && \
  sbt sbtVersion

Your child Dockerfile.mine

FROM basejava
# Base ONLBUILD instructions are automatically inserted here.
# Your app stuf here
# ...
# ...

Build:

docker build . -f Dockerfile.base -t basejava

export JAVA_VERSION=latest
export SCALA_VERSION=1.8
export SBT_VERSION=0.13.9
docker build . \
   -f Dockerfile.mine \
   --build-arg JAVA_VERSION=$JAVA_VERSION \
   --build-arg SCALA_VERSION=$SCALA_VERSION \
   --build-arg SBT_VERSION=$SBT_VERSION \
   -t myjava:java-$JAVA_VERSION-scala-$SCALA_VERSION-sbt-$SBT_VERSION
like image 172
Robert Avatar answered Oct 10 '22 12:10

Robert


ARG values are defined at build time.
Once your base image is built, you cannot just change the --build-arg to get another SCALA_VERSION inside your final image (or you have to install it again in you new Dockerfile)

The present Dockerfile is like a template for other Dockerfile.
You could use the ONBUILD instruction to effectively do the installations during the build of other images using this one as base image.

like image 36
zigarn Avatar answered Oct 10 '22 14:10

zigarn