I am building and push docker image from github actions to AWS. Both locally and on gitHub, I use the same command to build the image; however, it results to different image digests.
Command I used:
docker buildx build --build-arg DOCKER_REGISTRY=$ECR_REGISTRY --platform=linux/amd64 -t "$ECR_REGISTRY/$ECR_REPO_NAME:$LATEST_TAG" -t "$ECR_REGISTRY/$ECR_REPO_NAME:$ECR_TAG" -f Dockerfile .
My Dockerfile:
FROM node:16
RUN apt-get update
&& apt-get install -y chromium
fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1
--no-install-recommends
RUN mkdir -p /usr/src/app
RUN chown -R node: /usr/src/app
USER node
WORKDIR /usr/src/app
COPY --chown=node:node package.json package-lock.json /usr/src/app/
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
ENV PUPPETEER_EXECUTABLE_PATH /usr/bin/chromium
RUN npm config set registry https://registry.npmjs.org/
RUN npm install
# Copy crawl scripts
RUN mkdir -p /usr/src/app/scripts
RUN mkdir -p /usr/src/app/collected
COPY --chown=node:node lib/ /usr/src/app/lib/
COPY --chown=node:node scripts/ /usr/src/app/scripts/
2
Answers
You’re basing your image on a the
node:16
image, which is a moving target. Depending on when you last pulled that image, you might actually be usingnode:16.8.0
ornode:16.9.1
.Depending on which base image you start with, you’re going to end up with a final image digest.
If you want to make absolutely sure you’re building the same image in both environments, build using the digest rather than using a tag, e.g:
Docker image builds from docker build and buildx are not reproducible (at least for now). Everything pushed to a registry is content addressable, referenced by the digest of the content itself. The image digest is from a json manifest that contains digests of various components, similar to a Merkle tree. If any of those components change, the top level digest also changes. And the components include things that change. Among the things that change are:
RUN
steps, when those steps pull from external resources that give you the "latest" of some resource, e.g.apt-get install some_pkg
will change every time the package or one of it’s dependencies gets updatedI’ve been making efforts to modify an image after the fact, back dating timestamps, proxying all network requests, etc, but this is still pre-alpha and dependent on each image being built to find what changes between builds. For some of the debugging using regctl I’ve been adding
regctl manifest diff
,regctl blob diff-config
, andregctl blob diff-layer
. And then to change the image, there’s an experimentalregctl image mod
command.