Updating base images in Dockerfiles

Create a campaign to update Dockerfiles in every one of your repositories.

Introduction

Campaigns allow us to update the base images used in our Dockerfiles, across many repositories, in just a few commands.

This tutorial shows you how to create a campaign spec that

  1. finds Dockerfiles that make use of google/dart:2.x base images and
  2. changes those Dockerfiles to use google/dart:2.10

The campaign spec and instructions here can easily be adapted to update other base images.

Prerequisites

We recommend using the latest version of Sourcegraph when working with campaigns and that you have a basic understanding of how to create campaign specs and run them. See the following documents for more information:

  1. "Quickstart"
  2. "Introduction to campaigns"

Create the campaign spec

Save the following campaign spec YAML as update-dart-base-images-2-10.campaign.yaml:

name: update-dart-base-images-2-10
description: This campaign updates `google/dart:2.*` base images in Dockerfiles to `google/dart:2.10.2`.

on:
  # Find all repositories that contain Dockerfiles with `FROM google/dart:2.*` as base images.
  # The regexp used here matches images
  #
  #   google/dart:2.MINOR.PATCH
  #   google/dart:2.MINOR.PATCH-dev.DEVMINOR.DEVPATCH
  #
  #   google/dart-runtime:2.MINOR.PATCH
  #   google/dart-runtime:2.MINOR.PATCH-dev.DEVMINOR.DEVPATCH
  #
  # where the tag is < 2.10. Feel free to adjust it to your requirements.
  - repositoriesMatchingQuery: ^FROM google\/dart(-runtime)?:2\.[0-9]\.?\d?(-dev\.\d\.\d)? file:Dockerfile  patternType:regexp

# In each repository
steps:
  # find all Dockerfiles and replace the old image tags with our desired ones:
  - run: |
      find . -name Dockerfile -type f |\
      xargs sed\
        -i\
        --regexp-extended\
        's/FROM google\/dart(-runtime)?:2\.[[:digit:]]\.?[[:digit:]]?(-dev\.?[[:digit:]]?\.?[[:digit:]]?)?/FROM google\/dart:2\.10/g'      
    container: alpine:3

# Describe the changeset (e.g., GitHub pull request) you want for each repository.
changesetTemplate:
  title: Update google/dart base images in Dockerfiles to 2.10.2
  body: This updates google/dart base images used in Dockerfiles to version 2.10.2
  branch: campaigns/google-dart-2-10-2-base-images # Push the commit to this branch.
  commit:
    message: Update google/dart base images in Dockerfiles to 2.10.2
  published: false

Create the campaign

  1. In your terminal, run this command:

    src campaign preview -f update-dart-base-images-2-10.campaign.yaml
  2. Wait for it to run and compute the changes for each repository.

  3. Open the preview URL that the command printed out.

  4. Examine the preview. Confirm that the changesets are the ones you intended to track. If not, edit the campaign spec and then rerun the command above.

  5. Click the Apply spec button to create the campaign.

  6. Feel free to then publish the changesets (i.e. create pull requests and merge requests) by modifying the published attribute in the campaign spec and re-running the src campaign preview command.

Updating other base images

In order to update other base images in Dockerfiles you can either extend the campaign spec or create another campaign spec in which you change the repositoriesMatchingQuery and the steps.run properties.

You can keep using regexp-based search and sed, or you can use structural search combined with comby to update base images.

For example, here's how you would update alpine base images from alpine:3.9, alpine:3.10, alpine:3.11 to alpine:3.12:

# [...]

on:
  - repositoriesMatchingQuery: FROM alpine:3.:[minor~[91]+[0-1]?] file:Dockerfile patternType:structural
  - repositoriesMatchingQuery: FROM alpine:3.:[minor~[91]+[0-1]?]@sha256::[hash~[a-f0-9]+] file:Dockerfile patternType:structural

steps:
  - run: |
      comby \
        -in-place \
        'FROM alpine:3.:[minor~[91]+[0-1]?]@sha256::[hash~[a-f0-9]+]' \
        'FROM alpine:3.12@ sha256:c0e9560cda118f9ec63ddefb4a173a2b2a0347082d7dff7dc14272e7841a5b5a' \
        Dockerfile      
    container: comby/comby
  - run: comby -in-place 'alpine:3.:[minor~[91]+[0-1]?]' 'FROM alpine:3.12' Dockerfile
    container: comby/comby

# [...]

And here's how you could update golang base images to use Go 1.15:

# [...]
on:
  - repositoriesMatchingQuery: FROM golang:1.1:[minor~[0-4]]-alpine file:Dockerfile patternType:structural
  - repositoriesMatchingQuery: FROM golang:1.1:[minor~[0-4]]-alpine@sha256::[hash~[a-f0-9]+] file:Dockerfile patternType:structural

steps:
  - run: |
      comby \
        -in-place \
        'FROM golang::[version]-alpine@sha256::[hash~[a-f0-9]+]' \
        'FROM golang:1.15-alpine@sha256:df0119b970c8e5e9f0f5c40f6b55edddf616bab2b911927ebc3b361c469ea29c' \
        Dockerfile      
    container: comby/comby
  - run: comby -in-place 'FROM golang::[version]-alpine' 'FROM golang:1.15-alpine' Dockerfile
    container: comby/comby