Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a reusable dockerfile template?

I find myself often repeating dockerfile content. For example for a typical spring-boot application, this would be as follows:

FROM $BUILD_IMAGE as build
COPY pom.xml .
RUN mvn dependency:go-offline

COPY src src
RUN mvn package
RUN java -Djarmode=layertools -jar target/application.jar extract

FROM $RUNTIME_IMAGE
COPY --from=build /application/dependencies/ ./
COPY --from=build /application/spring-boot-loader/ ./
COPY --from=build /application/snapshot-dependencies/ ./
COPY --from=build /application/application/ ./

EXPOSE 8081
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

Here only 3 things are dynamic based on the project that executes the dockerfile: pom.xml, src, EXPOSE <port>. Everything else is always the same.

Question: is it possible to create some kind of "template", so that I can "feed" the template with those 3 dynamic files or folders?

I would not want to copy the dockerfile into all of my projects 1:1. I would prefer if I could use the dockerfile as a base definition, and reference it from all of my spring-boot projects.

like image 417
membersound Avatar asked Sep 16 '25 04:09

membersound


1 Answers

We can achieve this with the ARG directive (docs.docker.com). Here is an example Dockerfile:

# syntax=docker/dockerfile:1
ARG TAG

FROM ubuntu:$TAG
ARG FILE_TO_COPY
ARG EXPOSE_PORT
COPY $FILE_TO_COPY file.txt
CMD cat file.txt

EXPOSE $PORT_TO_EXPOSE

There is a semantic difference between any ARG before the first FROM and any arg after the first FROM: the former can be used within the FROM directive, e.g. to define the tag or digest. Its value is not available in a build stage. The latter belongs to a build stage, and thus in only accessible within the build stage. This behaviour is specified here (docs.docker.com).

We can build the image, specifying the build arguments:

$ docker build \
  --build-arg TAG=18.04 \
  --build-arg FILE_TO_COPY=foo.txt \
  --build-arg PORT_TO_EXPOSE=8080 \
  --tag test \
  .

and then run it:

$ docker run -it --rm test
bar
like image 97
Turing85 Avatar answered Sep 17 '25 16:09

Turing85