hello world render app
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

docker workflow

Signed-off-by: softprops <d.tangren@gmail.com>

+143
+60
.tangled/workflows/deploy.yml
··· 1 + # ATCR AppView Release 2 + # Builds multi-arch (amd64 + arm64) container image and publishes a manifest list. 3 + 4 + when: 5 + - event: ["push"] 6 + brach: ["main"] 7 + 8 + engine: kubernetes 9 + image: quay.io/buildah/stable:latest 10 + architecture: [amd64, arm64] 11 + 12 + environment: 13 + IMAGE_REGISTRY: atcr.io 14 + IMAGE_USER: softprops.bsky.social 15 + IMAGE_NAME: hello-render 16 + DOCKERFILE: ./Dockerfile 17 + 18 + steps: 19 + - name: Build image archive 20 + command: | 21 + set -e 22 + mkdir -p /artifacts 23 + buildah bud \ 24 + --tag "${IMAGE_NAME}:${TANGLED_ARCHITECTURE}" \ 25 + --file "${DOCKERFILE}" \ 26 + . 27 + buildah push \ 28 + "${IMAGE_NAME}:${TANGLED_ARCHITECTURE}" \ 29 + "oci-archive:/artifacts/${IMAGE_NAME}.tar" 30 + 31 + final: 32 + architecture: amd64 33 + image: quay.io/buildah/stable:latest 34 + steps: 35 + - name: Login to registry 36 + command: | 37 + echo "${APP_PASSWORD}" | buildah login \ 38 + -u "${IMAGE_USER}" \ 39 + --password-stdin \ 40 + "${IMAGE_REGISTRY}" 41 + 42 + - name: Create and push multi-arch manifest 43 + command: | 44 + set -e 45 + FULL="${IMAGE_REGISTRY}/${IMAGE_USER}/${IMAGE_NAME}" 46 + 47 + buildah pull "oci-archive:/artifacts/amd64/${IMAGE_NAME}.tar" 48 + buildah pull "oci-archive:/artifacts/arm64/${IMAGE_NAME}.tar" 49 + 50 + buildah manifest create "${FULL}:${TANGLED_REF_NAME}" 51 + buildah manifest add "${FULL}:${TANGLED_REF_NAME}" "${IMAGE_NAME}:amd64" 52 + buildah manifest add "${FULL}:${TANGLED_REF_NAME}" "${IMAGE_NAME}:arm64" 53 + 54 + buildah manifest push --all \ 55 + "${FULL}:${TANGLED_REF_NAME}" \ 56 + "docker://${FULL}:${TANGLED_REF_NAME}" 57 + 58 + buildah manifest push --all \ 59 + "${FULL}:${TANGLED_REF_NAME}" \ 60 + "docker://${FULL}:latest"
+22
Dockerfile
··· 1 + # https://render.com/docs/deploying-an-image#image-requirements 2 + FROM docker.io/golang:1.26.2-trixie AS builder 3 + ENV DEBIAN_FRONTEND=noninteractive 4 + RUN apt-get update && rm -rf /var/lib/apt/lists/* 5 + WORKDIR /app 6 + 7 + COPY go.mod ./ 8 + RUN go mod download 9 + 10 + COPY . . 11 + RUN CGO_ENABLED=0 go build \ 12 + -ldflags="-s -w" \ 13 + -o app . 14 + 15 + FROM scratch 16 + 17 + COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ 18 + COPY --from=builder /app/app /app 19 + 20 + EXPOSE 3000 21 + 22 + ENTRYPOINT ["/app"]
+2
README.md
··· 1 1 # hello render 2 + 3 + demo of deploying a go app [using render](https://render.com/docs/deploying-an-image)
+3
go.mod
··· 1 + module softprops.tngl.sh/hello-render 2 + 3 + go 1.26.2
+56
main.go
··· 1 + package main 2 + 3 + import ( 4 + "context" 5 + "errors" 6 + "fmt" 7 + "log/slog" 8 + "net" 9 + "net/http" 10 + "os" 11 + "os/signal" 12 + "syscall" 13 + "time" 14 + ) 15 + 16 + func main() { 17 + l := slog.New(slog.NewJSONHandler(os.Stdout, nil)) 18 + if err := run(l); err != nil { 19 + l.Error("failed to start application", slog.Any("err", err)) 20 + os.Exit(1) 21 + } 22 + } 23 + 24 + func run(l *slog.Logger) error { 25 + lis, err := net.Listen("tcp", ":3000") 26 + if err != nil { 27 + return err 28 + } 29 + server := http.Server{ 30 + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 31 + fmt.Fprintf(w, "hello %s %s", r.Method, r.URL) 32 + }), 33 + } 34 + 35 + go func() { 36 + if err := server.Serve(lis); !errors.Is(err, http.ErrServerClosed) { 37 + l.Error("Failed to start server", slog.Any("err", err)) 38 + os.Exit(1) 39 + } 40 + }() 41 + l.Info("server listening", slog.String("addr", lis.Addr().String())) 42 + 43 + // wait for term signal then gracefully shutdown the server 44 + term := make(chan os.Signal, 1) 45 + signal.Notify(term, syscall.SIGINT, syscall.SIGTERM) 46 + <-term 47 + 48 + shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 49 + defer cancel() 50 + 51 + if err := server.Shutdown(shutdownCtx); err != nil { 52 + l.Error("failed to shutdown server", slog.Any("err", err)) 53 + } 54 + 55 + return nil 56 + }