diff --git a/.github/workflows/main-docker-alpine.yml b/.github/workflows/main-docker-alpine.yml deleted file mode 100644 index cbf195c86..000000000 --- a/.github/workflows/main-docker-alpine.yml +++ /dev/null @@ -1,143 +0,0 @@ -on: - workflow_dispatch: - -env: - GHCR_REGISTRY: ghcr.io - DOCKERHUB_REGISTRY: docker.io - IMAGE_NAME: ${{ github.repository }} - TEST_TAG: triliumnext/notes:test - PLATFORMS: linux/amd64 - -jobs: - test_docker: - name: Check Docker build - runs-on: ubuntu-latest - steps: - - name: Checkout the repository - uses: actions/checkout@v4 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Set up node & dependencies - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: "npm" - - - run: npm ci - - - name: Run the TypeScript build - run: npx tsc - - - name: Create server-package.json - run: cat package.json | grep -v electron > server-package.json - - - name: Build and export to Docker - uses: docker/build-push-action@v6 - with: - context: . - load: true - tags: ${{ env.TEST_TAG }} - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Run the container in the background - run: docker run -d --rm --name trilium_local ${{ env.TEST_TAG }} - - - name: Wait for the healthchecks to pass - uses: stringbean/docker-healthcheck-action@v1 - with: - container: trilium_local - wait-time: 50 - require-status: running - require-healthy: true - - build_docker: - name: Build Docker images - runs-on: ubuntu-latest - needs: - - test_docker - permissions: - contents: read - packages: write - attestations: write - id-token: write - steps: - - uses: actions/checkout@v4 - - name: Extract metadata (tags, labels) for GHCR image - id: ghcr-meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=tag - type=sha - - name: Extract metadata (tags, labels) for DockerHub image - id: dh-meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=tag - type=sha - - name: Set up node & dependencies - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: "npm" - - run: npm ci - - name: Run the TypeScript build - run: npx tsc - - name: Create server-package.json - run: cat package.json | grep -v electron > server-package.json - - name: Log in to the GHCR container registry - uses: docker/login-action@v2 - with: - registry: ${{ env.GHCR_REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - uses: docker/setup-buildx-action@v3 - - name: Build and push container image to GHCR - uses: docker/build-push-action@v6 - id: ghcr-push - with: - file: ./Dockerfile.alpine - context: . - platforms: ${{ env.PLATFORMS }} - push: true - tags: ${{ steps.ghcr-meta.outputs.tags }} - labels: ${{ steps.ghcr-meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - - name: Generate and push artifact attestation to GHCR - uses: actions/attest-build-provenance@v1 - with: - subject-name: ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME}} - subject-digest: ${{ steps.ghcr-push.outputs.digest }} - push-to-registry: true - - name: Log in to the DockerHub container registry - uses: docker/login-action@v2 - with: - registry: ${{ env.DOCKERHUB_REGISTRY }} - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Build and push image to DockerHub - uses: docker/build-push-action@v6 - id: dh-push - with: - context: . - platforms: ${{ env.PLATFORMS }} - push: true - tags: ${{ steps.dh-meta.outputs.tags }} - labels: ${{ steps.dh-meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - - name: Generate and push artifact attestation to DockerHub - uses: actions/attest-build-provenance@v1 - with: - subject-name: ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME}} - subject-digest: ${{ steps.dh-push.outputs.digest }} - push-to-registry: true \ No newline at end of file diff --git a/.github/workflows/main-docker.yml b/.github/workflows/main-docker.yml index 70a3592b1..049b13392 100644 --- a/.github/workflows/main-docker.yml +++ b/.github/workflows/main-docker.yml @@ -9,19 +9,24 @@ on: - "bin/**" tags: - "v*" - workflow_dispatch: + workflow_dispatch: env: GHCR_REGISTRY: ghcr.io DOCKERHUB_REGISTRY: docker.io - IMAGE_NAME: ${{ github.repository }} - TEST_TAG: triliumnext/notes:test - PLATFORMS: linux/amd64,linux/arm64,linux/arm/v7 + IMAGE_NAME: ${{ github.repository_owner }}/notes + TEST_TAG: ${{ github.repository_owner }}/notes:test jobs: + test_docker: name: Check Docker build runs-on: ubuntu-latest + strategy: + matrix: + include: + - dockerfile: Dockerfile.alpine + - dockerfile: Dockerfile steps: - name: Checkout the repository uses: actions/checkout@v4 @@ -47,6 +52,7 @@ jobs: uses: docker/build-push-action@v6 with: context: . + file: ${{ matrix.dockerfile }} load: true tags: ${{ env.TEST_TAG }} cache-from: type=gha @@ -63,7 +69,7 @@ jobs: require-status: running require-healthy: true - build_docker: + build: name: Build Docker images runs-on: ubuntu-latest needs: @@ -73,26 +79,43 @@ jobs: packages: write attestations: write id-token: write - steps: - - uses: actions/checkout@v4 - - name: Extract metadata (tags, labels) for GHCR image - id: ghcr-meta + strategy: + fail-fast: false + matrix: + include: + - dockerfile: Dockerfile.alpine + platform: linux/amd64 + - dockerfile: Dockerfile + platform: linux/arm64 + - dockerfile: Dockerfile + platform: linux/arm/v7 + steps: + - name: Prepare + run: | + platform=${{ matrix.platform }} + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + + - name: Checkout repository + uses: actions/checkout@v4 + - name: Docker meta + id: meta uses: docker/metadata-action@v4 with: - images: ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=tag - type=sha - - name: Extract metadata (tags, labels) for DockerHub image - id: dh-meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }} + images: | + ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }} + ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=ref,event=branch type=ref,event=tag type=sha + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Set up node & dependencies uses: actions/setup-node@v4 with: @@ -103,50 +126,106 @@ jobs: run: npx tsc - name: Create server-package.json run: cat package.json | grep -v electron > server-package.json - - name: Log in to the GHCR container registry + + - name: Login to GHCR uses: docker/login-action@v2 with: registry: ${{ env.GHCR_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - uses: docker/setup-buildx-action@v3 - - name: Build and push container image to GHCR - uses: docker/build-push-action@v6 - id: ghcr-push - with: - context: . - platforms: ${{ env.PLATFORMS }} - push: true - tags: ${{ steps.ghcr-meta.outputs.tags }} - labels: ${{ steps.ghcr-meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - - name: Generate and push artifact attestation to GHCR - uses: actions/attest-build-provenance@v1 - with: - subject-name: ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME}} - subject-digest: ${{ steps.ghcr-push.outputs.digest }} - push-to-registry: true - - name: Log in to the DockerHub container registry + + - name: Login to DockerHub uses: docker/login-action@v2 with: registry: ${{ env.DOCKERHUB_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Build and push image to DockerHub + + - name: Build and push by digest + id: build uses: docker/build-push-action@v6 - id: dh-push with: context: . - platforms: ${{ env.PLATFORMS }} - push: true - tags: ${{ steps.dh-meta.outputs.tags }} - labels: ${{ steps.dh-meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - - name: Generate and push artifact attestation to DockerHub - uses: actions/attest-build-provenance@v1 + file: ${{ matrix.dockerfile }} + platforms: ${{ matrix.platform }} + labels: ${{ steps.meta.outputs.labels }} + outputs: type=image,name=${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true + + - name: Export digest + run: | + mkdir -p /tmp/digests + digest="${{ steps.build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v4 with: - subject-name: ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME}} - subject-digest: ${{ steps.dh-push.outputs.digest }} - push-to-registry: true \ No newline at end of file + name: digests-${{ env.PLATFORM_PAIR }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + merge: + name: Merge manifest lists + runs-on: ubuntu-latest + needs: + - build + steps: + - name: Download digests + uses: actions/download-artifact@v4 + with: + path: /tmp/digests + pattern: digests-* + merge-multiple: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v4 + with: + images: | + ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }} + ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Login to GHCR + uses: docker/login-action@v2 + with: + registry: ${{ env.GHCR_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + registry: ${{ env.DOCKERHUB_REGISTRY }} + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Create manifest list and push + working-directory: /tmp/digests + run: | + # Extract the branch or tag name from the ref + REF_NAME=$(echo "${GITHUB_REF}" | sed 's/refs\/heads\///' | sed 's/refs\/tags\///') + + # Get the first 7 characters of the commit SHA + SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7) + + # Create and push the manifest list with both the branch/tag name and the commit SHA + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + -t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:${REF_NAME} \ + -t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:sha256-${{ github.sha }} \ + -t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${SHORT_SHA} \ + $(printf '${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) + + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + -t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${REF_NAME} \ + -t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:sha256-${{ github.sha }} \ + -t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${SHORT_SHA} \ + $(printf '${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) + + - name: Inspect image + run: | + docker buildx imagetools inspect ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} + docker buildx imagetools inspect ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} \ No newline at end of file diff --git a/start-docker.sh b/start-docker.sh index 624db0dd2..1e5800608 100755 --- a/start-docker.sh +++ b/start-docker.sh @@ -1,7 +1,7 @@ -#!/usr/bin/env bash +#!/bin/sh -[[ ! -z "${USER_UID}" ]] && usermod -u ${USER_UID} node || echo "No USER_UID specified, leaving 1000" -[[ ! -z "${USER_GID}" ]] && groupmod -og ${USER_GID} node || echo "No USER_GID specified, leaving 1000" +[ ! -z "${USER_UID}" ] && usermod -u ${USER_UID} node || echo "No USER_UID specified, leaving 1000" +[ ! -z "${USER_GID}" ] && groupmod -og ${USER_GID} node || echo "No USER_GID specified, leaving 1000" chown -R node:node /home/node -exec su -c "node ./src/www" node +exec su -c "node ./src/www" node \ No newline at end of file