Dockerfile

kind: dockerfile

sourceconditiontarget

Description

condition

The Dockerfile "condition" tests that a Dockerfile instruction is correctly set to a value

target

The Dockerfile "target" updates if needed the Dockerfile

Methods

There are 2 available methods for the resource "Dockerfile":

  • By Text Matching

    • Batch: Can match multiple instructions

    • Keeper: Does not remove Dockerfile comments

  • By Specific Coordinates

    • Precise: only 1 instruction matched

    • Full Support: all keywords are supported

By Text Matching

Matches a set of Dockerfile instructions to manipulate, by filtering per keyword and text matching on the keyword’s arguments.

Usage

Given the following file:

### File: Dockerfile.webapp
ARG GO_VERSION=1.15.8
FROM golang:"${GO_VERSION}-alpine" AS build
# Retrieve source code
WORKDIR /app
COPY . /app
# Build application
RUN go build -X "GoVersion=${GO_VERSION}" -o ./webapp

FROM ubuntu AS test
ARG GO_VERSION
ENV GO_VERSION=${GO_VERSION}
RUN ./run_tests.sh

FROM ubuntu:18.04 AS run
COPY --from=builder /app/webapp /usr/local/bin/webapp

And the following configuration:

title: "Bump golang version"
# Define custom source here
targets:
  updateGoVersion:
    name: "Update the value of ARG GO_VERSION in the Dockerfile"
    sourceID: getGolangVersion
    kind: dockerfile
    spec:
      file: Dockerfile.webapp
      instruction:
        keyword: "ARG"
        matcher: "GO_VERSION"
  updateUbuntuVersion:
    name: "Update Ubuntu image to latest LTS"
    sourceID: getLatestUbuntuLTSVersion
    kind: dockerfile
    spec:
      files:
        - Dockerfile.webapp
        - Dockerfile.api
      instruction:
        keyword: "FROM"
        matcher: "ubuntu"

With the following:

  • getGolangVersion: 1.15.11

  • getLatestUbuntuLTSVersion: 20.04

Then the result is:

### File: Dockerfile.webapp
ARG GO_VERSION=1.15.11 (1)
FROM golang:"${GO_VERSION}-alpine" AS build
# Retrieve source code
WORKDIR /app
COPY . /app
# Build application
RUN go build -X "GoVersion=${GO_VERSION}" -o ./webapp

FROM ubuntu:20.04 AS test (2)
ARG GO_VERSION=1.15.11 (1)
ENV GO_VERSION=${GO_VERSION}
RUN ./run_tests.sh

FROM ubuntu:20.04 AS run (2)
COPY --from=builder /app/webapp /usr/local/bin/webapp
  1. Changed by the target updateGoVersion

  2. Changed by the target updateUbuntuVersion

Please look at Supported Keywords to see more specific examples.

Parameters

NameRequiredDefaultDescription

file

✔ (if files is not set)

-

Specifies the dockerimage file path to use and is incompatible with files

files

✔ (if file is not set)

-

Specifies the dockerimage file path to use and is incompatible with files

instruction.keyword

-

Set the Supported Keywords to be matched.

instruction.matcher

-

Set the text to be matched.

Supported Keywords

From the Dockerfile reference , the following keyword are currently supported:

If you need an unsupported keyword, or an unsupported scenario:

FROM

Matches Dockerfile FROM instructions by image name to manipulate their image’s tags.

  • Matches only on the image name

    • Matching is case sensitive

    • Multi stages with an alias are supported, but the alias is not used for matching

  • When used as a target, only the image tag is modified by Updatecli

    • "Friends don’t let friend use `latest`": if an instruction is matched and it has no tag, then Updatecli append the values as a tag.

With the following definition:

spec:
  file: Dockerfile
  instruction:
    keyword: "FROM"
    matcher: "alpine"

you get the following results:

# Matches
FROM alpine:3.12
from alpine:3.13
FROM alpine:3.11 AS builder
FROM alpine
FROM alpine:latest

## Does NOT matches
FROM ubuntu:20.04
FROM debian:buster AS alpine
FROM mountain:alpine
FROM ALPINE:3.11

ARG

Matches Dockerfile ARG instruction by key to manipulate their values.

  • Only matches by key (left of the = when present)

    • Matching is case sensitive

  • When used as a target, only the value of the argument (right of the = when present)

    • When no argument value is found (e.g. default value, no character = or empty value), then updatecli appends the = character followed by the value.

With the following definition:

spec:
  file: Dockerfile
  instruction:
    keyword: "ARG"
    matcher: "UPDATECLI_VERSION"

you get the following results:

# Matches
ARG UPDATECLI_VERSION
ARG UPDATECLI_VERSION=
ARG UPDATECLI_VERSION=0.1.0
arg UPDATECLI_VERSION=0.1.0

## Does NOT matches
ARG GOLANG_VERSION
ARG RUST_VERSION=UPDATECLI_VERSION
ARG updatecli_version

ENV

Matches Dockerfile ENV instruction by keys to manipulate their values.

  • Only matches on the environment key (left of the = when present)

    • Matching is case sensitive

  • Only matches single and valid key/value pairs:

    • ENV foo=bar is supported

    • ENV foo=bar toto=titi is NOT supported

    • ENV foo is NOT supported (invalid Dockerfile instruction as a value is mandatory)

  • When used as a target, only the value of the environment (right of the = when present)

    • When no environment value is found (e.g. default value, no character = or empty value), then updatecli appends the = character followed by the value.

With the following definition:

spec:
  file: Dockerfile
  instruction:
    keyword: "ENV"
    matcher: "UPDATECLI_VERSION"

you get the following results:

# Matches
ENV UPDATECLI_VERSION=0.1.0
env UPDATECLI_VERSION=0.1.0

## Does NOT matches
# Invalid
ENV GOLANG_VERSION
# No match
ENV RUST_VERSION=UPDATECLI_VERSION
# lower case: no match
ENV updatecli_version
# Multiple key/value pairs
ENV FOO=BAR UPDATECLI_VERSION=0.1.0

By Specific Coordinates

Parameters

NameTypeDescriptionRequired
filestringFile specifies the dockerimage file path to use and is incompatible with Files
filesarrayFiles specifies the dockerimage file path(s) to use and is incompatible with File
instructionInstruction specifies a DockerImage instruction such as ENV
stagestring

Stage can be used to further refined the scope For Sources:

  • If not defined, the last stage will be considered For Condition and Targets:
  • If not defined, all stages will be considered
valuestringValue specifies the value for a specified Dockerfile instruction.

Syntax

Updatecli represents internally a Dockerfile as a two-dimensional array where the first dimension is a list of Dockerfile instruction like "FROM", "RUN", etc…​, and the second dimension represents a list of arguments for each instruction.

In the following example "Dockerfile", the first dimension is ["FROM","LABEL","LABEL"]

Dockerfile
FROM jenkins/jenkins:2.274
LABEL maintainer=olblak
LABEL version=2.274 \
      date = "2021/01/09"

And the second dimension is :

FROM    = ["jenkins/jenkins:2.274"]
LABEL0  = ["maintainer", "olblak"]
LABEL1  = ["version", "2.274", "date", "2021/01/09"]

Updatecli identifies a specific Dockerfile instruction through its coordinates, by using the syntax INSTRUCTION[x][y] where:

  • INSTRUCTION must be replaced by a valid Dockerfile instruction like ARG, ENV, LABEL, etc

  • "x" references a specific instruction position where x is replaced by any integer starting from 0. So "0" means the first instruction of type INSTRUCTION, "1" means the second, etc

  • "y" references a specific argument element for the INSTRUCTION[x] where "y" is replaced by any integer starting from 0. So "0" means the first argument, "1" means the second, etc

Based on the Dockerfile example, here is the list of instruction equivalent * LABEL[0][0] equal maintainer * LABEL[0][1] equal olblak * LABEL[1][0] equal version * LABEL[1][4] equal 2021/01/09

Note
A shorter syntax is available where INSTRUCTION is an alias for INSTRUCTION[0][0].
Important

When used as a target (and writing to a file):

  • "Specific Coordinates" method might not keep the initial Dockerfile syntax

  • "Specific Coordinates" method drops comments from the initial Dockerfile

Examples

updatecli.yaml
sources:
  lastHelmVersion:
    name: Get Latest helm release version
    kind: githubRelease
    spec:
      owner: "helm"
      repository: "helm"
      token: {{ requiredEnv .github.token }}
      username: olblak
      versionFilter:
        kind: latest
conditions:
  isENVSet:
    name: Is ENV HELM_VERSION set
    kind: dockerfile
    spec:
      file: docker/Dockerfile
      instruction: ENV[1][0]
      value: "HELM_VERSION"
    scm:
      github:
        user: "updatecli"
        email: "updatecli@olblak.com"
        owner: "olblak"
        repository: "charts"
        token: {{ requiredEnv "GITHUB_TOKEN" }}
        username: "olblak"
        branch: "master"
targets:
  updateENVHELMVERSION:
    name: Update HELM_VERSION
    kind: dockerfile
    spec:
      file: docker/Dockerfile
      instruction: ENV[1][1]
    scm:
      github:
        user: "updatecli"
        email: "updatecli@olblak.com"
        owner: "olblak"
        repository: "charts"
        token: {{ requiredEnv "GITHUB_TOKEN" }}
        username: "olblak"
        branch: "master"

What it says:

Source

Retrieve the helm version from its github release located on https://github.com/helm/helm ⇒ v3.4.2

Conditions

Then it will test one condition: If the dockerfile 'docker/Dockerfile' is located on the git repository https://github.com/olblak/charts has the instruction ENV[1][0] set to "HELM_VERSION". ENV[1][0] is a custom syntax to represent a two-dimensional array where the first element represents a specific Dockerfile instruction identifier starting from "0" at the beginning of the document, so we are looking for the second INSTRUCTION "ENV". The second element represents an instruction argument position. In this case, we want to check that ENV key is set to "HELM_VERSION"

Targets

If the condition is met, which is to be sure that the ENV key set to "HELM_VERSION" exist, then we’ll are going to update its value if needed based on the version retrieved from the source. The syntax is the same for the condition excepted that this time we are looking for ENV[1][1] which means that the second argument of the second ENV instruction.

Top