Canonical way to checksum downloads in a Dockerfile? [closed]
Asked Answered
P

4

31

I'm creating a Dockerfile that downloads, builds, installs node.js from source. I'd like to checksum the download before building it, and stop or exit the Dockerfile if the checksum fails:

# officially supported ubuntu
FROM ubuntu:12.04

# SETUP
RUN cd /tmp
RUN apt-get update -y
RUN apt-get install wget build-essential automake -y
RUN wget http://nodejs.org/dist/latest/node-v0.10.26.tar.gz
RUN wget http://nodejs.org/dist/latest/SHASUMS256.txt

# RUN checksum: exit on fail, continue on success
??? how ???

# INSTALL
RUN tar -xvf node-v0.10.26.tar.gz && cd node-v0.10.26
RUN ./configure && make && make install

# CLEANUP
apt-get autoremove --purge wget build-essential automake -y

Has the Docker community settled on a 'best practices' way of doing this?

Phenocryst answered 22/4, 2014 at 3:38 Comment(1)
One useful design goal: if a checksum fails, report what the checksum is (so it can be updated) rather than throwing away a (potentially large) download. I suspect that part of this answer would be "it depends on the ecosystem of what you're building". I think Ruby, for example, has this sort of thing baked in. RPM packages ought to be signed, etc. Still, it would be good to have this in the Docker Best PracticesTrommel
R
21

If any of the RUN commands return a non-zero code, the build will fail.

FROM fedora
RUN false

In the Dockerfile above, I'm just doing a quick test by running false. false is a linux utility that just sets a non-zero return code, handy for testing. As you can see, when I build that Dockerfile, it complains and fails out.

$ docker build .
Uploading context 12.29 kB
Uploading context
Step 0 : FROM fedora
 ---> 58394af37342
Step 1 : RUN false
 ---> Running in a5b9a4b37e25
2014/04/22 09:41:19 The command [/bin/sh -c false] returned a non-zero code: 1

Now that we know this, if we have the file and checksums in the image (which you appear to have via wget), we can test that they match up. Here is a quick and dirty version of this below, in which I generate a file and calculate its checksum before verifying it. In your example, you would obviously not be doing that, I just do it to show you how this works.

FROM fedora

# Create the text file
RUN echo ThisIsATest > echo.txt

# Calculate the checksum
RUN sha1sum echo.txt > sha1sums.txt

# Validate the checksum (this should pass)
RUN sha1sum -c sha1sums.txt

# Alter the text
RUN echo ThisShouldFail > echo.txt

# Validate the checksum (this should now fail)
RUN sha1sum -c sha1sums.txt

And if we run this...

$ docker build -no-cache .
Warning: '-no-cache' is deprecated, it will be removed soon. See usage.
Uploading context  12.8 kB
Uploading context
Step 0 : FROM fedora
 ---> 58394af37342
Step 1 : RUN echo ThisIsATest > echo.txt
 ---> Running in cd158d4e6d91
 ---> 4088b1b4945f
Step 2 : RUN sha1sum echo.txt > sha1sums.txt
 ---> Running in 5d028d901d94
 ---> c97b1d31a720
Step 3 : RUN sha1sum -c sha1sums.txt
 ---> Running in 44d119897164
echo.txt: OK
 ---> ca01d590cadd
Step 4 : RUN echo ThisShouldFail > echo.txt
 ---> Running in 87b575ac4052
 ---> 36bb5d8cf6d1
Step 5 : RUN sha1sum -c sha1sums.txt
 ---> Running in e20b7ac0c924
echo.txt: FAILED
WARNING: 1 computed checksum did NOT match
2014/04/22 10:29:07 The command [/bin/sh -c sha1sum -c sha1sums.txt] returned a non-zero code: 1
Rotberg answered 22/4, 2014 at 14:59 Comment(0)
B
11

1- Download your file and put it where you need it, then run:

sha256sum /path/to/file

Output:

255d...334  /path/to/file

2- copy the output and put it in your Dockerfile like this: (be careful about spaces between brackets)

RUN [ "255d...334  /path/to/file" = "$(sha256sum /usr/local/bin/confd)" ]

As @Todd mentioned, if the command responds non-zero the build will fail. you can use sha1sum or sha512sum aswell.

Bluecoat answered 15/11, 2018 at 17:14 Comment(1)
is the /usr/local/bin/confd what we should use or is that an example like /path/to/file?Granoff
H
7

I have set the checksum as a variable

ARG CHECKSUMKUBECTL="51f5679a0cb11a65f25c3479bbfdfd21c4d0acd8814d3cbaf5aaeea7682178a3820c3555b17ea6ee24470ac67ebfd0f78cc98513e5b526436494350be64bda69"

The following throws an exit code when they do not match, and an Ok if they match.

RUN echo "${CHECKSUMKUBECTL}  $BIN_DIR/kubectl" | sha512sum --check
Hecklau answered 19/4, 2022 at 8:8 Comment(4)
Could you provide a bit of reasoning why this is a better/preferable answer in certain situations, or follows "best practice" as the question asked?Gurevich
I think this is a good answer, but can be improved a bit for greater impact.Gurevich
For some reason, when I try this approach, ${CHECKSUMKUBECTL} is not expanded. It get’s inserted as a literal string in the argument passed to sh. Resulting in this error: The command '/bin/sh -c echo "${CHECKSUM} foo" | sha256sum --check' returned a non-zero code: 1Sumption
"Works for me" (using sha256sum --check)Skvorak
U
3

Note that it's possible to use docker itself nowadays to download and check files, obviating the need to use wget/curl in the image:

ADD --checksum=sha256:24454f830cdb571e2c4ad15481119c43b3cafd48dd869a9b2945d1036d1dc68d https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/linux-0.01.tar.gz /

Underbodice answered 8/4 at 10:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.