84

I am wondering if a env variable can be used in a docker from? Reason for this is to control the tagging. For example, say I have this line in my Dockerfile:

FROM myApp

What I want is this:

FROM myApp:${VERSION}

This way I can say docker build . myApp --build-arg VERSION=9

The process to build docker images for this app is the same. I don't want to have Dockerfiles that are almost identical just to use a different base image.If I want to build version 9, it should use version 9 of the base image.

bgrupczy
  • 67
  • 1
  • 2
  • 8
CodyK
  • 3,426
  • 4
  • 36
  • 52

5 Answers5

110

Quoting this link :

This is now possible if anyone comes here looking for answers: https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact

FROM instructions support variables that are declared by any ARG instructions that occur before the first FROM.

ARG  CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD  /code/run-app

FROM extras:${CODE_VERSION}
CMD  /code/run-extras
Paul Sturm
  • 2,118
  • 1
  • 18
  • 23
Hadrien TOMA
  • 2,375
  • 2
  • 22
  • 32
35

For at least this docker version this is feasible

docker --version
docker version 18.09.8, build bfed4f5

It requires a preset variable in Dockerfile e.g.

ARG TAG=latest
FROM traefik:${TAG}

Then you can override this preset with the following

docker build --build-arg "TAG=2.2.8" -t my-app:$TAG

The version number will not show up during build. if you want to test if it works, reference a non-existing version - it will fail with: manifest my-app:version not found.

Mandragor
  • 4,684
  • 7
  • 25
  • 40
3

You could simply generate your Dockerfile from a template. Put something like this in a Makefile:

MYTAG=latest

.PHONY: Dockerfile
Dockerfile: Dockerfile.in
    sed 's/MYTAG/$(MYTAG)/' $< > $@ || rm -f $@

Then you can run:

make MYTAG=8; docker build -t my-app-8 .

This would only make sense if you are frequently building images that require a different tag in the FROM line.

larsks
  • 277,717
  • 41
  • 399
  • 399
  • 1
    I thought about that. I was just hoping for a native docker feature for this. – CodyK Apr 11 '16 at 19:21
  • 3
    There's no native solution; there is an open proposal/feature request though; https://github.com/docker/docker/issues/18119 – thaJeztah Apr 11 '16 at 20:32
1

Build your container programatically using buildah (It can take Dockerfile too).

So for your use-case:

 VERSION=v0.1.0

 myCon=$(buildah from myApp:${VERSION})

 buildah config --cmd "sleep 1d" $myCon

 buildah commit $myCon $USER/sleeping1d

You can obviously script it, save and invoke it, and one more advantage is buildah doesn't need docker daemon running, which is great for CI. Also it's an open-source project, check out the project page.

BTW I saw this issue lately which is exactly what you want - https://github.com/projectatomic/buildah/issues/581

Roy Golan
  • 113
  • 3
-1

Unfortunately it's not possible to do that. The first line of your Dockerfile must be a FROM directive, and so that precludes the use of the ARG directive. There is a good answer there from larsks about generating a Dockerfile, but I'd also like to suggest merely creating different Dockerfiles and then specifying a particular one in your docker build command using the -f switch:

docker build -t codemiester/app:latest -f ./Dockerfile.apache2.ubuntu
L0j1k
  • 12,255
  • 7
  • 53
  • 65
  • I can do that. It is just a pain, given as I mentioned the process is the same regardless of versions. And I also, want an easy mechanism to keep image and base image synchronized. – CodyK Apr 12 '16 at 13:34