mirror of
				https://github.com/steveiliop56/tinyauth.git
				synced 2025-10-31 06:05:43 +00:00 
			
		
		
		
	feat: distroless image
This commit is contained in:
		
							
								
								
									
										161
									
								
								.github/workflows/nightly.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										161
									
								
								.github/workflows/nightly.yml
									
									
									
									
										vendored
									
									
								
							| @@ -171,6 +171,8 @@ jobs: | |||||||
|           labels: ${{ steps.meta.outputs.labels }} |           labels: ${{ steps.meta.outputs.labels }} | ||||||
|           tags: ghcr.io/${{ github.repository_owner }}/tinyauth |           tags: ghcr.io/${{ github.repository_owner }}/tinyauth | ||||||
|           outputs: type=image,push-by-digest=true,name-canonical=true,push=true |           outputs: type=image,push-by-digest=true,name-canonical=true,push=true | ||||||
|  |           cache-from: type=gha | ||||||
|  |           cache-to: type=gha,mode=max | ||||||
|           build-args: | |           build-args: | | ||||||
|             VERSION=${{ needs.generate-metadata.outputs.VERSION }} |             VERSION=${{ needs.generate-metadata.outputs.VERSION }} | ||||||
|             COMMIT_HASH=${{ needs.generate-metadata.outputs.COMMIT_HASH }} |             COMMIT_HASH=${{ needs.generate-metadata.outputs.COMMIT_HASH }} | ||||||
| @@ -190,6 +192,64 @@ jobs: | |||||||
|           if-no-files-found: error |           if-no-files-found: error | ||||||
|           retention-days: 1 |           retention-days: 1 | ||||||
|  |  | ||||||
|  |   image-build-distroless: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     needs: | ||||||
|  |       - create-release | ||||||
|  |       - generate-metadata | ||||||
|  |       - image-build | ||||||
|  |     steps: | ||||||
|  |       - name: Checkout | ||||||
|  |         uses: actions/checkout@v4 | ||||||
|  |         with: | ||||||
|  |           ref: nightly | ||||||
|  |  | ||||||
|  |       - name: Docker meta | ||||||
|  |         id: meta | ||||||
|  |         uses: docker/metadata-action@v5 | ||||||
|  |         with: | ||||||
|  |           images: ghcr.io/${{ github.repository_owner }}/tinyauth | ||||||
|  |  | ||||||
|  |       - name: Login to GitHub Container Registry | ||||||
|  |         uses: docker/login-action@v3 | ||||||
|  |         with: | ||||||
|  |           registry: ghcr.io | ||||||
|  |           username: ${{ github.repository_owner }} | ||||||
|  |           password: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  |  | ||||||
|  |       - name: Set up Docker Buildx | ||||||
|  |         uses: docker/setup-buildx-action@v3 | ||||||
|  |  | ||||||
|  |       - name: Build and push | ||||||
|  |         uses: docker/build-push-action@v6 | ||||||
|  |         id: build | ||||||
|  |         with: | ||||||
|  |           platforms: linux/amd64 | ||||||
|  |           labels: ${{ steps.meta.outputs.labels }} | ||||||
|  |           tags: ghcr.io/${{ github.repository_owner }}/tinyauth | ||||||
|  |           outputs: type=image,push-by-digest=true,name-canonical=true,push=true | ||||||
|  |           file: Dockerfile.distroless | ||||||
|  |           cache-from: type=gha | ||||||
|  |           cache-to: type=gha,mode=max | ||||||
|  |           build-args: | | ||||||
|  |             VERSION=${{ needs.generate-metadata.outputs.VERSION }} | ||||||
|  |             COMMIT_HASH=${{ needs.generate-metadata.outputs.COMMIT_HASH }} | ||||||
|  |             BUILD_TIMESTAMP=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }} | ||||||
|  |  | ||||||
|  |       - name: Export digest | ||||||
|  |         run: | | ||||||
|  |           mkdir -p ${{ runner.temp }}/digests | ||||||
|  |           digest="${{ steps.build.outputs.digest }}" | ||||||
|  |           touch "${{ runner.temp }}/digests/${digest#sha256:}" | ||||||
|  |  | ||||||
|  |       - name: Upload digest | ||||||
|  |         uses: actions/upload-artifact@v4 | ||||||
|  |         with: | ||||||
|  |           name: digests-distoless-linux-amd64 | ||||||
|  |           path: ${{ runner.temp }}/digests/* | ||||||
|  |           if-no-files-found: error | ||||||
|  |           retention-days: 1 | ||||||
|  |  | ||||||
|   image-build-arm: |   image-build-arm: | ||||||
|     runs-on: ubuntu-24.04-arm |     runs-on: ubuntu-24.04-arm | ||||||
|     needs: |     needs: | ||||||
| @@ -217,10 +277,6 @@ jobs: | |||||||
|       - name: Set up Docker Buildx |       - name: Set up Docker Buildx | ||||||
|         uses: docker/setup-buildx-action@v3 |         uses: docker/setup-buildx-action@v3 | ||||||
|  |  | ||||||
|       - name: Set version |  | ||||||
|         run: | |  | ||||||
|           echo nightly > internal/assets/version |  | ||||||
|  |  | ||||||
|       - name: Build and push |       - name: Build and push | ||||||
|         uses: docker/build-push-action@v6 |         uses: docker/build-push-action@v6 | ||||||
|         id: build |         id: build | ||||||
| @@ -229,6 +285,8 @@ jobs: | |||||||
|           labels: ${{ steps.meta.outputs.labels }} |           labels: ${{ steps.meta.outputs.labels }} | ||||||
|           tags: ghcr.io/${{ github.repository_owner }}/tinyauth |           tags: ghcr.io/${{ github.repository_owner }}/tinyauth | ||||||
|           outputs: type=image,push-by-digest=true,name-canonical=true,push=true |           outputs: type=image,push-by-digest=true,name-canonical=true,push=true | ||||||
|  |           cache-from: type=gha | ||||||
|  |           cache-to: type=gha,mode=max | ||||||
|           build-args: | |           build-args: | | ||||||
|             VERSION=${{ needs.generate-metadata.outputs.VERSION }} |             VERSION=${{ needs.generate-metadata.outputs.VERSION }} | ||||||
|             COMMIT_HASH=${{ needs.generate-metadata.outputs.COMMIT_HASH }} |             COMMIT_HASH=${{ needs.generate-metadata.outputs.COMMIT_HASH }} | ||||||
| @@ -248,6 +306,64 @@ jobs: | |||||||
|           if-no-files-found: error |           if-no-files-found: error | ||||||
|           retention-days: 1 |           retention-days: 1 | ||||||
|  |  | ||||||
|  |   image-build-arm-distroless: | ||||||
|  |     runs-on: ubuntu-24.04-arm | ||||||
|  |     needs: | ||||||
|  |       - create-release | ||||||
|  |       - generate-metadata | ||||||
|  |       - image-build-arm | ||||||
|  |     steps: | ||||||
|  |       - name: Checkout | ||||||
|  |         uses: actions/checkout@v4 | ||||||
|  |         with: | ||||||
|  |           ref: nightly | ||||||
|  |  | ||||||
|  |       - name: Docker meta | ||||||
|  |         id: meta | ||||||
|  |         uses: docker/metadata-action@v5 | ||||||
|  |         with: | ||||||
|  |           images: ghcr.io/${{ github.repository_owner }}/tinyauth | ||||||
|  |  | ||||||
|  |       - name: Login to GitHub Container Registry | ||||||
|  |         uses: docker/login-action@v3 | ||||||
|  |         with: | ||||||
|  |           registry: ghcr.io | ||||||
|  |           username: ${{ github.repository_owner }} | ||||||
|  |           password: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  |  | ||||||
|  |       - name: Set up Docker Buildx | ||||||
|  |         uses: docker/setup-buildx-action@v3 | ||||||
|  |  | ||||||
|  |       - name: Build and push | ||||||
|  |         uses: docker/build-push-action@v6 | ||||||
|  |         id: build | ||||||
|  |         with: | ||||||
|  |           platforms: linux/arm64 | ||||||
|  |           labels: ${{ steps.meta.outputs.labels }} | ||||||
|  |           tags: ghcr.io/${{ github.repository_owner }}/tinyauth | ||||||
|  |           outputs: type=image,push-by-digest=true,name-canonical=true,push=true | ||||||
|  |           file: Dockerfile.distroless | ||||||
|  |           cache-from: type=gha | ||||||
|  |           cache-to: type=gha,mode=max | ||||||
|  |           build-args: | | ||||||
|  |             VERSION=${{ needs.generate-metadata.outputs.VERSION }} | ||||||
|  |             COMMIT_HASH=${{ needs.generate-metadata.outputs.COMMIT_HASH }} | ||||||
|  |             BUILD_TIMESTAMP=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }} | ||||||
|  |  | ||||||
|  |       - name: Export digest | ||||||
|  |         run: | | ||||||
|  |           mkdir -p ${{ runner.temp }}/digests | ||||||
|  |           digest="${{ steps.build.outputs.digest }}" | ||||||
|  |           touch "${{ runner.temp }}/digests/${digest#sha256:}" | ||||||
|  |  | ||||||
|  |       - name: Upload digest | ||||||
|  |         uses: actions/upload-artifact@v4 | ||||||
|  |         with: | ||||||
|  |           name: digests-distroless-linux-arm64 | ||||||
|  |           path: ${{ runner.temp }}/digests/* | ||||||
|  |           if-no-files-found: error | ||||||
|  |           retention-days: 1 | ||||||
|  |  | ||||||
|   image-merge: |   image-merge: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     needs: |     needs: | ||||||
| @@ -285,6 +401,43 @@ jobs: | |||||||
|           docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ |           docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ | ||||||
|             $(printf 'ghcr.io/${{ github.repository_owner }}/tinyauth@sha256:%s ' *) |             $(printf 'ghcr.io/${{ github.repository_owner }}/tinyauth@sha256:%s ' *) | ||||||
|  |  | ||||||
|  |   image-merge-distroless: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     needs: | ||||||
|  |       - image-build-distroless | ||||||
|  |       - image-build-arm-distroless | ||||||
|  |     steps: | ||||||
|  |       - name: Download digests | ||||||
|  |         uses: actions/download-artifact@v4 | ||||||
|  |         with: | ||||||
|  |           path: ${{ runner.temp }}/digests | ||||||
|  |           pattern: digests-distroless-* | ||||||
|  |           merge-multiple: true | ||||||
|  |  | ||||||
|  |       - name: Login to GitHub Container Registry | ||||||
|  |         uses: docker/login-action@v3 | ||||||
|  |         with: | ||||||
|  |           registry: ghcr.io | ||||||
|  |           username: ${{ github.repository_owner }} | ||||||
|  |           password: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  |  | ||||||
|  |       - name: Set up Docker Buildx | ||||||
|  |         uses: docker/setup-buildx-action@v3 | ||||||
|  |  | ||||||
|  |       - name: Docker meta | ||||||
|  |         id: meta | ||||||
|  |         uses: docker/metadata-action@v5 | ||||||
|  |         with: | ||||||
|  |           images: ghcr.io/${{ github.repository_owner }}/tinyauth | ||||||
|  |           tags: | | ||||||
|  |             type=raw,nightly-distroless | ||||||
|  |  | ||||||
|  |       - name: Create manifest list and push | ||||||
|  |         working-directory: ${{ runner.temp }}/digests | ||||||
|  |         run: | | ||||||
|  |           docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ | ||||||
|  |             $(printf 'ghcr.io/${{ github.repository_owner }}/tinyauth@sha256:%s ' *) | ||||||
|  |  | ||||||
|   update-release: |   update-release: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     needs: |     needs: | ||||||
|   | |||||||
| @@ -51,4 +51,6 @@ EXPOSE 3000 | |||||||
|  |  | ||||||
| VOLUME ["/data"] | VOLUME ["/data"] | ||||||
|  |  | ||||||
| ENTRYPOINT ["./tinyauth"] | HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 CMD ["/tinyauth/tinyauth", "healthcheck"] | ||||||
|  |  | ||||||
|  | ENTRYPOINT ["tinyauth"] | ||||||
							
								
								
									
										56
									
								
								Dockerfile.distroless
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								Dockerfile.distroless
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | |||||||
|  | # Site builder | ||||||
|  | FROM oven/bun:1.2.23-alpine AS frontend-builder | ||||||
|  |  | ||||||
|  | WORKDIR /frontend | ||||||
|  |  | ||||||
|  | COPY ./frontend/package.json ./ | ||||||
|  | COPY ./frontend/bun.lock ./ | ||||||
|  |  | ||||||
|  | RUN bun install | ||||||
|  |  | ||||||
|  | COPY ./frontend/public ./public | ||||||
|  | COPY ./frontend/src ./src | ||||||
|  | COPY ./frontend/eslint.config.js ./ | ||||||
|  | COPY ./frontend/index.html ./ | ||||||
|  | COPY ./frontend/tsconfig.json ./ | ||||||
|  | COPY ./frontend/tsconfig.app.json ./ | ||||||
|  | COPY ./frontend/tsconfig.node.json ./ | ||||||
|  | COPY ./frontend/vite.config.ts ./ | ||||||
|  |  | ||||||
|  | RUN bun run build | ||||||
|  |  | ||||||
|  | # Builder | ||||||
|  | FROM golang:1.25-alpine3.21 AS builder | ||||||
|  |  | ||||||
|  | ARG VERSION | ||||||
|  | ARG COMMIT_HASH | ||||||
|  | ARG BUILD_TIMESTAMP | ||||||
|  |  | ||||||
|  | WORKDIR /tinyauth | ||||||
|  |  | ||||||
|  | COPY go.mod ./ | ||||||
|  | COPY go.sum ./ | ||||||
|  |  | ||||||
|  | RUN go mod download | ||||||
|  |  | ||||||
|  | COPY ./main.go ./ | ||||||
|  | COPY ./cmd ./cmd | ||||||
|  | COPY ./internal ./internal | ||||||
|  | COPY --from=frontend-builder /frontend/dist ./internal/assets/dist | ||||||
|  |  | ||||||
|  | RUN CGO_ENABLED=0 go build -ldflags "-s -w -X tinyauth/internal/config.Version=${VERSION} -X tinyauth/internal/config.CommitHash=${COMMIT_HASH} -X tinyauth/internal/config.BuildTimestamp=${BUILD_TIMESTAMP}"  | ||||||
|  |   | ||||||
|  | # Runner | ||||||
|  | FROM gcr.io/distroless/static-debian12:latest AS runner | ||||||
|  |  | ||||||
|  | WORKDIR /tinyauth | ||||||
|  |  | ||||||
|  | COPY --from=builder /tinyauth/tinyauth ./ | ||||||
|  |  | ||||||
|  | EXPOSE 3000 | ||||||
|  |  | ||||||
|  | VOLUME ["/data"] | ||||||
|  |  | ||||||
|  | HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 CMD ["/tinyauth/tinyauth", "healthcheck"] | ||||||
|  |  | ||||||
|  | ENTRYPOINT ["tinyauth"] | ||||||
| @@ -17,24 +17,24 @@ type healthzResponse struct { | |||||||
| 	Message string `json:"message"` | 	Message string `json:"message"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type healthCmd struct { | type healthcheckCmd struct { | ||||||
| 	root *cobra.Command | 	root *cobra.Command | ||||||
| 	cmd  *cobra.Command | 	cmd  *cobra.Command | ||||||
| 
 | 
 | ||||||
| 	viper *viper.Viper | 	viper *viper.Viper | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func newHealthCmd(root *cobra.Command) *healthCmd { | func newHealthcheckCmd(root *cobra.Command) *healthcheckCmd { | ||||||
| 	return &healthCmd{ | 	return &healthcheckCmd{ | ||||||
| 		root:  root, | 		root:  root, | ||||||
| 		viper: viper.New(), | 		viper: viper.New(), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *healthCmd) Register() { | func (c *healthcheckCmd) Register() { | ||||||
| 	c.cmd = &cobra.Command{ | 	c.cmd = &cobra.Command{ | ||||||
| 		Use:   "health", | 		Use:   "healthcheck [app-url]", | ||||||
| 		Short: "Health check", | 		Short: "Perform a health check", | ||||||
| 		Long:  `Use the health check endpoint to verify that Tinyauth is running and it's healthy.`, | 		Long:  `Use the health check endpoint to verify that Tinyauth is running and it's healthy.`, | ||||||
| 		Run:   c.run, | 		Run:   c.run, | ||||||
| 	} | 	} | ||||||
| @@ -46,26 +46,34 @@ func (c *healthCmd) Register() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *healthCmd) GetCmd() *cobra.Command { | func (c *healthcheckCmd) GetCmd() *cobra.Command { | ||||||
| 	return c.cmd | 	return c.cmd | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *healthCmd) run(cmd *cobra.Command, args []string) { | func (c *healthcheckCmd) run(cmd *cobra.Command, args []string) { | ||||||
| 	log.Logger = log.Level(zerolog.InfoLevel) | 	log.Logger = log.Level(zerolog.InfoLevel) | ||||||
| 
 | 
 | ||||||
| 	appUrl := "http://127.0.0.1:3000" | 	var appUrl string | ||||||
| 
 | 
 | ||||||
| 	port := c.viper.GetString("PORT") | 	port := c.viper.GetString("PORT") | ||||||
| 	address := c.viper.GetString("ADDRESS") | 	address := c.viper.GetString("ADDRESS") | ||||||
| 
 | 
 | ||||||
| 	if address != "" && port != "" { | 	if port == "" { | ||||||
| 		appUrl = "http://" + address + ":" + port | 		port = "3000" | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if address == "" { | ||||||
|  | 		address = "127.0.0.1" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	appUrl = "http://" + address + ":" + port | ||||||
|  | 
 | ||||||
| 	if len(args) > 0 { | 	if len(args) > 0 { | ||||||
| 		appUrl = args[0] | 		appUrl = args[0] | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	log.Info().Str("appUrl", appUrl).Msg("Performing health check") | ||||||
|  | 
 | ||||||
| 	client := http.Client{} | 	client := http.Client{} | ||||||
| 
 | 
 | ||||||
| 	req, err := http.NewRequest("GET", appUrl+"/api/healthz", nil) | 	req, err := http.NewRequest("GET", appUrl+"/api/healthz", nil) | ||||||
| @@ -140,7 +140,7 @@ func Run() { | |||||||
| 	newVerifyUserCmd(userCmd).Register() | 	newVerifyUserCmd(userCmd).Register() | ||||||
| 	newGenerateTotpCmd(totpCmd).Register() | 	newGenerateTotpCmd(totpCmd).Register() | ||||||
| 	newVersionCmd(root).Register() | 	newVersionCmd(root).Register() | ||||||
| 	newHealthCmd(root).Register() | 	newHealthcheckCmd(root).Register() | ||||||
|  |  | ||||||
| 	root.AddCommand(userCmd) | 	root.AddCommand(userCmd) | ||||||
| 	root.AddCommand(totpCmd) | 	root.AddCommand(totpCmd) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Stavros
					Stavros