feat: builds with gox and buildx (#2381)
* feat: builds with gox and buildx This change builds all of Authelia respective binaries in parallel within a single step and distributes as necessary to subsequent steps, we now also build and distribute for the following OS/Architecture: freebsd/amd64. Our CI/CD pipeline now also utilises docker buildx as a default for builds and pushes. * refactor: clean up docker helper * Remove `authelia-scripts docker push-image` command as all pushes will be performed with buildx and manifests * Rename the --arch flag to --container * Add Dockerfile.dev for users that want to build an Authelia container from source without utilising suites * Set Dockerfile.dev as default for `authelia-scripts docker build` command * refactor: variant -> containerpull/2383/head
parent
e1ca24344a
commit
92ec00d7c5
|
@ -5,24 +5,26 @@
|
|||
<dd>
|
||||
<a href="artifact://authelia-linux-amd64.tar.gz">authelia-linux-amd64.tar.gz</a><br>
|
||||
<a href="artifact://authelia-linux-amd64.tar.gz.sha256">authelia-linux-amd64.tar.gz.sha256</a><br>
|
||||
<a href="artifact://authelia-freebsd-amd64.tar.gz">authelia-freebsd-amd64.tar.gz</a><br>
|
||||
<a href="artifact://authelia-freebsd-amd64.tar.gz.sha256">authelia-freebsd-amd64.tar.gz.sha256</a><br>
|
||||
<a href="artifact://authelia_amd64.deb">authelia_amd64.deb</a><br>
|
||||
<a href="artifact://authelia_amd64.deb.sha256">authelia_amd64.deb.sha256</a>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="m1">
|
||||
<dt>arm32v7</dt>
|
||||
<dt>arm</dt>
|
||||
<dd>
|
||||
<a href="artifact://authelia-linux-arm32v7.tar.gz">authelia-linux-arm32v7.tar.gz</a><br>
|
||||
<a href="artifact://authelia-linux-arm32v7.tar.gz.sha256">authelia-linux-arm32v7.tar.gz.sha256</a><br>
|
||||
<a href="artifact://authelia-linux-arm.tar.gz">authelia-linux-arm.tar.gz</a><br>
|
||||
<a href="artifact://authelia-linux-arm.tar.gz.sha256">authelia-linux-arm.tar.gz.sha256</a><br>
|
||||
<a href="artifact://authelia_armhf.deb">authelia_armhf.deb</a><br>
|
||||
<a href="artifact://authelia_armhf.deb.sha256">authelia_armhf.deb.sha256</a>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="m1">
|
||||
<dt>arm64v8</dt>
|
||||
<dt>arm64</dt>
|
||||
<dd>
|
||||
<a href="artifact://authelia-linux-arm64v8.tar.gz">authelia-linux-arm64v8.tar.gz</a><br>
|
||||
<a href="artifact://authelia-linux-arm64v8.tar.gz.sha256">authelia-linux-arm64v8.tar.gz.sha256</a><br>
|
||||
<a href="artifact://authelia-linux-arm64.tar.gz">authelia-linux-arm64.tar.gz</a><br>
|
||||
<a href="artifact://authelia-linux-arm64.tar.gz.sha256">authelia-linux-arm64.tar.gz.sha256</a><br>
|
||||
<a href="artifact://authelia_arm64.deb">authelia_arm64.deb</a><br>
|
||||
<a href="artifact://authelia_arm64.deb.sha256">authelia_arm64.deb.sha256</a>
|
||||
</dd>
|
||||
|
|
|
@ -22,20 +22,13 @@ env:
|
|||
CI_BYPASS: ${CI_BYPASS}
|
||||
|
||||
steps:
|
||||
- label: ":docker: Image Deployments"
|
||||
command: ".buildkite/steps/deployimages.sh | buildkite-agent pipeline upload"
|
||||
if: build.env("CI_BYPASS") != "true"
|
||||
|
||||
- wait:
|
||||
if: build.env("CI_BYPASS") != "true"
|
||||
|
||||
- label: ":docker: Deploy Manifests"
|
||||
- label: ":docker: Deploy Manifest"
|
||||
command: "authelia-scripts docker push-manifest"
|
||||
depends_on:
|
||||
- "unit-test"
|
||||
retry:
|
||||
manual:
|
||||
permit_on_passed: true
|
||||
env:
|
||||
DOCKER_CLI_EXPERIMENTAL: "enabled"
|
||||
agents:
|
||||
upload: "fast"
|
||||
if: build.env("CI_BYPASS") != "true"
|
||||
|
@ -43,9 +36,7 @@ steps:
|
|||
- label: ":github: Deploy Artifacts"
|
||||
command: "ghartifacts.sh"
|
||||
depends_on:
|
||||
- "build-docker-linux-amd64"
|
||||
- "build-docker-linux-arm32v7"
|
||||
- "build-docker-linux-arm64v8"
|
||||
- "unit-test"
|
||||
- "build-deb-package-amd64"
|
||||
- "build-deb-package-armhf"
|
||||
- "build-deb-package-arm64"
|
||||
|
|
|
@ -31,7 +31,7 @@ if [[ "${BUILDKITE_LABEL}" =~ ":selenium:" ]] || [[ "${BUILDKITE_LABEL}" =~ ":do
|
|||
fi
|
||||
fi
|
||||
|
||||
if [[ "${BUILDKITE_LABEL}" == ":docker: Image Deployments" ]]; then
|
||||
if [[ "${BUILDKITE_LABEL}" == ":debian: Package Builds" ]]; then
|
||||
cat .buildkite/annotations/artifacts | buildkite-agent annotate --style "success" --context "ctx-success"
|
||||
fi
|
||||
|
||||
|
@ -40,7 +40,7 @@ if [[ "${BUILDKITE_LABEL}" =~ ":docker: Deploy" ]]; then
|
|||
docker logout ghcr.io
|
||||
fi
|
||||
|
||||
if [[ "${BUILDKITE_LABEL}" == ":docker: Deploy Manifests" ]] && [[ "${BUILDKITE_BRANCH}" == "master" ]] && [[ "${BUILDKITE_PULL_REQUEST}" == "false" ]]; then
|
||||
if [[ "${BUILDKITE_LABEL}" == ":docker: Deploy Manifest" ]] && [[ "${BUILDKITE_BRANCH}" == "master" ]] && [[ "${BUILDKITE_PULL_REQUEST}" == "false" ]]; then
|
||||
echo "--- :docker: Removing tags for deleted branches"
|
||||
anontoken=$(curl -fsL --retry 3 'https://auth.docker.io/token?service=registry.docker.io&scope=repository:authelia/authelia:pull' | jq -r .token)
|
||||
authtoken=$(curl -fs --retry 3 -H "Content-Type: application/json" -X "POST" -d '{"username": "'${DOCKER_USERNAME}'", "password": "'${DOCKER_PASSWORD}'"}' https://hub.docker.com/v2/users/login/ | jq -r .token)
|
||||
|
|
|
@ -2,25 +2,25 @@
|
|||
|
||||
set +u
|
||||
|
||||
declare -A BUILDS=(["linux"]="amd64 arm arm64" ["freebsd"]="amd64")
|
||||
DOCKER_IMAGE=authelia/authelia
|
||||
|
||||
if [[ "${BUILDKITE_LABEL}" == ":hammer_and_wrench: Unit Test" ]]; then
|
||||
echo "--- :docker: Saving artifacts for :buildkite: :docker: :github: releases"
|
||||
for OS in "${!BUILDS[@]}"; do
|
||||
for ARCH in ${BUILDS[$OS]}; do
|
||||
tar -czf "authelia-${OS}-${ARCH}.tar.gz" "authelia-${OS}-${ARCH}" authelia.service config.template.yml
|
||||
sha256sum "authelia-${OS}-${ARCH}.tar.gz" > "authelia-${OS}-${ARCH}.tar.gz.sha256"
|
||||
done
|
||||
done
|
||||
|
||||
tar -czf authelia-public_html.tar.gz -C dist public_html
|
||||
sha256sum authelia-public_html.tar.gz > authelia-public_html.tar.gz.sha256
|
||||
fi
|
||||
|
||||
if [[ "${BUILDKITE_LABEL}" =~ ":docker: Build Image" ]]; then
|
||||
echo "--- :docker: Saving artifacts for :buildkite: :docker: :github: releases"
|
||||
# Save binary for buildkite and github artifacts
|
||||
if [[ "${ARCH}" != "coverage" ]]; then
|
||||
docker create --name authelia-binary "${DOCKER_IMAGE}:latest"
|
||||
docker cp authelia-binary:/app/authelia "./authelia-${OS}-${ARCH}"
|
||||
docker rm -f authelia-binary
|
||||
tar -czf "authelia-${OS}-${ARCH}.tar.gz" "authelia-${OS}-${ARCH}" authelia.service config.template.yml
|
||||
sha256sum "authelia-${OS}-${ARCH}.tar.gz" > "authelia-${OS}-${ARCH}.tar.gz.sha256"
|
||||
fi
|
||||
# Saving image for push to docker hub
|
||||
docker save "${DOCKER_IMAGE}" | zstdmt -T0 -12 > "authelia-image-${ARCH}.tar.zst"
|
||||
if [[ "${BUILDKITE_LABEL}" == ":docker: Build Image [coverage]" ]]; then
|
||||
# Saving image for docker push
|
||||
docker save "${DOCKER_IMAGE}" | zstdmt -T0 -12 > "authelia-image-coverage.tar.zst"
|
||||
fi
|
||||
|
||||
if [[ "${BUILDKITE_LABEL}" =~ ":debian: Build Package" ]]; then
|
||||
|
|
|
@ -14,12 +14,6 @@ if [[ "${BUILDKITE_LABEL}" =~ ":selenium:" ]]; then
|
|||
docker tag authelia/authelia authelia:dist
|
||||
fi
|
||||
|
||||
if [[ "${BUILDKITE_LABEL}" =~ ":docker: Build Image" ]] && [[ "${ARCH}" != "coverage" ]]; then
|
||||
echo "--- :react: :swagger: Extract frontend assets"
|
||||
buildkite-agent artifact download "authelia-public_html.tar.gz" .
|
||||
tar xzf authelia-public_html.tar.gz
|
||||
fi
|
||||
|
||||
if [[ "${BUILDKITE_LABEL}" =~ ":debian: Build Package" ]]; then
|
||||
buildkite-agent artifact download "authelia-linux-${ARCH}.tar.gz" .
|
||||
fi
|
||||
|
@ -29,6 +23,12 @@ if [[ "${BUILDKITE_LABEL}" =~ ":docker: Deploy Image" ]]; then
|
|||
zstdcat "authelia-image-${ARCH}.tar.zst" | docker load
|
||||
fi
|
||||
|
||||
if [[ "${BUILDKITE_LABEL}" == ":docker: Deploy Manifest" ]]; then
|
||||
echo "--- :go: :react: :swagger: Extract pre-built binary"
|
||||
buildkite-agent artifact download "authelia-linux-*.tar.gz" .
|
||||
for archive in authelia-linux-*.tar.gz; do tar xzf ${archive} --wildcards "authelia-linux-*"; done
|
||||
fi
|
||||
|
||||
if [[ "${BUILDKITE_LABEL}" == ":github: Deploy Artifacts" ]]; then
|
||||
buildkite-agent artifact download "authelia-*.tar.gz*" .
|
||||
buildkite-agent artifact download "authelia_*.deb*" .
|
||||
|
|
|
@ -37,35 +37,29 @@ steps:
|
|||
agents:
|
||||
build: "unit-test"
|
||||
artifact_paths:
|
||||
- "authelia-public_html.tar.gz"
|
||||
- "authelia-public_html.tar.gz.sha256"
|
||||
- "authelia-*.tar.gz"
|
||||
- "authelia-*.tar.gz.sha256"
|
||||
key: "unit-test"
|
||||
if: build.env("CI_BYPASS") != "true"
|
||||
|
||||
- wait:
|
||||
if: build.env("CI_BYPASS") != "true"
|
||||
|
||||
- label: ":docker: Image Builds"
|
||||
command: ".buildkite/steps/buildimages.sh | buildkite-agent pipeline upload"
|
||||
concurrency: 3
|
||||
concurrency_group: "builds"
|
||||
- label: ":docker: Build Image [coverage]"
|
||||
command: "authelia-scripts docker build --container=coverage"
|
||||
agents:
|
||||
build: "linux-coverage"
|
||||
artifact_paths:
|
||||
- "authelia-image-coverage.tar.zst"
|
||||
depends_on: ~
|
||||
if: build.env("CI_BYPASS") != "true"
|
||||
key: "build-docker-linux-coverage"
|
||||
if: build.env("CI_BYPASS") != "true" && build.branch !~ /^(v[0-9]+\.[0-9]+\.[0-9]+)$\$/ && build.message !~ /\[(skip test|test skip)\]/
|
||||
|
||||
- label: ":debian: Package Builds"
|
||||
command: ".buildkite/steps/debpackages.sh | buildkite-agent pipeline upload"
|
||||
depends_on: ~
|
||||
if: build.branch !~ /^(dependabot|renovate)\/.*/ && build.env("CI_BYPASS") != "true"
|
||||
|
||||
- wait:
|
||||
if: build.env("CI_BYPASS") != "true"
|
||||
|
||||
- label: ":vertical_traffic_light: Build Concurrency Gate"
|
||||
command: "echo End of concurrency gate"
|
||||
concurrency: 3
|
||||
concurrency_group: "builds"
|
||||
if: build.env("CI_BYPASS") != "true"
|
||||
|
||||
- wait:
|
||||
if: build.branch !~ /^(v[0-9]+\.[0-9]+\.[0-9]+)$\$/ && build.env("CI_BYPASS") != "true" && build.message !~ /\[(skip test|test skip)\]/
|
||||
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -eu
|
||||
|
||||
declare -A BUILDS=(["linux"]="amd64 arm32v7 arm64v8 coverage")
|
||||
|
||||
for BUILD_OS in "${!BUILDS[@]}"; do
|
||||
for BUILD_ARCH in ${BUILDS[$BUILD_OS]}; do
|
||||
cat << EOF
|
||||
- label: ":docker: Build Image [${BUILD_ARCH}]"
|
||||
command: "authelia-scripts docker build --arch=${BUILD_ARCH}"
|
||||
retry:
|
||||
manual:
|
||||
permit_on_passed: true
|
||||
agents:
|
||||
build: "${BUILD_OS}-${BUILD_ARCH}"
|
||||
artifact_paths:
|
||||
- "authelia-image-${BUILD_ARCH}.tar.zst"
|
||||
EOF
|
||||
if [[ "${BUILD_ARCH}" != "coverage" ]]; then
|
||||
cat << EOF
|
||||
- "authelia-${BUILD_OS}-${BUILD_ARCH}.tar.gz"
|
||||
- "authelia-${BUILD_OS}-${BUILD_ARCH}.tar.gz.sha256"
|
||||
depends_on:
|
||||
- "unit-test"
|
||||
EOF
|
||||
fi
|
||||
cat << EOF
|
||||
env:
|
||||
ARCH: "${BUILD_ARCH}"
|
||||
OS: "${BUILD_OS}"
|
||||
key: "build-docker-${BUILD_OS}-${BUILD_ARCH}"
|
||||
EOF
|
||||
if [[ "${BUILD_ARCH}" == "coverage" ]]; then
|
||||
cat << EOF
|
||||
if: build.branch !~ /^(v[0-9]+\.[0-9]+\.[0-9]+)$\$/ && build.message !~ /\[(skip test|test skip)\]/
|
||||
EOF
|
||||
else
|
||||
cat << EOF
|
||||
if: build.branch !~ /^(dependabot|renovate)\/.*/
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
done
|
|
@ -11,8 +11,8 @@ fi
|
|||
wget https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=authelia-bin -qO PKGBUILD && \
|
||||
sed -i -e '/^pkgname=/c pkgname=authelia' -e "/pkgver=/c $VERSION" -e '10,14d' \
|
||||
-e 's/source_x86_64.*/source_x86_64=("authelia-linux-amd64.tar.gz")/' \
|
||||
-e 's/source_aarch64.*/source_aarch64=("authelia-linux-arm64v8.tar.gz")/' \
|
||||
-e 's/source_armv7h.*/source_armv7h=("authelia-linux-arm32v7.tar.gz")/' \
|
||||
-e 's/source_aarch64.*/source_aarch64=("authelia-linux-arm64.tar.gz")/' \
|
||||
-e 's/source_armv7h.*/source_armv7h=("authelia-linux-arm.tar.gz")/' \
|
||||
-e 's/sha256sums_x86_64.*/sha256sums_x86_64=("SKIP")/' \
|
||||
-e 's/sha256sums_aarch64.*/sha256sums_aarch64=("SKIP")/' \
|
||||
-e 's/sha256sums_armv7h.*/sha256sums_armv7h=("SKIP")/' PKGBUILD
|
||||
|
|
|
@ -14,23 +14,19 @@ EOF
|
|||
if [[ "${DEB_PACKAGE}" == "amd64" ]]; then
|
||||
cat << EOF
|
||||
ARCH: "${DEB_PACKAGE}"
|
||||
depends_on:
|
||||
- "build-docker-linux-amd64"
|
||||
EOF
|
||||
elif [[ "${DEB_PACKAGE}" == "armhf" ]]; then
|
||||
cat << EOF
|
||||
ARCH: "arm32v7"
|
||||
depends_on:
|
||||
- "build-docker-linux-arm32v7"
|
||||
ARCH: "arm"
|
||||
EOF
|
||||
else
|
||||
cat << EOF
|
||||
ARCH: "arm64v8"
|
||||
depends_on:
|
||||
- "build-docker-linux-arm64v8"
|
||||
ARCH: "arm64"
|
||||
EOF
|
||||
fi
|
||||
cat << EOF
|
||||
depends_on:
|
||||
- "unit-test"
|
||||
key: "build-deb-package-${DEB_PACKAGE}"
|
||||
EOF
|
||||
done
|
|
@ -1,32 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -eu
|
||||
|
||||
for BUILD_ARCH in amd64 arm32v7 arm64v8; do
|
||||
cat << EOF
|
||||
- label: ":docker: Deploy Image [${BUILD_ARCH}]"
|
||||
command: "authelia-scripts docker push-image --arch=${BUILD_ARCH}"
|
||||
retry:
|
||||
manual:
|
||||
permit_on_passed: true
|
||||
depends_on:
|
||||
EOF
|
||||
if [[ "${BUILD_ARCH}" == "amd64" ]]; then
|
||||
cat << EOF
|
||||
- "build-docker-linux-amd64"
|
||||
EOF
|
||||
elif [[ "${BUILD_ARCH}" == "arm32v7" ]]; then
|
||||
cat << EOF
|
||||
- "build-docker-linux-arm32v7"
|
||||
EOF
|
||||
else
|
||||
cat << EOF
|
||||
- "build-docker-linux-arm64v8"
|
||||
EOF
|
||||
fi
|
||||
cat << EOF
|
||||
agents:
|
||||
upload: "fast"
|
||||
env:
|
||||
ARCH: "${BUILD_ARCH}"
|
||||
EOF
|
||||
done
|
|
@ -5,8 +5,9 @@ artifacts=()
|
|||
|
||||
for FILE in \
|
||||
authelia-linux-amd64.tar.gz authelia-linux-amd64.tar.gz.sha256 \
|
||||
authelia-linux-arm32v7.tar.gz authelia-linux-arm32v7.tar.gz.sha256 \
|
||||
authelia-linux-arm64v8.tar.gz authelia-linux-arm64v8.tar.gz.sha256 \
|
||||
authelia-linux-arm.tar.gz authelia-linux-arm.tar.gz.sha256 \
|
||||
authelia-linux-arm64.tar.gz authelia-linux-arm64.tar.gz.sha256 \
|
||||
authelia-freebsd-amd64.tar.gz authelia-freebsd-amd64.tar.gz.sha256 \
|
||||
authelia-public_html.tar.gz authelia-public_html.tar.gz.sha256;
|
||||
do
|
||||
# Add the version to the artifact name
|
||||
|
|
|
@ -1,26 +1,9 @@
|
|||
# CI/Git Directories
|
||||
.git
|
||||
.cache
|
||||
.buildkite
|
||||
.github
|
||||
coverage.txt
|
||||
Dockerfile*
|
||||
|
||||
# Node Modules Directories
|
||||
**/node_modules
|
||||
|
||||
# Documentation
|
||||
docs
|
||||
examples
|
||||
|
||||
# Dot Files and Markdown
|
||||
.*
|
||||
*.md
|
||||
|
||||
# Other
|
||||
internal/server/public_html
|
||||
authelia.service
|
||||
bootstrap.sh
|
||||
# Ignore All
|
||||
*
|
||||
|
||||
# Overrides
|
||||
!authelia-linux-*
|
||||
!LICENSE
|
||||
!entrypoint.sh
|
||||
!healthcheck.sh
|
||||
!.healthcheck.env
|
||||
|
|
49
Dockerfile
49
Dockerfile
|
@ -1,47 +1,32 @@
|
|||
# =======================================
|
||||
# ===== Build image for the backend =====
|
||||
# =======================================
|
||||
FROM golang:1.17.1-alpine AS builder-backend
|
||||
|
||||
WORKDIR /go/src/app
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
|
||||
RUN \
|
||||
echo ">> Downloading go modules..." && \
|
||||
go mod download
|
||||
|
||||
COPY / ./
|
||||
|
||||
ARG LDFLAGS_EXTRA
|
||||
|
||||
RUN \
|
||||
mv public_html internal/server/public_html && \
|
||||
chmod 0666 /go/src/app/.healthcheck.env && \
|
||||
echo ">> Starting go build..." && \
|
||||
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -tags netgo \
|
||||
-ldflags "-s -w ${LDFLAGS_EXTRA}" -trimpath -o authelia ./cmd/authelia
|
||||
|
||||
# ===================================
|
||||
# ===== Authelia official image =====
|
||||
# ===================================
|
||||
FROM alpine:3.14.2
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apk --no-cache add ca-certificates su-exec tzdata
|
||||
|
||||
COPY --from=builder-backend /go/src/app/authelia /go/src/app/LICENSE /go/src/app/entrypoint.sh /go/src/app/healthcheck.sh /go/src/app/.healthcheck.env ./
|
||||
|
||||
EXPOSE 9091
|
||||
|
||||
VOLUME /config
|
||||
|
||||
# Set environment variables
|
||||
ENV PATH="/app:${PATH}" \
|
||||
PUID=0 \
|
||||
PGID=0
|
||||
|
||||
RUN \
|
||||
apk --no-cache add ca-certificates su-exec tzdata
|
||||
|
||||
COPY LICENSE .healthcheck.env entrypoint.sh healthcheck.sh ./
|
||||
|
||||
RUN \
|
||||
chmod 0666 /app/.healthcheck.env
|
||||
|
||||
COPY authelia-${TARGETOS}-${TARGETARCH} ./authelia
|
||||
|
||||
EXPOSE 9091
|
||||
|
||||
VOLUME /config
|
||||
|
||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||
CMD ["--config", "/config/configuration.yml"]
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=1m CMD /app/healthcheck.sh
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
# =======================================
|
||||
# ===== Build image for the backend =====
|
||||
# =======================================
|
||||
FROM golang:1.17.1-alpine AS builder-backend
|
||||
|
||||
WORKDIR /go/src/app
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
|
||||
RUN \
|
||||
echo ">> Downloading go modules..." && \
|
||||
go mod download
|
||||
|
||||
COPY / ./
|
||||
|
||||
ARG LDFLAGS_EXTRA
|
||||
|
||||
RUN \
|
||||
mv public_html internal/server/public_html && \
|
||||
chmod 0666 /go/src/app/.healthcheck.env && \
|
||||
echo ">> Starting go build..." && \
|
||||
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -tags netgo \
|
||||
-ldflags "-s -w ${LDFLAGS_EXTRA}" -trimpath -o authelia ./cmd/authelia
|
||||
|
||||
# ===================================
|
||||
# ===== Authelia official image =====
|
||||
# ===================================
|
||||
FROM arm64v8/alpine:3.14.2
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN \
|
||||
apk --no-cache add ca-certificates su-exec tzdata
|
||||
|
||||
COPY --from=builder-backend /go/src/app/authelia /go/src/app/LICENSE /go/src/app/entrypoint.sh /go/src/app/healthcheck.sh /go/src/app/.healthcheck.env ./
|
||||
|
||||
EXPOSE 9091
|
||||
|
||||
VOLUME /config
|
||||
|
||||
# Set environment variables
|
||||
ENV PATH="/app:${PATH}" \
|
||||
PUID=0 \
|
||||
PGID=0
|
||||
|
||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||
CMD ["--config", "/config/configuration.yml"]
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=1m CMD /app/healthcheck.sh
|
|
@ -0,0 +1,22 @@
|
|||
# CI/Git Directories
|
||||
coverage.txt
|
||||
Dockerfile*
|
||||
|
||||
# Node Modules Directories
|
||||
**/node_modules
|
||||
|
||||
# Documentation
|
||||
docs
|
||||
examples
|
||||
|
||||
# Dot Files and Markdown
|
||||
.*
|
||||
*.md
|
||||
|
||||
# Other
|
||||
internal/server/public_html
|
||||
authelia.service
|
||||
bootstrap.sh
|
||||
|
||||
# Overrides
|
||||
!.healthcheck.env
|
|
@ -1,3 +1,15 @@
|
|||
# ========================================
|
||||
# ===== Build image for the frontend =====
|
||||
# ========================================
|
||||
FROM node:16-alpine AS builder-frontend
|
||||
|
||||
WORKDIR /node/src/app
|
||||
|
||||
COPY web ./
|
||||
|
||||
# Install the dependencies and build
|
||||
RUN yarn install --frozen-lockfile && INLINE_RUNTIME_CHUNK=false yarn coverage
|
||||
|
||||
# =======================================
|
||||
# ===== Build image for the backend =====
|
||||
# =======================================
|
||||
|
@ -13,36 +25,41 @@ go mod download
|
|||
|
||||
COPY / ./
|
||||
|
||||
ARG LDFLAGS_EXTRA
|
||||
# Prepare static files to be embedded in Go binary
|
||||
COPY --from=builder-frontend /node/src/internal/server/public_html internal/server/public_html
|
||||
|
||||
ARG LDFLAGS_EXTRA
|
||||
RUN \
|
||||
mv public_html internal/server/public_html && \
|
||||
mv api internal/server/public_html/api && \
|
||||
chmod 0666 /go/src/app/.healthcheck.env && \
|
||||
echo ">> Starting go build..." && \
|
||||
GOOS=linux GOARCH=arm CGO_ENABLED=0 go build -tags netgo \
|
||||
CGO_ENABLED=0 go build -tags netgo \
|
||||
-ldflags "-s -w ${LDFLAGS_EXTRA}" -trimpath -o authelia ./cmd/authelia
|
||||
|
||||
# ===================================
|
||||
# ===== Authelia official image =====
|
||||
# ===================================
|
||||
FROM arm32v7/alpine:3.14.2
|
||||
FROM alpine:3.14.2
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN \
|
||||
apk --no-cache add ca-certificates su-exec tzdata
|
||||
|
||||
COPY --from=builder-backend /go/src/app/authelia /go/src/app/LICENSE /go/src/app/entrypoint.sh /go/src/app/healthcheck.sh /go/src/app/.healthcheck.env ./
|
||||
|
||||
EXPOSE 9091
|
||||
|
||||
VOLUME /config
|
||||
|
||||
# Set environment variables
|
||||
ENV PATH="/app:${PATH}" \
|
||||
PUID=0 \
|
||||
PGID=0
|
||||
|
||||
RUN \
|
||||
apk --no-cache add ca-certificates su-exec tzdata
|
||||
|
||||
COPY --from=builder-backend /go/src/app/cmd/authelia/authelia /go/src/app/LICENSE /go/src/app/entrypoint.sh /go/src/app/healthcheck.sh /go/src/app/.healthcheck.env ./
|
||||
|
||||
RUN \
|
||||
chmod 0666 /app/.healthcheck.env
|
||||
|
||||
EXPOSE 9091
|
||||
|
||||
VOLUME /config
|
||||
|
||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||
CMD ["--config", "/config/configuration.yml"]
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=1m CMD /app/healthcheck.sh
|
|
@ -0,0 +1,22 @@
|
|||
# CI/Git Directories
|
||||
coverage.txt
|
||||
Dockerfile*
|
||||
|
||||
# Node Modules Directories
|
||||
**/node_modules
|
||||
|
||||
# Documentation
|
||||
docs
|
||||
examples
|
||||
|
||||
# Dot Files and Markdown
|
||||
.*
|
||||
*.md
|
||||
|
||||
# Other
|
||||
internal/server/public_html
|
||||
authelia.service
|
||||
bootstrap.sh
|
||||
|
||||
# Overrides
|
||||
!.healthcheck.env
|
|
@ -10,12 +10,18 @@ import (
|
|||
"github.com/authelia/authelia/v4/internal/utils"
|
||||
)
|
||||
|
||||
func buildAutheliaBinary(xflags []string) {
|
||||
cmd := utils.CommandWithStdout("go", "build", "-o", "../../"+OutputDir+"/authelia", "-ldflags", strings.Join(xflags, " "))
|
||||
cmd.Dir = "cmd/authelia"
|
||||
func buildAutheliaBinary(xflags []string, buildkite bool) {
|
||||
cmd := utils.CommandWithStdout("go", "build", "-tags", "netgo", "-trimpath", "-o", OutputDir+"/authelia", "-ldflags", "-s -w "+strings.Join(xflags, " "), "./cmd/authelia/")
|
||||
|
||||
cmd.Env = append(os.Environ(),
|
||||
"GOOS=linux", "GOARCH=amd64", "CGO_ENABLED=0")
|
||||
"CGO_ENABLED=0")
|
||||
|
||||
if buildkite {
|
||||
cmd = utils.CommandWithStdout("gox", "-tags=netgo", "-output={{.Dir}}-{{.OS}}-{{.Arch}}", "-ldflags=-s -w "+strings.Join(xflags, " "), "-osarch=linux/amd64 linux/arm linux/arm64 freebsd/amd64", "./cmd/authelia/")
|
||||
|
||||
cmd.Env = append(os.Environ(),
|
||||
"GOFLAGS=-trimpath", "CGO_ENABLED=0")
|
||||
}
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
|
@ -98,7 +104,7 @@ func Build(cobraCmd *cobra.Command, args []string) {
|
|||
|
||||
Clean(cobraCmd, args)
|
||||
|
||||
xflags, err := getXFlags("", "0", "")
|
||||
xflags, err := getXFlags(os.Getenv("BUILDKITE_BRANCH"), os.Getenv("BUILDKITE_BUILD_NUMBER"), "")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -118,11 +124,12 @@ func Build(cobraCmd *cobra.Command, args []string) {
|
|||
|
||||
buildkite, _ := cobraCmd.Flags().GetBool("buildkite")
|
||||
if buildkite {
|
||||
log.Debug("Buildkite job detected, skipping Authelia Go binary build")
|
||||
log.Debug("Building Authelia Go binaries with gox...")
|
||||
} else {
|
||||
log.Debug("Building Authelia Go binary...")
|
||||
buildAutheliaBinary(xflags)
|
||||
}
|
||||
|
||||
buildAutheliaBinary(xflags, buildkite)
|
||||
|
||||
cleanAssets()
|
||||
}
|
||||
|
|
|
@ -6,19 +6,15 @@ import (
|
|||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/authelia/authelia/v4/internal/utils"
|
||||
)
|
||||
|
||||
var arch string
|
||||
var container string
|
||||
|
||||
var supportedArch = []string{"amd64", "arm32v7", "arm64v8", "coverage"}
|
||||
var defaultArch = "amd64"
|
||||
var buildkiteQEMU = os.Getenv("BUILDKITE_AGENT_META_DATA_QEMU")
|
||||
var containers = []string{"dev", "coverage"}
|
||||
var defaultContainer = "dev"
|
||||
var ciBranch = os.Getenv("BUILDKITE_BRANCH")
|
||||
var ciPullRequest = os.Getenv("BUILDKITE_PULL_REQUEST")
|
||||
var ciTag = os.Getenv("BUILDKITE_TAG")
|
||||
|
@ -28,38 +24,23 @@ var publicRepo = regexp.MustCompile(`.*:.*`)
|
|||
var tags = dockerTags.FindStringSubmatch(ciTag)
|
||||
|
||||
func init() {
|
||||
DockerBuildCmd.PersistentFlags().StringVar(&arch, "arch", defaultArch, "target architecture among: "+strings.Join(supportedArch, ", "))
|
||||
DockerPushCmd.PersistentFlags().StringVar(&arch, "arch", defaultArch, "target architecture among: "+strings.Join(supportedArch, ", "))
|
||||
DockerBuildCmd.PersistentFlags().StringVar(&container, "container", defaultContainer, "target container among: "+strings.Join(containers, ", "))
|
||||
}
|
||||
|
||||
func checkArchIsSupported(arch string) {
|
||||
for _, a := range supportedArch {
|
||||
if arch == a {
|
||||
func checkContainerIsSupported(container string) {
|
||||
for _, v := range containers {
|
||||
if container == v {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
log.Fatal("Architecture is not supported. Please select one of " + strings.Join(supportedArch, ", ") + ".")
|
||||
log.Fatal("Container is not supported. Please select one of " + strings.Join(containers, ", ") + ".")
|
||||
}
|
||||
|
||||
func dockerBuildOfficialImage(arch string) error {
|
||||
docker := &Docker{}
|
||||
// Set default Architecture Dockerfile to amd64.
|
||||
dockerfile := "Dockerfile"
|
||||
|
||||
// If not the default value.
|
||||
if arch != defaultArch {
|
||||
dockerfile = fmt.Sprintf("%s.%s", dockerfile, arch)
|
||||
}
|
||||
|
||||
if arch == "arm32v7" || arch == "arm64v8" {
|
||||
if buildkiteQEMU != stringTrue {
|
||||
err := utils.CommandWithStdout("docker", "run", "--rm", "--privileged", "multiarch/qemu-user-static", "--reset", "-p", "yes").Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
filename := "Dockerfile"
|
||||
dockerfile := fmt.Sprintf("%s.%s", filename, arch)
|
||||
|
||||
flags, err := getXFlags(ciBranch, os.Getenv("BUILDKITE_BUILD_NUMBER"), "")
|
||||
if err != nil {
|
||||
|
@ -76,8 +57,8 @@ var DockerBuildCmd = &cobra.Command{
|
|||
Short: "Build the docker image of Authelia",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
log.Infof("Building Docker image %s...", DockerImageName)
|
||||
checkArchIsSupported(arch)
|
||||
err := dockerBuildOfficialImage(arch)
|
||||
checkContainerIsSupported(container)
|
||||
err := dockerBuildOfficialImage(container)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -92,23 +73,11 @@ var DockerBuildCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
// DockerPushCmd Command for pushing Authelia docker image to DockerHub.
|
||||
var DockerPushCmd = &cobra.Command{
|
||||
Use: "push-image",
|
||||
Short: "Publish Authelia docker image to Docker Hub",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
log.Infof("Pushing Docker image %s to Docker Hub...", DockerImageName)
|
||||
checkArchIsSupported(arch)
|
||||
publishDockerImage(arch)
|
||||
},
|
||||
}
|
||||
|
||||
// DockerManifestCmd Command for pushing Authelia docker manifest to DockerHub.
|
||||
var DockerManifestCmd = &cobra.Command{
|
||||
Use: "push-manifest",
|
||||
Short: "Publish Authelia docker manifest to Docker Hub",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
log.Infof("Pushing Docker manifest of %s to Docker Hub...", DockerImageName)
|
||||
publishDockerManifest()
|
||||
},
|
||||
}
|
||||
|
@ -142,125 +111,54 @@ func login(docker *Docker, registry string) {
|
|||
}
|
||||
}
|
||||
|
||||
func deploy(docker *Docker, tag, registry string) {
|
||||
imageWithTag := registry + "/" + DockerImageName + ":" + tag
|
||||
func deployManifest(docker *Docker, tag string) {
|
||||
log.Infof("Docker manifest %s:%s will be deployed on %s and %s", DockerImageName, tag, dockerhub, ghcr)
|
||||
|
||||
log.Infof("Docker image %s will be deployed on %s", imageWithTag, registry)
|
||||
dockerhub := dockerhub + "/" + DockerImageName + ":" + tag
|
||||
ghcr := ghcr + "/" + DockerImageName + ":" + tag
|
||||
|
||||
if err := docker.Tag(DockerImageName, imageWithTag); err != nil {
|
||||
if err := docker.Manifest(dockerhub, ghcr); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := docker.Push(imageWithTag); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func deployManifest(docker *Docker, tag, amd64tag, arm32v7tag, arm64v8tag, registry string) {
|
||||
dockerImagePrefix := registry + "/" + DockerImageName + ":"
|
||||
|
||||
log.Infof("Docker manifest %s%s will be deployed on %s", dockerImagePrefix, tag, registry)
|
||||
|
||||
err := docker.Manifest(dockerImagePrefix+tag, dockerImagePrefix+amd64tag, dockerImagePrefix+arm32v7tag, dockerImagePrefix+arm64v8tag)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
tags := []string{amd64tag, arm32v7tag, arm64v8tag}
|
||||
|
||||
if registry == dockerhub {
|
||||
for _, t := range tags {
|
||||
log.Infof("Docker removing tag for %s%s on Docker Hub", dockerImagePrefix, t)
|
||||
|
||||
if err := utils.RunFuncWithRetry(3, 10*time.Second, func() (err error) {
|
||||
err = docker.CleanTag(t)
|
||||
return
|
||||
}); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func publishDockerImage(arch string) {
|
||||
docker := &Docker{}
|
||||
|
||||
for _, registry := range registries {
|
||||
switch {
|
||||
case ciTag != "":
|
||||
if len(tags) == 4 {
|
||||
log.Infof("Detected tags: '%s' | '%s' | '%s'", tags[1], tags[2], tags[3])
|
||||
login(docker, registry)
|
||||
deploy(docker, tags[1]+"-"+arch, registry)
|
||||
|
||||
if !ignoredSuffixes.MatchString(ciTag) {
|
||||
deploy(docker, tags[2]+"-"+arch, registry)
|
||||
deploy(docker, tags[3]+"-"+arch, registry)
|
||||
deploy(docker, "latest-"+arch, registry)
|
||||
}
|
||||
} else {
|
||||
log.Fatal("Docker image will not be published, the specified tag does not conform to the standard")
|
||||
}
|
||||
case ciBranch != masterTag && !publicRepo.MatchString(ciBranch):
|
||||
login(docker, registry)
|
||||
deploy(docker, ciBranch+"-"+arch, registry)
|
||||
case ciBranch != masterTag && publicRepo.MatchString(ciBranch):
|
||||
login(docker, registry)
|
||||
deploy(docker, "PR"+ciPullRequest+"-"+arch, registry)
|
||||
case ciBranch == masterTag && ciPullRequest == stringFalse:
|
||||
login(docker, registry)
|
||||
deploy(docker, "master-"+arch, registry)
|
||||
default:
|
||||
log.Info("Docker image will not be published")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func publishDockerManifest() {
|
||||
docker := &Docker{}
|
||||
|
||||
for _, registry := range registries {
|
||||
switch {
|
||||
case ciTag != "":
|
||||
if len(tags) == 4 {
|
||||
log.Infof("Detected tags: '%s' | '%s' | '%s'", tags[1], tags[2], tags[3])
|
||||
login(docker, registry)
|
||||
deployManifest(docker, tags[1], tags[1]+"-amd64", tags[1]+"-arm32v7", tags[1]+"-arm64v8", registry)
|
||||
|
||||
if registry == dockerhub {
|
||||
login(docker, dockerhub)
|
||||
login(docker, ghcr)
|
||||
deployManifest(docker, tags[1])
|
||||
publishDockerReadme(docker)
|
||||
}
|
||||
|
||||
if !ignoredSuffixes.MatchString(ciTag) {
|
||||
deployManifest(docker, tags[2], tags[2]+"-amd64", tags[2]+"-arm32v7", tags[2]+"-arm64v8", registry)
|
||||
deployManifest(docker, tags[3], tags[3]+"-amd64", tags[3]+"-arm32v7", tags[3]+"-arm64v8", registry)
|
||||
deployManifest(docker, "latest", "latest-amd64", "latest-arm32v7", "latest-arm64v8", registry)
|
||||
|
||||
if registry == dockerhub {
|
||||
deployManifest(docker, tags[2])
|
||||
deployManifest(docker, tags[3])
|
||||
deployManifest(docker, "latest")
|
||||
publishDockerReadme(docker)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Fatal("Docker manifest will not be published, the specified tag does not conform to the standard")
|
||||
}
|
||||
case ciBranch != masterTag && !publicRepo.MatchString(ciBranch):
|
||||
login(docker, registry)
|
||||
deployManifest(docker, ciBranch, ciBranch+"-amd64", ciBranch+"-arm32v7", ciBranch+"-arm64v8", registry)
|
||||
login(docker, dockerhub)
|
||||
login(docker, ghcr)
|
||||
deployManifest(docker, ciBranch)
|
||||
case ciBranch != masterTag && publicRepo.MatchString(ciBranch):
|
||||
login(docker, registry)
|
||||
deployManifest(docker, "PR"+ciPullRequest, "PR"+ciPullRequest+"-amd64", "PR"+ciPullRequest+"-arm32v7", "PR"+ciPullRequest+"-arm64v8", registry)
|
||||
login(docker, dockerhub)
|
||||
login(docker, ghcr)
|
||||
deployManifest(docker, "PR"+ciPullRequest)
|
||||
case ciBranch == masterTag && ciPullRequest == stringFalse:
|
||||
login(docker, registry)
|
||||
deployManifest(docker, "master", "master-amd64", "master-arm32v7", "master-arm64v8", registry)
|
||||
|
||||
if registry == dockerhub {
|
||||
login(docker, dockerhub)
|
||||
login(docker, ghcr)
|
||||
deployManifest(docker, "master")
|
||||
publishDockerReadme(docker)
|
||||
}
|
||||
default:
|
||||
log.Info("Docker manifest will not be published")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func publishDockerReadme(docker *Docker) {
|
||||
|
|
|
@ -9,14 +9,11 @@ var DockerImageName = "authelia/authelia"
|
|||
// IntermediateDockerImageName local name of the docker image.
|
||||
var IntermediateDockerImageName = "authelia:dist"
|
||||
|
||||
var registries = []string{"docker.io", "ghcr.io"}
|
||||
|
||||
const dockerhub = "docker.io"
|
||||
const ghcr = "ghcr.io"
|
||||
|
||||
const masterTag = "master"
|
||||
const stringFalse = "false"
|
||||
const stringTrue = "true"
|
||||
const webDirectory = "web"
|
||||
|
||||
const fmtLDFLAGSX = "-X 'github.com/authelia/authelia/v4/internal/utils.%s=%s'"
|
||||
|
|
|
@ -22,40 +22,12 @@ func (d *Docker) Tag(image, tag string) error {
|
|||
|
||||
// Login login to the dockerhub registry.
|
||||
func (d *Docker) Login(username, password, registry string) error {
|
||||
return utils.CommandWithStdout("docker", "login", registry, "-u", username, "-p", password).Run()
|
||||
}
|
||||
|
||||
// Push push a docker image to dockerhub.
|
||||
func (d *Docker) Push(tag string) error {
|
||||
return utils.CommandWithStdout("docker", "push", tag).Run()
|
||||
return utils.CommandWithStdout("bash", "-c", `echo `+password+` | docker login `+registry+` --password-stdin -u `+username).Run()
|
||||
}
|
||||
|
||||
// Manifest push a docker manifest to dockerhub.
|
||||
func (d *Docker) Manifest(tag, amd64tag, arm32v7tag, arm64v8tag string) error {
|
||||
err := utils.CommandWithStdout("docker", "manifest", "create", tag, amd64tag, arm32v7tag, arm64v8tag).Run()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = utils.CommandWithStdout("docker", "manifest", "annotate", tag, arm32v7tag, "--os", "linux", "--arch", "arm").Run()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = utils.CommandWithStdout("docker", "manifest", "annotate", tag, arm64v8tag, "--os", "linux", "--arch", "arm64", "--variant", "v8").Run()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return utils.CommandWithStdout("docker", "manifest", "push", "--purge", tag).Run()
|
||||
}
|
||||
|
||||
// CleanTag remove a tag from dockerhub.
|
||||
func (d *Docker) CleanTag(tag string) error {
|
||||
return utils.CommandWithStdout("bash", "-c", `token=$(curl -fs --retry 3 -H "Content-Type: application/json" -X "POST" -d '{"username": "'$DOCKER_USERNAME'", "password": "'$DOCKER_PASSWORD'"}' https://hub.docker.com/v2/users/login/ | jq -r .token) && curl -fs --retry 3 -o /dev/null -L -X "DELETE" -H "Authorization: JWT $token" https://hub.docker.com/v2/repositories/`+DockerImageName+"/tags/"+tag+"/").Run()
|
||||
func (d *Docker) Manifest(tag1, tag2 string) error {
|
||||
return utils.CommandWithStdout("docker", "build", "-t", tag1, "-t", tag2, "--platform", "linux/amd64,linux/arm/v7,linux/arm64", "--builder", "buildx", "--push", ".").Run()
|
||||
}
|
||||
|
||||
// PublishReadme push README.md to dockerhub.
|
||||
|
|
|
@ -50,7 +50,7 @@ var Commands = []AutheliaCommandDefinition{
|
|||
{
|
||||
Name: "docker",
|
||||
Short: "Commands related to building and publishing docker image",
|
||||
SubCommands: CobraCommands{DockerBuildCmd, DockerPushCmd, DockerManifestCmd},
|
||||
SubCommands: CobraCommands{DockerBuildCmd, DockerManifestCmd},
|
||||
},
|
||||
{
|
||||
Name: "serve [config]",
|
||||
|
|
Loading…
Reference in New Issue