Skip to content
This repository has been archived by the owner on Jun 10, 2024. It is now read-only.

Commit

Permalink
Merge pull request #15 from kpcyrd/archlinux-docker
Browse files Browse the repository at this point in the history
Add support for Arch Linux Dockerfiles
  • Loading branch information
AkihiroSuda authored Oct 25, 2022
2 parents 879a621 + 206c7ea commit dd0b611
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 13 deletions.
46 changes: 46 additions & 0 deletions pkg/distro/arch/Dockerfile.generate-hash.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# syntax = docker.io/docker/dockerfile:1.4@sha256:9ba7531bd80fb0a858632727cf7a112fbfd19b17e94c4e84ced81e24ef1a0dbc
# Generated by repro-get.

# "Timetraveling" Dockerfile for generating the hash file with a past snapshot.

# ⚠️ EXPERIMENTAL ⚠️

# Usage:
# ----------------------------------------------------------
# export DOCKER_BUILDKIT=1
# docker build --output . -f Dockerfile.generate-hash .
# ----------------------------------------------------------

# Output files:
# - SHA256SUMS-{{.OCIArchDashVariant}}: the hash file

ARG BASE_IMAGE={{.BaseImage}} # {{.BaseImageOrig}}
ARG PACKAGES="{{join .Packages " "}}"

ARG REPRO_GET_VERSION={{.ReproGetVersion}}
ARG REPRO_GET_SHA256SUMS_SHA256SUM={{.ReproGetSHASHA}}
{{snippet "fetch-repro-get"}}

FROM --platform=${TARGETPLATFORM} ${BASE_IMAGE} AS generate-hash
ARG PACKAGES
ARG TARGETARCH
ARG TARGETVARIANT
SHELL ["/bin/bash", "-c"]
RUN \
--mount=type=cache,target=/var/cache/pacman \
--mount=type=cache,target=/var/cache/repro-get \
--mount=type=bind,from=repro-get,source=/repro-get.linux-${TARGETARCH}${TARGETVARIANT:+-${TARGETVARIANT}},target=/usr/local/bin/repro-get \
set -eux -o pipefail; \
export SOURCE_DATE_EPOCH="$(stat --format=%Y /var/log/pacman.log)" && \
date -d "@${SOURCE_DATE_EPOCH}" '+Server = https://archive.archlinux.org/repos/%Y/%m/%d/$repo/os/$arch' > /etc/pacman.d/mirrorlist && \
pacman -Sy && \
mkdir -p /out && \
/usr/local/bin/repro-get hash generate >"/out/SHA256SUMS-preinstalled" && \
pacman -Su --noconfirm ${PACKAGES} && \
/usr/local/bin/repro-get hash generate --dedupe "/out/SHA256SUMS-preinstalled" >"/out/SHA256SUMS-${TARGETARCH}${TARGETVARIANT:+-${TARGETVARIANT}}" && \
rm -f "/out/SHA256SUMS-preinstalled" && \
chmod 444 /out/* && \
touch --date=@${SOURCE_DATE_EPOCH} /out/*

FROM scratch
COPY --from=generate-hash /out/ /
44 changes: 44 additions & 0 deletions pkg/distro/arch/Dockerfile.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# syntax = docker.io/docker/dockerfile:1.4@sha256:9ba7531bd80fb0a858632727cf7a112fbfd19b17e94c4e84ced81e24ef1a0dbc
# Generated by repro-get.

# Dockerfile for building a container image using the hash file.

# ⚠️ EXPERIMENTAL ⚠️

# Usage:
# Make sure that the hash file "SHA256SUMS-{{.OCIArchDashVariant}}" is present in the current directory.
# ----------------------------------------------------------
# export DOCKER_BUILDKIT=1
# docker build .
# ----------------------------------------------------------

ARG BASE_IMAGE={{.BaseImage}} # {{.BaseImageOrig}}
ARG REPRO_GET_PROVIDER={{join .Providers ","}}

ARG REPRO_GET_VERSION={{.ReproGetVersion}}
ARG REPRO_GET_SHA256SUMS_SHA256SUM={{.ReproGetSHASHA}}
{{snippet "fetch-repro-get"}}

FROM --platform=${TARGETPLATFORM} ${BASE_IMAGE}
ARG TARGETARCH
ARG TARGETVARIANT
ARG REPRO_GET_PROVIDER
SHELL ["/bin/bash", "-c"]
# The cache dir is mounted under a directory inside tmpfs (/dev/*), so that the mount point directory does not remain in the image
RUN \
--mount=type=cache,target=/dev/.cache/repro-get \
--mount=type=bind,from=repro-get,source=/repro-get.linux-${TARGETARCH}${TARGETVARIANT:+-${TARGETVARIANT}},target=/usr/local/bin/repro-get \
--mount=type=bind,source=.,target=/mnt \
set -eux -o pipefail ; \
export SOURCE_DATE_EPOCH="$(stat --format=%Y /var/log/pacman.log)" && \
pacman-key --init && \
/usr/local/bin/repro-get --provider="${REPRO_GET_PROVIDER}" --cache=/dev/.cache/repro-get install "/mnt/SHA256SUMS-${TARGETARCH}${TARGETVARIANT:+-${TARGETVARIANT}}" && \
: Removing web of trust private key && \
rm -rf /etc/pacman.d/gnupg && \
: Remove unneeded files for reproducibility && \
find /var/log -name '*.log' -or -name '*.log.*' -newermt "@${SOURCE_DATE_EPOCH}" -not -type d | xargs rm -f && \
find /run /tmp -newermt "@${SOURCE_DATE_EPOCH}" -not -type d -xdev | xargs rm -f && \
rm -f /var/cache/ldconfig/* && \
: Reset the timestamp for reproducibility && \
find $( ls / | grep -E -v "^(dev|mnt|proc|sys)$" ) -newermt "@${SOURCE_DATE_EPOCH}" -writable -xdev | xargs touch --date="@${SOURCE_DATE_EPOCH}" --no-dereference
SHELL ["/bin/sh", "-c"]
45 changes: 32 additions & 13 deletions pkg/distro/arch/arch.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package arch
import (
"bufio"
"context"
_ "embed"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -252,8 +253,7 @@ func (d *arch) InstallPackages(ctx context.Context, c *cache.Cache, pkgs []files
if err != nil {
return err
}
args := []string{"--verify"}
logrus.Infof("Running '%s %s ...' with %d signatures", cmdName, strings.Join(args, " "), len(opts.AuxFiles))
logrus.Infof("Running '%s --verify ...' with %d signatures", cmdName, len(opts.AuxFiles))

pkgSigMap := make(map[string]string) // key: pkg basename, val: sig basename
for _, f := range opts.AuxFiles {
Expand All @@ -262,21 +262,22 @@ func (d *arch) InstallPackages(ctx context.Context, c *cache.Cache, pkgs []files
}
pkgSigMap[strings.TrimSuffix(f.Basename, ".sig")] = f.Basename
file := filepath.Join(tmpDir, f.Basename) // securejoin can't be used for symlinks; f.Basename is verified
args = append(args, file)
}
cmd := exec.CommandContext(ctx, cmdName, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
logrus.Debugf("Running %v", cmd.Args)
if err := cmd.Run(); err != nil {
return err
args := []string{"--verify", file}

cmd := exec.CommandContext(ctx, cmdName, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
logrus.Debugf("Running %v", cmd.Args)
if err := cmd.Run(); err != nil {
return err
}
}

cmdName, err = exec.LookPath("pacman")
if err != nil {
return err
}
args = []string{"-Uv", "--noconfirm"}
args := []string{"-Uv", "--noconfirm"}
logrus.Infof("Running '%s %s ...' with %d packages", cmdName, strings.Join(args, " "), len(pkgs))
for _, f := range pkgs {
if _, ok := pkgSigMap[f.Basename]; !ok {
Expand All @@ -285,7 +286,7 @@ func (d *arch) InstallPackages(ctx context.Context, c *cache.Cache, pkgs []files
file := filepath.Join(tmpDir, f.Basename) // securejoin can't be used for symlinks; f.Basename is verified
args = append(args, file)
}
cmd = exec.CommandContext(ctx, cmdName, args...)
cmd := exec.CommandContext(ctx, cmdName, args...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
Expand All @@ -296,6 +297,24 @@ func (d *arch) InstallPackages(ctx context.Context, c *cache.Cache, pkgs []files
return nil
}

var (
//go:embed Dockerfile.generate-hash.tmpl
dockerfileGenerateHashTmpl string

//go:embed Dockerfile.tmpl
dockerfileTmpl string
)

func (d *arch) GenerateDockerfile(ctx context.Context, dir string, args distro.DockerfileTemplateArgs, opts distro.DockerfileOpts) error {
return distro.ErrNotImplemented
if opts.GenerateHash {
f := filepath.Join(dir, "Dockerfile.generate-hash") // no need to use securejoin (const)
if err := args.WriteToFile(f, dockerfileGenerateHashTmpl); err != nil {
return fmt.Errorf("failed to generate %q: %w", f, err)
}
}
f := filepath.Join(dir, "Dockerfile") // no need to use securejoin (const)
if err := args.WriteToFile(f, dockerfileTmpl); err != nil {
return fmt.Errorf("failed to generate %q: %w", f, err)
}
return nil
}

0 comments on commit dd0b611

Please sign in to comment.