Directly build restic binary in release Docker container

This commit is contained in:
Michael Eischer 2023-05-19 17:43:11 +02:00
parent 2293835242
commit 43fa051546
4 changed files with 28 additions and 23 deletions

View file

@ -4,7 +4,6 @@
changelog/ changelog/
doc/ doc/
docker/ docker/
helpers/
# Files # Files
.gitignore .gitignore

View file

@ -1,20 +1,18 @@
FROM --platform=$BUILDPLATFORM alpine:latest as helper # the official binaries are cross-built from Linux running on an AMD64 host
# other architectures also seem to generate identical binaries but stay on the safe side
FROM --platform=linux/amd64 restic/builder:latest as helper
ARG VERSION
ARG TARGETOS ARG TARGETOS
ARG TARGETARCH ARG TARGETARCH
# add release binary for the appropriate platform COPY . /restic
COPY restic_${VERSION}_${TARGETOS}_${TARGETARCH}.bz2 / RUN go run helpers/build-release-binaries/main.go --platform $TARGETOS/$TARGETARCH --skip-compress
RUN apk add --update --no-cache bzip2 RUN mv /output/restic_${TARGETOS}_${TARGETARCH} /output/restic
RUN set -e && \
bzcat restic_${VERSION}_${TARGETOS}_${TARGETARCH}.bz2 > restic && \
chmod +x restic
FROM alpine:latest FROM alpine:latest
COPY --from=helper /restic /usr/bin COPY --from=helper /output/restic /usr/bin
RUN apk add --update --no-cache ca-certificates fuse openssh-client tzdata jq RUN apk add --update --no-cache ca-certificates fuse openssh-client tzdata jq
ENTRYPOINT ["/usr/bin/restic"] ENTRYPOINT ["/usr/bin/restic"]

View file

@ -22,6 +22,8 @@ var opts = struct {
OutputDir string OutputDir string
Tags string Tags string
PlatformSubset string PlatformSubset string
Platform string
SkipCompress bool
Version string Version string
}{} }{}
@ -31,6 +33,8 @@ func init() {
pflag.StringVarP(&opts.OutputDir, "output", "o", "/output", "path to the output `directory`") pflag.StringVarP(&opts.OutputDir, "output", "o", "/output", "path to the output `directory`")
pflag.StringVar(&opts.Tags, "tags", "", "additional build `tags`") pflag.StringVar(&opts.Tags, "tags", "", "additional build `tags`")
pflag.StringVar(&opts.PlatformSubset, "platform-subset", "", "specify `n/t` to only build this subset") pflag.StringVar(&opts.PlatformSubset, "platform-subset", "", "specify `n/t` to only build this subset")
pflag.StringVarP(&opts.Platform, "platform", "p", "", "specify `os/arch` to only build this specific platform")
pflag.BoolVar(&opts.SkipCompress, "skip-compress", false, "skip binary compression step")
pflag.StringVar(&opts.Version, "version", "", "use `x.y.z` as the version for output files") pflag.StringVar(&opts.Version, "version", "", "use `x.y.z` as the version for output files")
pflag.Parse() pflag.Parse()
} }
@ -188,7 +192,9 @@ func buildForTarget(sourceDir, outputDir, goos, goarch string) (filename string)
filename = build(sourceDir, outputDir, goos, goarch) filename = build(sourceDir, outputDir, goos, goarch)
touch(filepath.Join(outputDir, filename), mtime) touch(filepath.Join(outputDir, filename), mtime)
chmod(filepath.Join(outputDir, filename), 0755) chmod(filepath.Join(outputDir, filename), 0755)
filename = compress(goos, outputDir, filename) if !opts.SkipCompress {
filename = compress(goos, outputDir, filename)
}
return filename return filename
} }
@ -311,6 +317,8 @@ func main() {
if err != nil { if err != nil {
die("%s", err) die("%s", err)
} }
} else if opts.Platform != "" {
targets = buildPlatformList([]string{opts.Platform})
} }
sourceDir := abs(opts.SourceDir) sourceDir := abs(opts.SourceDir)

View file

@ -4,6 +4,7 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"fmt" "fmt"
"math/rand"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@ -409,19 +410,19 @@ func signFiles(filenames ...string) {
} }
} }
func updateDocker(outputDir, version string) string { func updateDocker(sourceDir, version string) string {
run("docker", "buildx", "create", "--name", "restic-release-builder", "--driver", "docker-container", "--bootstrap") r := rand.New(rand.NewSource(time.Now().UnixNano()))
builderName := fmt.Sprintf("restic-release-builder-%d", r.Int())
run("docker", "buildx", "create", "--name", builderName, "--driver", "docker-container", "--bootstrap")
cmds := "" buildCmd := fmt.Sprintf("docker buildx build --builder %s --platform linux/386,linux/amd64,linux/arm,linux/arm64 --pull -f docker/Dockerfile.release %q", builderName, sourceDir)
run("sh", "-c", buildCmd+" --no-cache")
publishCmds := ""
for _, tag := range []string{"restic/restic:latest", "restic/restic:" + version} { for _, tag := range []string{"restic/restic:latest", "restic/restic:" + version} {
cmd := fmt.Sprintf("docker buildx build --builder restic-release-builder --platform linux/386,linux/amd64,linux/arm,linux/arm64 --pull --tag %q -f docker/Dockerfile.release --build-arg VERSION=%q %q", tag, version, outputDir) publishCmds += buildCmd + fmt.Sprintf(" --tag %q --push\n", tag)
run("sh", "-c", cmd)
cmds += cmd + " --push\n"
} }
return publishCmds + "\ndocker buildx rm " + builderName
return cmds + "\ndocker buildx rm restic-release-builder"
} }
func tempdir(prefix string) string { func tempdir(prefix string) string {
@ -470,15 +471,14 @@ func main() {
extractTar(tarFilename, sourceDir) extractTar(tarFilename, sourceDir)
runBuild(sourceDir, opts.OutputDir, opts.Version) runBuild(sourceDir, opts.OutputDir, opts.Version)
rmdir(sourceDir)
sha256sums(opts.OutputDir, filepath.Join(opts.OutputDir, "SHA256SUMS")) sha256sums(opts.OutputDir, filepath.Join(opts.OutputDir, "SHA256SUMS"))
signFiles(filepath.Join(opts.OutputDir, "SHA256SUMS"), tarFilename) signFiles(filepath.Join(opts.OutputDir, "SHA256SUMS"), tarFilename)
dockerCmds := updateDocker(opts.OutputDir, opts.Version) dockerCmds := updateDocker(sourceDir, opts.Version)
msg("done, output dir is %v", opts.OutputDir) msg("done, output dir is %v", opts.OutputDir)
msg("now run:\n\ngit push --tags origin master\n%s\n", dockerCmds) msg("now run:\n\ngit push --tags origin master\n%s\n\nrm -rf %q", dockerCmds, sourceDir)
} }