deterministic OCI container build setup

This commit is contained in:
Lance Vick 2023-09-04 21:00:01 -07:00
parent 4885e07e45
commit f062697572
Signed by: lrvick
GPG Key ID: 8E47A1EC35A1551D
3 changed files with 1353 additions and 36 deletions

View File

@ -1,22 +1,118 @@
FROM ruby:3.2.2-alpine AS builder
LABEL stage=distrust-co-builder
RUN apk update && apk add g++ make git git-lfs
RUN mkdir -p /home
COPY Gemfile /home
COPY Gemfile.lock /home
COPY _vendor /home/_vendor
WORKDIR /home
ARG DEBIAN_HASH=b91baba9c2cae5edbe3b0ff50ae8f05157e3ae6f018372dcfc3aba224acb392b
ARG BUILD_ENV=pin
FROM debian@sha256:${DEBIAN_HASH} AS build_base
FROM build_base AS build_pin
ARG DEBIAN_RELEASE=bookworm
ARG REQUIRED_PACKAGES="git ruby ruby-dev ruby-bundler media-types"
ONBUILD RUN \
export date=$(date +"%Y%m%dT000000Z") \
&& export url=http://snapshot.debian.org/archive/debian \
&& export rel=${DEBIAN_RELEASE} \
&& echo "deb [trusted=yes] ${url}/${date} ${rel} main" \
> apt-sources.list \
&& echo "deb [trusted=yes] ${url}-security/${date} ${rel}-security main" \
> apt-sources.list \
&& echo "deb [trusted=yes] ${url}/${date} ${rel}-updates main" \
> apt-sources.list
ONBUILD RUN \
apt-get update \
&& apt-get install \
-y \
--download-only \
dpkg-dev bzip2 ${REQUIRED_PACKAGES} \
&& ( cd /var/cache/apt/archives \
&& find . -type f \( -iname \*.deb \) -exec sha256sum {} \; \
| sed 's/.\///g' \
| LC_ALL=C sort \
) > apt-hashes.list \
&& echo "Pinned APT packages:" \
&& cat apt-hashes.list
ONBUILD RUN \
for deb in /var/cache/apt/archives/*.deb; do \
package=$(dpkg-deb -f $deb Package); \
version=$(dpkg --info ${deb} | grep "^ Version: " | sed 's/^ Version: //g'); \
echo "${package}=${version}" >> apt-pins.list; \
done \
&& mkdir apt-packages \
&& mv /var/cache/apt/archives/*.deb apt-packages \
&& apt-get install -y bzip2 dpkg-dev \
&& dpkg-scanpackages apt-packages | bzip2 > apt-packages/Packages.bz2
FROM build_base AS build_fetch
ONBUILD COPY apt-hashes.list .
ONBUILD COPY apt-sources.list .
ONBUILD COPY apt-pins.list .
ONBUILD RUN \
rm -f /etc/apt/sources.list.d/* \
&& mv apt-sources.list /etc/apt/sources.list \
&& apt update -o Acquire::Check-Valid-Until=false \
&& apt-get install \
--download-only \
--allow-downgrades \
-o Acquire::Check-Valid-Until=false \
-y $(cat apt-pins.list) \
&& cd /var/cache/apt/archives \
&& find . -type f \( -iname \*.deb \) -exec sha256sum {} \; \
| sed 's/.\///g' \
| LC_ALL=C sort \
) > apt-hashes-compare.list \
&& diff apt-hashes.list apt-hashes-compare.list \
&& mkdir apt-packages \
&& mv /var/cache/apt/archives/*.deb apt-packages \
&& dpkg-scanpackages apt-packages | bzip2 > apt-packages/Packages.bz2
FROM build_base AS build_reproduce
ONBUILD COPY apt-hashes.list .
ONBUILD COPY apt-sources.list .
ONBUILD COPY apt-pins.list .
ONBUILD COPY apt-packages .
FROM build_${BUILD_ENV} as build
RUN \
rm -f /etc/apt/sources.list.d/* \
&& echo "deb [trusted=yes] file:///. apt-packages/" > /etc/apt/sources.list \
&& apt update -o Acquire::Check-Valid-Until=false \
&& apt-get install \
--allow-downgrades \
-y $(cat apt-pins.list)
FROM build as build-httpd
ARG BUSYBOX_REPO=https://git.busybox.net/busybox
ARG BUSYBOX_HASH=1a64f6a20aaf6ea4dbba68bbfa8cc1ab7e5c57c4 # 1.36.1
RUN \
git clone https://git.busybox.net/busybox \
&& git -C busybox checkout ${BUSYBOX_HASH} \
&& git -C busybox rev-parse --verify HEAD | grep -q ${BUSYBOX_HASH} || { \
echo 'Error: Git ref/branch collision.'; exit 1; \
}
COPY config/busybox.config busybox/.config
RUN \
echo "building busybox httpd" \
&& cd busybox \
&& make \
&& bash make_single_applets.sh \
&& mv busybox_HTTPD ../httpd
FROM build as build-site
RUN mkdir build
WORKDIR build
COPY . .
RUN bundle install
COPY . /home
RUN jekyll build
RUN jekyll build
FROM debian:bookworm AS mime-types
RUN apt-get update && apt-get install -y media-types
FROM build as build-rootfs
RUN mkdir -p rootfs/etc \
&& echo "nogroup:*:100:nobody" > rootfs/etc/group \
&& echo "nobody:*:100:100:::" > rootfs/etc/passwd
RUN echo 'types {' > /tmp/mime.types
RUN sed -e '/^$/d' -e 's/$/;/' /etc/mime.types >> /tmp/mime.types
RUN echo '}' >> /tmp/mime.types
FROM nginx
COPY --from=builder /home/_site /usr/share/nginx/html
COPY --from=mime-types /tmp/mime.types /etc/nginx/mime.types
FROM scratch
COPY --from=build-rootfs --chown=100:100 rootfs /
COPY --from=build-site build/_site static
COPY --from=build-httpd httpd .
USER 100:100
EXPOSE 8080
WORKDIR static
ENTRYPOINT ["/httpd"]
CMD ["-f","-v"]

View File

@ -1,22 +1,44 @@
.PHONY: build
build:
# Build Docker image
docker build -t distrust-co .
.PHONY: fullclean
fullclean: clean
docker rmi distrust-co || true
docker image prune -f --filter label=stage=distrust-co-builder || true
.PHONY: clean
clean:
rm -r _site || true
_site: build
mkdir -p _site
docker run distrust-co tar c -C /usr/share/nginx/html . | tar x -C _site
rm -r _site
.PHONY: serve
serve: build
# Run Docker container with listener for current dir and port mapping
docker run --rm -p 0.0.0.0:4000:80 -it distrust-co
docker run --rm -p 8080:8080/tcp -it distrust/website
.PHONY: build
build: out/website.oci.tar
config/apt-packages.list \
config/apt-hashes.list \
config/apt-sources.list \
fetch/apt/Packages.bz2:
buildah build \
-f Dockerfile \
-t distrust/website \
--timestamp 1 \
--format oci \
--arch amd64 \
--output cache/reproduce
cp cache/reproduce/apt-packages/* fetch/apt/
cp cache/reproduce/apt-*.list config
out/website.oci.tar:
buildah build \
-f Dockerfile \
-t distrust/website \
--timestamp 1 \
--format oci \
--arch amd64 \
buildah push \
distrust/website \
oci:cache/oci
tar \
-C cache/oci \
--sort=name \
--mtime='@0' \
--owner=0 \
--group=0 \
--numeric-owner \
-cf $@ \
.

1199
config/busybox.config Normal file

File diff suppressed because it is too large Load Diff