Docker multiarch image (#703)

fixes #257 .
fixes #350

---------

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
This commit is contained in:
饺子w (Yumechi) 2024-10-22 16:14:59 -05:00 committed by GitHub
parent 58084c8dea
commit ec02350587
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 141 additions and 88 deletions

9
.dockerignore Normal file
View File

@ -0,0 +1,9 @@
vendor/
.idea/
build/
licenses/
coverage.txt
data/
images/
.git/
*/node_modules/

View File

@ -31,27 +31,32 @@ jobs:
- if: startsWith(github.ref, 'refs/tags/v') - if: startsWith(github.ref, 'refs/tags/v')
run: | run: |
export LD_FLAGS="-w -s -X main.Version=$VERSION -X main.BuildDate=$(date "+%F-%T") -X main.Commit=$(git rev-parse --verify HEAD) -X main.Mode=prod" export LD_FLAGS="-w -s -X main.Version=$VERSION -X main.BuildDate=$(date "+%F-%T") -X main.Commit=$(git rev-parse --verify HEAD) -X main.Mode=prod"
echo "LD_FLAGS=$LD_FLAGS" >> $GITHUB_ENV
make build make build
sudo chown -R $UID build sudo chown -R $UID build
make package-zip make package-zip
ls -lath build ls -lath build
make build-docker - if: startsWith(github.ref, 'refs/tags/v')
docker image ls name: Set up Docker Buildx
echo "$DOCKER_PASS" | docker login --username "$DOCKER_USER" --password-stdin uses: docker/setup-buildx-action@v3
echo "$DOCKER_GHCR_PASS" | docker login ghcr.io --username "$DOCKER_GHCR_USER" --password-stdin - if: startsWith(github.ref, 'refs/tags/v')
docker push --all-tags gotify/server name: Set up QEMU
docker push --all-tags gotify/server-arm7 uses: docker/setup-qemu-action@v2
docker push --all-tags gotify/server-arm64 - if: startsWith(github.ref, 'refs/tags/v')
docker push --all-tags gotify/server-riscv64 uses: docker/login-action@v3
docker push --all-tags ghcr.io/gotify/server with:
docker push --all-tags ghcr.io/gotify/server-arm7 username: ${{ secrets.DOCKER_USER }}
docker push --all-tags ghcr.io/gotify/server-arm64 password: ${{ secrets.DOCKER_PASS }}
docker push --all-tags ghcr.io/gotify/server-riscv64 - if: startsWith(github.ref, 'refs/tags/v')
env: uses: docker/login-action@v3
DOCKER_USER: ${{ secrets.DOCKER_USER }} with:
DOCKER_PASS: ${{ secrets.DOCKER_PASS }} registry: ghcr.io
DOCKER_GHCR_USER: ${{ secrets.DOCKER_GHCR_USER }} username: ${{ secrets.DOCKER_GHCR_USER }}
DOCKER_GHCR_PASS: ${{ secrets.DOCKER_GHCR_PASS }} password: ${{ secrets.DOCKER_GHCR_PASS }}
- if: startsWith(github.ref, 'refs/tags/v')
run: |
make DOCKER_BUILD_PUSH=true build-docker
- if: startsWith(github.ref, 'refs/tags/v') - if: startsWith(github.ref, 'refs/tags/v')
uses: svenstaro/upload-release-action@v2 uses: svenstaro/upload-release-action@v2
with: with:

View File

@ -5,8 +5,9 @@ SHELL := /bin/bash
GO_VERSION=`cat GO_VERSION` GO_VERSION=`cat GO_VERSION`
DOCKER_BUILD_IMAGE=gotify/build DOCKER_BUILD_IMAGE=gotify/build
DOCKER_WORKDIR=/proj DOCKER_WORKDIR=/proj
DOCKER_RUN=docker run --rm -v "$$PWD/.:${DOCKER_WORKDIR}" -v "`go env GOPATH`/pkg/mod/.:/go/pkg/mod:ro" -w ${DOCKER_WORKDIR} DOCKER_RUN=docker run --rm -e LD_FLAGS="$$LD_FLAGS" -v "$$PWD/.:${DOCKER_WORKDIR}" -v "`go env GOPATH`/pkg/mod/.:/go/pkg/mod:ro" -w ${DOCKER_WORKDIR}
DOCKER_GO_BUILD=go build -mod=readonly -a -installsuffix cgo -ldflags "$$LD_FLAGS" DOCKER_GO_BUILD=go build -mod=readonly -a -installsuffix cgo -ldflags "$$LD_FLAGS"
DOCKER_TEST_LEVEL ?= 0 # Optionally run a test during docker build
NODE_OPTIONS=$(shell if node --help | grep -q -- "--openssl-legacy-provider"; then echo --openssl-legacy-provider; fi) NODE_OPTIONS=$(shell if node --help | grep -q -- "--openssl-legacy-provider"; then echo --openssl-legacy-provider; fi)
test: test-coverage test-js test: test-coverage test-js
@ -63,10 +64,9 @@ package-zip: extract-licenses
zip -ur $$BUILD.zip ${LICENSE_DIR}; \ zip -ur $$BUILD.zip ${LICENSE_DIR}; \
done done
build-docker-amd64: require-version build-docker-multiarch: require-version
cp ${BUILD_DIR}/gotify-linux-amd64 ./docker/gotify-app docker buildx build --sbom=true --provenance=true \
cd ${DOCKER_DIR} && \ $(if $(DOCKER_BUILD_PUSH),--push) \
docker build \
-t gotify/server:latest \ -t gotify/server:latest \
-t gotify/server:${VERSION} \ -t gotify/server:${VERSION} \
-t gotify/server:$(shell echo $(VERSION) | cut -d '.' -f -2) \ -t gotify/server:$(shell echo $(VERSION) | cut -d '.' -f -2) \
@ -74,27 +74,7 @@ build-docker-amd64: require-version
-t ghcr.io/gotify/server:latest \ -t ghcr.io/gotify/server:latest \
-t ghcr.io/gotify/server:${VERSION} \ -t ghcr.io/gotify/server:${VERSION} \
-t ghcr.io/gotify/server:$(shell echo $(VERSION) | cut -d '.' -f -2) \ -t ghcr.io/gotify/server:$(shell echo $(VERSION) | cut -d '.' -f -2) \
-t ghcr.io/gotify/server:$(shell echo $(VERSION) | cut -d '.' -f -1) . -t ghcr.io/gotify/server:$(shell echo $(VERSION) | cut -d '.' -f -1) \
rm ${DOCKER_DIR}gotify-app
build-docker-arm-7: require-version
cp ${BUILD_DIR}/gotify-linux-arm-7 ./docker/gotify-app
cd ${DOCKER_DIR} && \
docker build -f Dockerfile.armv7 \
-t gotify/server-arm7:latest \
-t gotify/server-arm7:${VERSION} \
-t gotify/server-arm7:$(shell echo $(VERSION) | cut -d '.' -f -2) \
-t gotify/server-arm7:$(shell echo $(VERSION) | cut -d '.' -f -1) \
-t ghcr.io/gotify/server-arm7:latest \
-t ghcr.io/gotify/server-arm7:${VERSION} \
-t ghcr.io/gotify/server-arm7:$(shell echo $(VERSION) | cut -d '.' -f -2) \
-t ghcr.io/gotify/server-arm7:$(shell echo $(VERSION) | cut -d '.' -f -1) .
rm ${DOCKER_DIR}gotify-app
build-docker-arm64: require-version
cp ${BUILD_DIR}/gotify-linux-arm64 ./docker/gotify-app
cd ${DOCKER_DIR} && \
docker build -f Dockerfile.arm64 \
-t gotify/server-arm64:latest \ -t gotify/server-arm64:latest \
-t gotify/server-arm64:${VERSION} \ -t gotify/server-arm64:${VERSION} \
-t gotify/server-arm64:$(shell echo $(VERSION) | cut -d '.' -f -2) \ -t gotify/server-arm64:$(shell echo $(VERSION) | cut -d '.' -f -2) \
@ -102,13 +82,15 @@ build-docker-arm64: require-version
-t ghcr.io/gotify/server-arm64:latest \ -t ghcr.io/gotify/server-arm64:latest \
-t ghcr.io/gotify/server-arm64:${VERSION} \ -t ghcr.io/gotify/server-arm64:${VERSION} \
-t ghcr.io/gotify/server-arm64:$(shell echo $(VERSION) | cut -d '.' -f -2) \ -t ghcr.io/gotify/server-arm64:$(shell echo $(VERSION) | cut -d '.' -f -2) \
-t ghcr.io/gotify/server-arm64:$(shell echo $(VERSION) | cut -d '.' -f -1) . -t ghcr.io/gotify/server-arm64:$(shell echo $(VERSION) | cut -d '.' -f -1) \
rm ${DOCKER_DIR}gotify-app -t gotify/server-arm7:latest \
-t gotify/server-arm7:${VERSION} \
build-docker-riscv64: require-version -t gotify/server-arm7:$(shell echo $(VERSION) | cut -d '.' -f -2) \
cp ${BUILD_DIR}/gotify-linux-riscv64 ./docker/gotify-app -t gotify/server-arm7:$(shell echo $(VERSION) | cut -d '.' -f -1) \
cd ${DOCKER_DIR} && \ -t ghcr.io/gotify/server-arm7:latest \
docker build -f Dockerfile.riscv64 \ -t ghcr.io/gotify/server-arm7:${VERSION} \
-t ghcr.io/gotify/server-arm7:$(shell echo $(VERSION) | cut -d '.' -f -2) \
-t ghcr.io/gotify/server-arm7:$(shell echo $(VERSION) | cut -d '.' -f -1) \
-t gotify/server-riscv64:latest \ -t gotify/server-riscv64:latest \
-t gotify/server-riscv64:${VERSION} \ -t gotify/server-riscv64:${VERSION} \
-t gotify/server-riscv64:$(shell echo $(VERSION) | cut -d '.' -f -2) \ -t gotify/server-riscv64:$(shell echo $(VERSION) | cut -d '.' -f -2) \
@ -116,34 +98,42 @@ build-docker-riscv64: require-version
-t ghcr.io/gotify/server-riscv64:latest \ -t ghcr.io/gotify/server-riscv64:latest \
-t ghcr.io/gotify/server-riscv64:${VERSION} \ -t ghcr.io/gotify/server-riscv64:${VERSION} \
-t ghcr.io/gotify/server-riscv64:$(shell echo $(VERSION) | cut -d '.' -f -2) \ -t ghcr.io/gotify/server-riscv64:$(shell echo $(VERSION) | cut -d '.' -f -2) \
-t ghcr.io/gotify/server-riscv64:$(shell echo $(VERSION) | cut -d '.' -f -1) . -t ghcr.io/gotify/server-riscv64:$(shell echo $(VERSION) | cut -d '.' -f -1) \
rm ${DOCKER_DIR}gotify-app --build-arg RUN_TESTS=$(DOCKER_TEST_LEVEL) \
--build-arg GO_VERSION=$(shell cat GO_VERSION) \
--build-arg LD_FLAGS="$$LD_FLAGS" \
--platform linux/amd64,linux/arm64,linux/386,linux/arm/v7,linux/riscv64 \
-f docker/Dockerfile .
build-docker: build-docker-amd64 build-docker-arm-7 build-docker-arm64 build-docker-riscv64 build-docker: build-docker-multiarch
_build_within_docker: OUTPUT = gotify-app
_build_within_docker:
${DOCKER_GO_BUILD} -o ${OUTPUT}
build-js: build-js:
(cd ui && NODE_OPTIONS="${NODE_OPTIONS}" yarn build) (cd ui && NODE_OPTIONS="${NODE_OPTIONS}" yarn build)
build-linux-amd64: build-linux-amd64:
${DOCKER_RUN} ${DOCKER_BUILD_IMAGE}:$(GO_VERSION)-linux-amd64 ${DOCKER_GO_BUILD} -o ${BUILD_DIR}/gotify-linux-amd64 ${DOCKER_WORKDIR} ${DOCKER_RUN} ${DOCKER_BUILD_IMAGE}:$(GO_VERSION)-linux-amd64 make _build_within_docker OUTPUT=${BUILD_DIR}/gotify-linux-amd64
build-linux-386: build-linux-386:
${DOCKER_RUN} ${DOCKER_BUILD_IMAGE}:$(GO_VERSION)-linux-386 ${DOCKER_GO_BUILD} -o ${BUILD_DIR}/gotify-linux-386 ${DOCKER_WORKDIR} ${DOCKER_RUN} ${DOCKER_BUILD_IMAGE}:$(GO_VERSION)-linux-386 make _build_within_docker OUTPUT=${BUILD_DIR}/gotify-linux-386
build-linux-arm-7: build-linux-arm-7:
${DOCKER_RUN} ${DOCKER_BUILD_IMAGE}:$(GO_VERSION)-linux-arm-7 ${DOCKER_GO_BUILD} -o ${BUILD_DIR}/gotify-linux-arm-7 ${DOCKER_WORKDIR} ${DOCKER_RUN} ${DOCKER_BUILD_IMAGE}:$(GO_VERSION)-linux-arm-7 make _build_within_docker OUTPUT=${BUILD_DIR}/gotify-linux-arm-7
build-linux-arm64: build-linux-arm64:
${DOCKER_RUN} ${DOCKER_BUILD_IMAGE}:$(GO_VERSION)-linux-arm64 ${DOCKER_GO_BUILD} -o ${BUILD_DIR}/gotify-linux-arm64 ${DOCKER_WORKDIR} ${DOCKER_RUN} ${DOCKER_BUILD_IMAGE}:$(GO_VERSION)-linux-arm64 make _build_within_docker OUTPUT=${BUILD_DIR}/gotify-linux-arm64
build-linux-riscv64: build-linux-riscv64:
${DOCKER_RUN} ${DOCKER_BUILD_IMAGE}:$(GO_VERSION)-linux-riscv64 ${DOCKER_GO_BUILD} -o ${BUILD_DIR}/gotify-linux-riscv64 ${DOCKER_WORKDIR} ${DOCKER_RUN} ${DOCKER_BUILD_IMAGE}:$(GO_VERSION)-linux-riscv64 make _build_within_docker OUTPUT=${BUILD_DIR}/gotify-linux-riscv64
build-windows-amd64: build-windows-amd64:
${DOCKER_RUN} ${DOCKER_BUILD_IMAGE}:$(GO_VERSION)-windows-amd64 ${DOCKER_GO_BUILD} -o ${BUILD_DIR}/gotify-windows-amd64.exe ${DOCKER_WORKDIR} ${DOCKER_RUN} ${DOCKER_BUILD_IMAGE}:$(GO_VERSION)-windows-amd64 make _build_within_docker OUTPUT=${BUILD_DIR}/gotify-windows-amd64.exe
build-windows-386: build-windows-386:
${DOCKER_RUN} ${DOCKER_BUILD_IMAGE}:$(GO_VERSION)-windows-386 ${DOCKER_GO_BUILD} -o ${BUILD_DIR}/gotify-windows-386.exe ${DOCKER_WORKDIR} ${DOCKER_RUN} ${DOCKER_BUILD_IMAGE}:$(GO_VERSION)-windows-386 make _build_within_docker OUTPUT=${BUILD_DIR}/gotify-windows-386.exe
build: build-linux-arm-7 build-linux-amd64 build-linux-386 build-linux-arm64 build-linux-riscv64 build-windows-amd64 build-windows-386 build: build-linux-arm-7 build-linux-amd64 build-linux-386 build-linux-arm64 build-linux-riscv64 build-windows-amd64 build-windows-386

View File

@ -1,12 +1,74 @@
FROM amd64/debian:stable-slim ARG BUILDKIT_SBOM_SCAN_CONTEXT=true
ENV GOTIFY_SERVER_PORT="80" # Suppress warning about invalid variable expansion
ARG GO_VERSION=PLEASE_PROVIDE_GO_VERSION
ARG DEBIAN=sid-slim
# Hack to normalize platform to match the chosed build image
# Get the gotify/build image tag
ARG __TARGETPLATFORM_DASHES=${TARGETPLATFORM/\//-}
ARG __TARGETPLATFORM_GO_NOTATION=${__TARGETPLATFORM_DASHES/arm\/v7/arm-7}
# --- JS Builder ---
FROM --platform=${BUILDPLATFORM} node:23 AS js-builder
ARG BUILD_JS=0
COPY ./Makefile /src/gotify/Makefile
COPY ./ui /src/gotify/ui
RUN if [ "$BUILD_JS" = "1" ]; then \
(cd /src/gotify/ui && yarn install) && \
(cd /src/gotify && make build-js) \
else \
mkdir -p /src/gotify/ui/build; \
fi
# --- Go Builder ---
FROM --platform=${BUILDPLATFORM} gotify/build:${GO_VERSION}-${__TARGETPLATFORM_GO_NOTATION} AS builder
ARG BUILDPLATFORM
ARG TARGETPLATFORM
ARG BUILD_JS=0
ARG RUN_TESTS=0 # 0=never, 1=native only
ARG LD_FLAGS=""
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -yq --no-install-recommends \
ca-certificates \
git
COPY . /src/gotify
COPY --from=js-builder /src/gotify/ui/build /ui-build
RUN if [ "$BUILD_JS" = "1" ]; then \
cp -r --update /ui-build /src/gotify/ui/build; \
fi
RUN cd /src/gotify && \
if [ "$RUN_TESTS" = "1" ] && [ "$BUILDPLATFORM" = "$TARGETPLATFORM" ]; then \
go test -v ./...; \
fi && \
LD_FLAGS=${LD_FLAGS} make OUTPUT=/target/app/gotify-app _build_within_docker
FROM debian:${DEBIAN}
# Build-time configurables
ARG GOTIFY_SERVER_EXPOSE=80
ENV GOTIFY_SERVER_PORT=$GOTIFY_SERVER_EXPOSE
WORKDIR /app WORKDIR /app
RUN export DEBIAN_FRONTEND=noninteractive && apt-get update && apt-get install -yq \
RUN export DEBIAN_FRONTEND=noninteractive && apt-get update && apt-get install -yq --no-install-recommends \
tzdata \ tzdata \
curl \ curl \
ca-certificates \ ca-certificates && \
&& rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
ADD gotify-app /app/
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s CMD curl --fail http://localhost:$GOTIFY_SERVER_PORT/health || exit 1 HEALTHCHECK --interval=30s --timeout=5s --start-period=5s CMD curl --fail http://localhost:$GOTIFY_SERVER_PORT/health || exit 1
EXPOSE 80 EXPOSE $GOTIFY_SERVER_EXPOSE
COPY --from=builder /target /
ENTRYPOINT ["./gotify-app"] ENTRYPOINT ["./gotify-app"]

View File

@ -1,5 +0,0 @@
FROM arm64v8/debian
WORKDIR /app
ADD gotify-app /app/
EXPOSE 80
ENTRYPOINT ["./gotify-app"]

View File

@ -1,5 +0,0 @@
FROM arm32v7/debian:stable-slim
WORKDIR /app
ADD gotify-app /app/
EXPOSE 80
ENTRYPOINT ["./gotify-app"]

View File

@ -1,5 +0,0 @@
FROM riscv64/debian:sid-slim
WORKDIR /app
ADD gotify-app /app/
EXPOSE 80
ENTRYPOINT ["./gotify-app"]

View File

@ -32,9 +32,11 @@ func TestWithWd(t *testing.T) {
}) })
assert.Nil(t, os.Mkdir(tmpDir.Path(), 0o644)) assert.Nil(t, os.Mkdir(tmpDir.Path(), 0o644))
if os.Getuid() != 0 { // root is not subject to this check
assert.Panics(t, func() { assert.Panics(t, func() {
WithWd(tmpDir.Path(), func(string) {}) WithWd(tmpDir.Path(), func(string) {})
}) })
}
assert.Nil(t, os.Remove(tmpDir.Path())) assert.Nil(t, os.Remove(tmpDir.Path()))
assert.Nil(t, os.Mkdir(tmpDir.Path(), 0o755)) assert.Nil(t, os.Mkdir(tmpDir.Path(), 0o755))