12

I am building a Docker image using a command line like the following:

docker build -t myimage .

Once this command has succeeded, then rerunning it is a no-op as the image specified by the Dockerfile has not changed. Is there a way to detect if the Dockerfile (or one of the build context files) subsequently changes without rerunning this command?

Richard Cook
  • 32,523
  • 5
  • 46
  • 71

3 Answers3

18

looking at docker inspect $image_name from one build to another, several information doesn't change if the docker image hasn't changed. One of them is the docker Id. So, I used the Id information to check if a docker has been changed as follows:

First, one can get the image Id as follows:

docker inspect --format {{.Id}} $docker_image_name

Then, to check if there is a change after a build, you can follow these steps:

  1. Get the image id before the build
  2. Build the image
  3. Get the image id after the build
  4. Compare the two ids, if they match there is no change, if they don't match, there was a change.

Code: Here is a working bash script implementing the above idea:

docker inspect --format {{.Id}} $docker_image_name > deploy/last_image_build_id.log
# I get the docker last image id from a file
last_docker_id=$(cat deploy/last_image_build_id.log)
docker build -t $docker_image_name .
docker_id_after_build=$(docker inspect --format {{.Id}} $docker_image_name)
if [ "$docker_id_after_build" != "$last_docker_id" ]; then
   echo "image changed" 
else
   echo "image didn't change" 
fi
Mohamed Ali JAMAOUI
  • 14,275
  • 14
  • 73
  • 117
  • 12
    Is there a way to determine whether `docker build` will yield a new image or not _without_ actually building? – Dror Mar 30 '20 at 13:12
  • If you are following best practices for layer optimization in your Dockerfile, then the `docker build` command will skip all steps if the Dockerfile has not changed. Practically speaking, this is near-instantaneous, and once done you can compare the `Id` as in this answer. – mainmachine Jul 18 '22 at 19:06
  • @mainmachine Regardless of the runtime, a `--dry-run` option would be useful. When writing scripts that re-build a docker image if necessary, then launch a command within that image, I prefer to print the output of `docker build` only when the build would have an effect. This would be straightforward if docker had a `--dry-run` option. Without such an option, this requires redirecting the stdout of `docker build`, parsing it, and redirecting/unbuffering the stdout if the build step does have an effect. – Eldritch Cheese Feb 04 '23 at 18:11
8

There isn't a dry-run option if that's what you are looking for. You can use a different tag to avoid affecting existing images and look for ---> Using cache in the output (then delete the tag if you don't want it).

ldg
  • 9,112
  • 2
  • 29
  • 44
0

What follows is not the answer to your exact question, but a work-around that has served me.

Since Docker apparently doesn't offer the "dry-run" feature, you could check the dependencies of the image. Specifically, you could checksum all files within the Docker context, being rough. To be finer, you could check only the actually used files.

The following code will make a hash of all files referenced by COPY commands as well as the Dockerfile itself.

( 
echo Dockerfile 
sed -n 's/^COPY \([^ ]\+\) .*$/\1/p' Dockerfile  
) | xargs --replace find '{}' -type f |
  sort |
  xargs cat | 
  sha256sum | cut -d' ' -f1
Raúl Salinas-Monteagudo
  • 3,412
  • 1
  • 24
  • 22