Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docker multiarch image #703

Merged
merged 15 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
vendor/
eternal-flame-AD marked this conversation as resolved.
Show resolved Hide resolved
.idea/
build/
licenses/
coverage.txt
data/
images/
.git/
*/node_modules/
39 changes: 22 additions & 17 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,32 @@ jobs:
- if: startsWith(github.ref, 'refs/tags/v')
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"
echo "LD_FLAGS=$LD_FLAGS" >> $GITHUB_ENV

make build
sudo chown -R $UID build
make package-zip
ls -lath build
make build-docker
docker image ls
echo "$DOCKER_PASS" | docker login --username "$DOCKER_USER" --password-stdin
echo "$DOCKER_GHCR_PASS" | docker login ghcr.io --username "$DOCKER_GHCR_USER" --password-stdin
docker push --all-tags gotify/server
docker push --all-tags gotify/server-arm7
docker push --all-tags gotify/server-arm64
docker push --all-tags gotify/server-riscv64
docker push --all-tags ghcr.io/gotify/server
docker push --all-tags ghcr.io/gotify/server-arm7
docker push --all-tags ghcr.io/gotify/server-arm64
docker push --all-tags ghcr.io/gotify/server-riscv64
env:
DOCKER_USER: ${{ secrets.DOCKER_USER }}
DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
DOCKER_GHCR_USER: ${{ secrets.DOCKER_GHCR_USER }}
DOCKER_GHCR_PASS: ${{ secrets.DOCKER_GHCR_PASS }}
- if: startsWith(github.ref, 'refs/tags/v')
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- if: startsWith(github.ref, 'refs/tags/v')
name: Set up QEMU
uses: docker/setup-qemu-action@v2
- if: startsWith(github.ref, 'refs/tags/v')
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASS }}
- if: startsWith(github.ref, 'refs/tags/v')
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ secrets.DOCKER_GHCR_USER }}
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')
uses: svenstaro/upload-release-action@v2
with:
Expand Down
78 changes: 34 additions & 44 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ SHELL := /bin/bash
GO_VERSION=`cat GO_VERSION`
DOCKER_BUILD_IMAGE=gotify/build
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_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)

test: test-coverage test-js
Expand Down Expand Up @@ -63,87 +64,76 @@ package-zip: extract-licenses
zip -ur $$BUILD.zip ${LICENSE_DIR}; \
done

build-docker-amd64: require-version
cp ${BUILD_DIR}/gotify-linux-amd64 ./docker/gotify-app
cd ${DOCKER_DIR} && \
docker build \
build-docker-multiarch: require-version
docker buildx build --sbom=true --provenance=true \
$(if $(DOCKER_BUILD_PUSH),--push) \
-t gotify/server:latest \
-t gotify/server:${VERSION} \
-t gotify/server:$(shell echo $(VERSION) | cut -d '.' -f -2) \
-t gotify/server:$(shell echo $(VERSION) | cut -d '.' -f -1) \
-t ghcr.io/gotify/server:latest \
-t ghcr.io/gotify/server:latest \
-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 -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 ghcr.io/gotify/server:$(shell echo $(VERSION) | cut -d '.' -f -1) \
-t gotify/server-arm64:latest \
-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 -1) \
-t ghcr.io/gotify/server-arm64:latest \
-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 -1) .
rm ${DOCKER_DIR}gotify-app

build-docker-riscv64: require-version
cp ${BUILD_DIR}/gotify-linux-riscv64 ./docker/gotify-app
cd ${DOCKER_DIR} && \
docker build -f Dockerfile.riscv64 \
-t ghcr.io/gotify/server-arm64:$(shell echo $(VERSION) | cut -d '.' -f -1) \
-t gotify/server-arm7:latest \
eternal-flame-AD marked this conversation as resolved.
Show resolved Hide resolved
-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) \
-t gotify/server-riscv64:latest \
-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 -1) \
-t ghcr.io/gotify/server-riscv64:latest \
-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 -1) .
rm ${DOCKER_DIR}gotify-app
-t ghcr.io/gotify/server-riscv64:$(shell echo $(VERSION) | cut -d '.' -f -1) \
--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-multiarch

build-docker: build-docker-amd64 build-docker-arm-7 build-docker-arm64 build-docker-riscv64
_build_within_docker: OUTPUT = gotify-app
_build_within_docker:
${DOCKER_GO_BUILD} -o ${OUTPUT}

build-js:
(cd ui && NODE_OPTIONS="${NODE_OPTIONS}" yarn build)

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:
${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:
${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:
${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:
${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:
${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:
${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

Expand Down
80 changes: 71 additions & 9 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,74 @@
FROM amd64/debian:stable-slim
ENV GOTIFY_SERVER_PORT="80"
ARG BUILDKIT_SBOM_SCAN_CONTEXT=true
# Suppress warning about invalid variable expansion
jmattheis marked this conversation as resolved.
Show resolved Hide resolved
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

eternal-flame-AD marked this conversation as resolved.
Show resolved Hide resolved
ARG BUILDPLATFORM
ARG TARGETPLATFORM
ARG BUILD_JS=0
ARG RUN_TESTS=0 # 0=never, 1=native only
eternal-flame-AD marked this conversation as resolved.
Show resolved Hide resolved
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
jmattheis marked this conversation as resolved.
Show resolved Hide resolved

WORKDIR /app
RUN export DEBIAN_FRONTEND=noninteractive && apt-get update && apt-get install -yq \
tzdata \
curl \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
ADD gotify-app /app/

RUN export DEBIAN_FRONTEND=noninteractive && apt-get update && apt-get install -yq --no-install-recommends \
tzdata \
curl \
ca-certificates && \
rm -rf /var/lib/apt/lists/*

HEALTHCHECK --interval=30s --timeout=5s --start-period=5s CMD curl --fail http://localhost:$GOTIFY_SERVER_PORT/health || exit 1
EXPOSE 80
eternal-flame-AD marked this conversation as resolved.
Show resolved Hide resolved
EXPOSE $GOTIFY_SERVER_EXPOSE

COPY --from=builder /target /

ENTRYPOINT ["./gotify-app"]
5 changes: 0 additions & 5 deletions docker/Dockerfile.arm64

This file was deleted.

5 changes: 0 additions & 5 deletions docker/Dockerfile.armv7

This file was deleted.

5 changes: 0 additions & 5 deletions docker/Dockerfile.riscv64

This file was deleted.

8 changes: 5 additions & 3 deletions test/filepath_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ func TestWithWd(t *testing.T) {
})

assert.Nil(t, os.Mkdir(tmpDir.Path(), 0o644))
assert.Panics(t, func() {
WithWd(tmpDir.Path(), func(string) {})
})
if os.Getuid() != 0 { // root is not subject to this check
assert.Panics(t, func() {
WithWd(tmpDir.Path(), func(string) {})
})
}
assert.Nil(t, os.Remove(tmpDir.Path()))

assert.Nil(t, os.Mkdir(tmpDir.Path(), 0o755))
Expand Down
Loading