refactor(ci): simplify Dockerfile and add docker image testing (#10021)
Piotr Galar committed
Jul 27, 2023 at 18:53 UTC
c5868a86be16e3c0cd31f95da194060670407bdf
4 files changed
+96
-45
.github/workflows/docker-build.yml
+2
@@ -1,3 +1,4 @@
1
+# If we decide to run build-image.yml on every PR, we could deprecate this workflow.
2
name: Docker Build
3
4
on:
@@ -30,3 +31,4 @@ jobs:
31
go-version: 1.19.x
32
- uses: actions/checkout@v3
33
- run: docker build -t $IMAGE_NAME:$WIP_IMAGE_TAG .
34
+ - run: docker run --rm $IMAGE_NAME:$WIP_IMAGE_TAG --version
.github/workflows/docker-image.yml
+59
-2
@@ -2,6 +2,16 @@ name: Docker Push
2
3
on:
4
workflow_dispatch:
5
+ inputs:
6
+ push:
7
+ description: 'Push to Docker Hub'
8
+ required: true
9
+ default: 'false'
10
+ # # If we decide to build all images on every PR, we should make sure that
11
+ # # they are NOT pushed to Docker Hub.
12
+ # pull_request:
13
+ # paths-ignore:
14
+ # - '**/*.md'
15
push:
16
branches:
17
- 'master'
@@ -53,7 +63,54 @@ jobs:
63
username: ${{ vars.DOCKER_USERNAME }}
64
password: ${{ secrets.DOCKER_PASSWORD }}
65
56
- - name: Build Docker image and publish to Docker Hub
66
+ # We have to build each platform separately because when using multi-arch
67
+ # builds, only one platform is being loaded into the cache. This would
68
+ # prevent us from testing the other platforms.
69
+ - name: Build Docker image (linux/amd64)
70
+ uses: docker/build-push-action@v4
71
+ with:
72
+ platforms: linux/amd64
73
+ context: .
74
+ push: false
75
+ load: true
76
+ file: ./Dockerfile
77
+ tags: ${{ env.IMAGE_NAME }}:linux-amd64
78
+ cache-from: type=local,src=/tmp/.buildx-cache
79
+ cache-to: type=local,dest=/tmp/.buildx-cache-new
80
+
81
+ - name: Build Docker image (linux/arm/v7)
82
+ uses: docker/build-push-action@v4
83
+ with:
84
+ platforms: linux/arm/v7
85
+ context: .
86
+ push: false
87
+ load: true
88
+ file: ./Dockerfile
89
+ tags: ${{ env.IMAGE_NAME }}:linux-arm-v7
90
+ cache-from: type=local,src=/tmp/.buildx-cache
91
+ cache-to: type=local,dest=/tmp/.buildx-cache-new
92
+
93
+ - name: Build Docker image (linux/arm64/v8)
94
+ uses: docker/build-push-action@v4
95
+ with:
96
+ platforms: linux/arm64/v8
97
+ context: .
98
+ push: false
99
+ load: true
100
+ file: ./Dockerfile
101
+ tags: ${{ env.IMAGE_NAME }}:linux-arm64-v8
102
+ cache-from: type=local,src=/tmp/.buildx-cache
103
+ cache-to: type=local,dest=/tmp/.buildx-cache-new
104
+
105
+ # We test all the images on amd64 host here. This uses QEMU to emulate
106
+ # the other platforms.
107
+ - run: docker run --rm $IMAGE_NAME:linux-amd64 --version
108
+ - run: docker run --rm $IMAGE_NAME:linux-arm-v7 --version
109
+ - run: docker run --rm $IMAGE_NAME:linux-arm64-v8 --version
110
+
111
+ # This will only push the previously built images.
112
+ - if: github.event_name != 'workflow_dispatch' || github.event.inputs.push == 'true'
113
+ name: Publish to Docker Hub
114
uses: docker/build-push-action@v4
115
with:
116
platforms: linux/amd64,linux/arm/v7,linux/arm64/v8
@@ -61,7 +118,7 @@ jobs:
118
push: true
119
file: ./Dockerfile
120
tags: "${{ steps.tags.outputs.value }}"
64
- cache-from: type=local,src=/tmp/.buildx-cache
121
+ cache-from: type=local,src=/tmp/.buildx-cache-new
122
cache-to: type=local,dest=/tmp/.buildx-cache-new
123
124
# https://github.com/docker/build-push-action/issues/252
Dockerfile
+33
-41
@@ -1,16 +1,6 @@
1
-FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.19-buster
2
-LABEL maintainer="Steven Allen <steven@stebalien.com>"
1
+FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.19-buster AS builder
2
4
-ARG TARGETPLATFORM
5
-ARG BUILDPLATFORM
6
-ARG TARGETOS
7
-ARG TARGETARCH
8
-
9
-# Install deps
10
-RUN apt-get update && apt-get install -y \
11
- libssl-dev \
12
- ca-certificates \
13
- fuse
3
+ARG TARGETPLATFORM TARGETOS TARGETARCH
4
5
ENV SRC_DIR /kubo
6
@@ -31,38 +21,40 @@ RUN cd $SRC_DIR \
21
&& mkdir -p .git/objects \
22
&& GOOS=$TARGETOS GOARCH=$TARGETARCH GOFLAGS=-buildvcs=false make build GOTAGS=openssl IPFS_PLUGINS=$IPFS_PLUGINS
23
34
-# Get su-exec, a very minimal tool for dropping privileges,
35
-# and tini, a very minimal init daemon for containers
36
-ENV SUEXEC_VERSION v0.2
37
-ENV TINI_VERSION v0.19.0
24
+# Using Debian Buster because the version of busybox we're using is based on it
25
+# and we want to make sure the libraries we're using are compatible. That's also
26
+# why we're running this for the target platform.
27
+FROM debian:buster-slim AS utilities
28
RUN set -eux; \
39
- dpkgArch="$(dpkg --print-architecture)"; \
40
- case "${dpkgArch##*-}" in \
41
- "amd64" | "armhf" | "arm64") tiniArch="tini-static-$dpkgArch" ;;\
42
- *) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; \
43
- esac; \
44
- cd /tmp \
45
- && git clone https://github.com/ncopa/su-exec.git \
46
- && cd su-exec \
47
- && git checkout -q $SUEXEC_VERSION \
48
- && make su-exec-static \
49
- && cd /tmp \
50
- && wget -q -O tini https://github.com/krallin/tini/releases/download/$TINI_VERSION/$tiniArch \
51
- && chmod +x tini
29
+ apt-get update; \
30
+ apt-get install -y \
31
+ tini \
32
+ # Using gosu (~2MB) instead of su-exec (~20KB) because it's easier to
33
+ # install on Debian. Useful links:
34
+ # - https://github.com/ncopa/su-exec#why-reinvent-gosu
35
+ # - https://github.com/tianon/gosu/issues/52#issuecomment-441946745
36
+ gosu \
37
+ # This installs fusermount which we later copy over to the target image.
38
+ fuse \
39
+ ca-certificates \
40
+ # This installs libssl.so and libcrypto.so which we later copy over to the
41
+ # target image. We need these to be able to use the OpenSSL plugin.
42
+ libssl-dev \
43
+ ; \
44
+ rm -rf /var/lib/apt/lists/*
45
46
# Now comes the actual target image, which aims to be as small as possible.
54
-FROM --platform=${BUILDPLATFORM:-linux/amd64} busybox:1.31.1-glibc
55
-LABEL maintainer="Steven Allen <steven@stebalien.com>"
47
+FROM busybox:1.31.1-glibc
48
49
# Get the ipfs binary, entrypoint script, and TLS CAs from the build container.
50
ENV SRC_DIR /kubo
59
-COPY --from=0 $SRC_DIR/cmd/ipfs/ipfs /usr/local/bin/ipfs
60
-COPY --from=0 $SRC_DIR/bin/container_daemon /usr/local/bin/start_ipfs
61
-COPY --from=0 $SRC_DIR/bin/container_init_run /usr/local/bin/container_init_run
62
-COPY --from=0 /tmp/su-exec/su-exec-static /sbin/su-exec
63
-COPY --from=0 /tmp/tini /sbin/tini
64
-COPY --from=0 /bin/fusermount /usr/local/bin/fusermount
65
-COPY --from=0 /etc/ssl/certs /etc/ssl/certs
51
+COPY --from=builder $SRC_DIR/cmd/ipfs/ipfs /usr/local/bin/ipfs
52
+COPY --from=builder $SRC_DIR/bin/container_daemon /usr/local/bin/start_ipfs
53
+COPY --from=builder $SRC_DIR/bin/container_init_run /usr/local/bin/container_init_run
54
+COPY --from=utilities /usr/sbin/gosu /sbin/gosu
55
+COPY --from=utilities /usr/bin/tini /sbin/tini
56
+COPY --from=utilities /bin/fusermount /usr/local/bin/fusermount
57
+COPY --from=utilities /etc/ssl/certs /etc/ssl/certs
58
59
# Add suid bit on fusermount so it will run properly
60
RUN chmod 4755 /usr/local/bin/fusermount
@@ -71,11 +63,11 @@ RUN chmod 4755 /usr/local/bin/fusermount
63
RUN chmod 0755 /usr/local/bin/start_ipfs
64
65
# This shared lib (part of glibc) doesn't seem to be included with busybox.
74
-COPY --from=0 /lib/*-linux-gnu*/libdl.so.2 /lib/
66
+COPY --from=utilities /lib/*-linux-gnu*/libdl.so.2 /lib/
67
68
# Copy over SSL libraries.
77
-COPY --from=0 /usr/lib/*-linux-gnu*/libssl.so* /usr/lib/
78
-COPY --from=0 /usr/lib/*-linux-gnu*/libcrypto.so* /usr/lib/
69
+COPY --from=utilities /usr/lib/*-linux-gnu*/libssl.so* /usr/lib/
70
+COPY --from=utilities /usr/lib/*-linux-gnu*/libcrypto.so* /usr/lib/
71
72
# Swarm TCP; should be exposed to the public
73
EXPOSE 4001
bin/container_daemon
+2
-2
@@ -7,9 +7,9 @@ repo="$IPFS_PATH"
7
if [ "$(id -u)" -eq 0 ]; then
8
echo "Changing user to $user"
9
# ensure folder is writable
10
- su-exec "$user" test -w "$repo" || chown -R -- "$user" "$repo"
10
+ gosu "$user" test -w "$repo" || chown -R -- "$user" "$repo"
11
# restart script with new privileges
12
- exec su-exec "$user" "$0" "$@"
12
+ exec gosu "$user" "$0" "$@"
13
fi
14
15
# 2nd invocation with regular user