Skip to content

Commit 653a30f

Browse files
authored
Merge pull request ethereum#23082 from karalabe/docker-flat-publish
travis, Dockerfile, build: docker build and multi-arch publish combo
2 parents da000c8 + 0f2347d commit 653a30f

File tree

4 files changed

+115
-22
lines changed

4 files changed

+115
-22
lines changed

.travis.yml

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ jobs:
2424
script:
2525
- go run build/ci.go lint
2626

27-
# These builders create the Docker sub-images for multi-arch push
27+
# These builders create the Docker sub-images for multi-arch push and each
28+
# will attempt to push the multi-arch image if they are the last builder
2829
- stage: build
2930
if: type = push
3031
os: linux
@@ -38,7 +39,7 @@ jobs:
3839
git:
3940
submodules: false # avoid cloning ethereum/tests
4041
script:
41-
- go run build/ci.go docker -image -upload karalabe/geth-docker-test
42+
- go run build/ci.go docker -image -manifest amd64,arm64 -upload karalabe/geth-docker-test
4243

4344
- stage: build
4445
if: type = push
@@ -53,24 +54,7 @@ jobs:
5354
git:
5455
submodules: false # avoid cloning ethereum/tests
5556
script:
56-
- go run build/ci.go docker -image -upload karalabe/geth-docker-test
57-
58-
# This builder does the Docker Hub multi-arch image
59-
- stage: publish
60-
if: type = push
61-
os: linux
62-
dist: bionic
63-
go: 1.16.x
64-
env:
65-
- docker
66-
services:
67-
- docker
68-
git:
69-
submodules: false # avoid cloning ethereum/tests
70-
before_install:
71-
- export DOCKER_CLI_EXPERIMENTAL=enabled
72-
script:
73-
- go run build/ci.go docker -manifest amd64,arm64 -upload karalabe/geth-docker-test
57+
- go run build/ci.go docker -image -manifest amd64,arm64 -upload karalabe/geth-docker-test
7458

7559
# This builder does the Ubuntu PPA upload
7660
- stage: build

Dockerfile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# Support setting various labels on the final image
2+
ARG COMMIT=""
3+
ARG VERSION=""
4+
ARG BUILDNUM=""
5+
16
# Build Geth in a stock Go builder container
27
FROM golang:1.16-alpine as builder
38

@@ -14,3 +19,10 @@ COPY --from=builder /go-ethereum/build/bin/geth /usr/local/bin/
1419

1520
EXPOSE 8545 8546 30303 30303/udp
1621
ENTRYPOINT ["geth"]
22+
23+
# Add some metadata labels to help programatic image consumption
24+
ARG COMMIT=""
25+
ARG VERSION=""
26+
ARG BUILDNUM=""
27+
28+
LABEL commit="$COMMIT" version="$VERSION" buildnum="$BUILDNUM"

Dockerfile.alltools

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# Support setting various labels on the final image
2+
ARG COMMIT=""
3+
ARG VERSION=""
4+
ARG BUILDNUM=""
5+
16
# Build Geth in a stock Go builder container
27
FROM golang:1.16-alpine as builder
38

@@ -13,3 +18,10 @@ RUN apk add --no-cache ca-certificates
1318
COPY --from=builder /go-ethereum/build/bin/* /usr/local/bin/
1419

1520
EXPOSE 8545 8546 30303 30303/udp
21+
22+
# Add some metadata labels to help programatic image consumption
23+
ARG COMMIT=""
24+
ARG VERSION=""
25+
ARG BUILDNUM=""
26+
27+
LABEL commit="$COMMIT" version="$VERSION" buildnum="$BUILDNUM"

build/ci.go

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import (
5454
"path/filepath"
5555
"regexp"
5656
"runtime"
57+
"strconv"
5758
"strings"
5859
"time"
5960

@@ -495,14 +496,45 @@ func doDocker(cmdline []string) {
495496
}
496497
// If architecture specific image builds are requested, build and push them
497498
if *image {
498-
build.MustRunCommand("docker", "build", "--tag", fmt.Sprintf("%s:TAG", *upload), ".")
499-
build.MustRunCommand("docker", "build", "--tag", fmt.Sprintf("%s:alltools-TAG", *upload), "-f", "Dockerfile.alltools", ".")
499+
build.MustRunCommand("docker", "build", "--build-arg", "COMMIT="+env.Commit, "--build-arg", "VERSION="+params.VersionWithMeta, "--build-arg", "BUILDNUM="+env.Buildnum, "--tag", fmt.Sprintf("%s:TAG", *upload), ".")
500+
build.MustRunCommand("docker", "build", "--build-arg", "COMMIT="+env.Commit, "--build-arg", "VERSION="+params.VersionWithMeta, "--build-arg", "BUILDNUM="+env.Buildnum, "--tag", fmt.Sprintf("%s:alltools-TAG", *upload), "-f", "Dockerfile.alltools", ".")
500501

501502
// Tag and upload the images to Docker Hub
502503
for _, tag := range tags {
503504
gethImage := fmt.Sprintf("%s:%s-%s", *upload, tag, runtime.GOARCH)
504505
toolImage := fmt.Sprintf("%s:alltools-%s-%s", *upload, tag, runtime.GOARCH)
505506

507+
// If the image already exists (non version tag), check the build
508+
// number to prevent overwriting a newer commit if concurrent builds
509+
// are running. This is still a tiny bit racey if two published are
510+
// done at the same time, but that's extremely unlikely even on the
511+
// master branch.
512+
for _, img := range []string{gethImage, toolImage} {
513+
if exec.Command("docker", "pull", img).Run() != nil {
514+
continue // Generally the only failure is a missing image, which is good
515+
}
516+
buildnum, err := exec.Command("docker", "inspect", "--format", "{{index .Config.Labels \"buildnum\"}}", img).CombinedOutput()
517+
if err != nil {
518+
log.Fatalf("Failed to inspect container: %v\nOutput: %s", err, string(buildnum))
519+
}
520+
buildnum = bytes.TrimSpace(buildnum)
521+
522+
if len(buildnum) > 0 && len(env.Buildnum) > 0 {
523+
oldnum, err := strconv.Atoi(string(buildnum))
524+
if err != nil {
525+
log.Fatalf("Failed to parse old image build number: %v", err)
526+
}
527+
newnum, err := strconv.Atoi(env.Buildnum)
528+
if err != nil {
529+
log.Fatalf("Failed to parse current build number: %v", err)
530+
}
531+
if oldnum > newnum {
532+
log.Fatalf("Current build number %d not newer than existing %d", newnum, oldnum)
533+
} else {
534+
log.Printf("Updating %s from build %d to %d", img, oldnum, newnum)
535+
}
536+
}
537+
}
506538
build.MustRunCommand("docker", "image", "tag", fmt.Sprintf("%s:TAG", *upload), gethImage)
507539
build.MustRunCommand("docker", "image", "tag", fmt.Sprintf("%s:alltools-TAG", *upload), toolImage)
508540
build.MustRunCommand("docker", "push", gethImage)
@@ -511,6 +543,59 @@ func doDocker(cmdline []string) {
511543
}
512544
// If multi-arch image manifest push is requested, assemble it
513545
if len(*manifest) != 0 {
546+
// Since different architectures are pushed by different builders, wait
547+
// until all required images are updated.
548+
var mismatch bool
549+
for i := 0; i < 2; i++ { // 2 attempts, second is race check
550+
mismatch = false // hope there's no mismatch now
551+
552+
for _, tag := range tags {
553+
for _, arch := range strings.Split(*manifest, ",") {
554+
gethImage := fmt.Sprintf("%s:%s-%s", *upload, tag, arch)
555+
toolImage := fmt.Sprintf("%s:alltools-%s-%s", *upload, tag, arch)
556+
557+
for _, img := range []string{gethImage, toolImage} {
558+
if out, err := exec.Command("docker", "pull", img).CombinedOutput(); err != nil {
559+
log.Printf("Required image %s unavailable: %v\nOutput: %s", img, err, out)
560+
mismatch = true
561+
break
562+
}
563+
buildnum, err := exec.Command("docker", "inspect", "--format", "{{index .Config.Labels \"buildnum\"}}", img).CombinedOutput()
564+
if err != nil {
565+
log.Fatalf("Failed to inspect container: %v\nOutput: %s", err, string(buildnum))
566+
}
567+
buildnum = bytes.TrimSpace(buildnum)
568+
569+
if string(buildnum) != env.Buildnum {
570+
log.Printf("Build number mismatch on %s: want %s, have %s", img, env.Buildnum, buildnum)
571+
mismatch = true
572+
break
573+
}
574+
}
575+
if mismatch {
576+
break
577+
}
578+
}
579+
if mismatch {
580+
break
581+
}
582+
}
583+
if mismatch {
584+
// Build numbers mismatching, retry in a short time to
585+
// avoid concurrent failes in both publisher images. If
586+
// however the retry failed too, it means the concurrent
587+
// builder is still crunching, let that do the publish.
588+
if i == 0 {
589+
time.Sleep(30 * time.Second)
590+
}
591+
continue
592+
}
593+
break
594+
}
595+
if mismatch {
596+
log.Println("Relinquishing publish to other builder")
597+
return
598+
}
514599
// Assemble and push the Geth manifest image
515600
for _, tag := range tags {
516601
gethImage := fmt.Sprintf("%s:%s", *upload, tag)

0 commit comments

Comments
 (0)