diff --git a/docs/serving/samples/hello-world/helloworld-go/Dockerfile b/docs/serving/samples/hello-world/helloworld-go/Dockerfile index 3adce8bf9..e141bf2cc 100644 --- a/docs/serving/samples/hello-world/helloworld-go/Dockerfile +++ b/docs/serving/samples/hello-world/helloworld-go/Dockerfile @@ -6,8 +6,8 @@ FROM golang:1.13 as builder # Create and change to the app directory. WORKDIR /app -# Retrieve application dependencies. -# This allows the container build to reuse cached dependencies. +# Retrieve application dependencies using go modules. +# Allows container builds to reuse downloaded dependencies. COPY go.* ./ RUN go mod download @@ -15,6 +15,7 @@ RUN go mod download COPY . ./ # Build the binary. +# -mod=readonly ensures immutable go.mod and go.sum in container builds. RUN CGO_ENABLED=0 GOOS=linux go build -mod=readonly -v -o server # Use the official Alpine image for a lean production container. diff --git a/docs/serving/samples/hello-world/helloworld-go/README.md b/docs/serving/samples/hello-world/helloworld-go/README.md index e2567a06b..cfa661708 100644 --- a/docs/serving/samples/hello-world/helloworld-go/README.md +++ b/docs/serving/samples/hello-world/helloworld-go/README.md @@ -42,7 +42,7 @@ cd knative-docs/docs/serving/samples/hello-world/helloworld-go ) func handler(w http.ResponseWriter, r *http.Request) { - log.Print("Hello world received a request.") + log.Print("helloworld: received a request") target := os.Getenv("TARGET") if target == "" { target = "World" @@ -51,7 +51,7 @@ cd knative-docs/docs/serving/samples/hello-world/helloworld-go } func main() { - log.Print("Hello world sample started.") + log.Print("helloworld: starting server...") http.HandleFunc("/", handler) @@ -60,6 +60,7 @@ cd knative-docs/docs/serving/samples/hello-world/helloworld-go port = "8080" } + log.Printf("helloworld: listening on port %s", port) log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil)) } ``` @@ -77,8 +78,8 @@ cd knative-docs/docs/serving/samples/hello-world/helloworld-go # Create and change to the app directory. WORKDIR /app - # Retrieve application dependencies. - # This allows the container build to reuse cached dependencies. + # Retrieve application dependencies using go modules. + # Allows container builds to reuse downloaded dependencies. COPY go.* ./ RUN go mod download @@ -86,6 +87,7 @@ cd knative-docs/docs/serving/samples/hello-world/helloworld-go COPY . ./ # Build the binary. + # -mod=readonly ensures immutable go.mod and go.sum in container builds. RUN CGO_ENABLED=0 GOOS=linux go build -mod=readonly -v -o server # Use the official Alpine image for a lean production container. diff --git a/docs/serving/samples/hello-world/helloworld-go/helloworld.go b/docs/serving/samples/hello-world/helloworld-go/helloworld.go index 720b1ec5e..0b97c3bdd 100644 --- a/docs/serving/samples/hello-world/helloworld-go/helloworld.go +++ b/docs/serving/samples/hello-world/helloworld-go/helloworld.go @@ -8,7 +8,7 @@ import ( ) func handler(w http.ResponseWriter, r *http.Request) { - log.Print("Hello world received a request.") + log.Print("helloworld: received a request") target := os.Getenv("TARGET") if target == "" { target = "World" @@ -17,7 +17,7 @@ func handler(w http.ResponseWriter, r *http.Request) { } func main() { - log.Print("Hello world sample started.") + log.Print("helloworld: starting server...") http.HandleFunc("/", handler) @@ -26,5 +26,6 @@ func main() { port = "8080" } + log.Printf("helloworld: listening on port %s", port) log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil)) } diff --git a/docs/serving/samples/hello-world/helloworld-shell/Dockerfile b/docs/serving/samples/hello-world/helloworld-shell/Dockerfile index 902d8c3ab..0220a75cb 100644 --- a/docs/serving/samples/hello-world/helloworld-shell/Dockerfile +++ b/docs/serving/samples/hello-world/helloworld-shell/Dockerfile @@ -1,26 +1,32 @@ -# Use the offical Golang image to create a build artifact. +# Use the official Golang image to create a build artifact. # This is based on Debian and sets the GOPATH to /go. # https://hub.docker.com/_/golang -FROM golang:1.12 as builder +FROM golang:1.13 as builder + +# Create and change to the app directory. +WORKDIR /app + +# Retrieve application dependencies using go modules. +# Allows container builds to reuse downloaded dependencies. +COPY go.* ./ +RUN go mod download # Copy local code to the container image. -WORKDIR /go/src/github.com/knative/docs/helloworld-shell -COPY invoke.go . +COPY invoke.go ./ -# Build the command inside the container. -# (You may fetch or manage dependencies here, -# either manually or with a tool like "godep".) -RUN CGO_ENABLED=0 GOOS=linux go build -v -o invoke +# Build the binary. +# -mod=readonly ensures immutable go.mod and go.sum in container builds. +RUN CGO_ENABLED=0 GOOS=linux go build -mod=readonly -v -o server -# The official Alpine base image +# Use the official Alpine image for a lean production container. # https://hub.docker.com/_/alpine -# Use a Docker multi-stage build to create a lean production image. # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds -FROM alpine:3.10 +FROM alpine:3 +RUN apk add --no-cache ca-certificates -# Copy Go binary -COPY --from=builder /go/src/github.com/knative/docs/helloworld-shell/invoke /invoke -COPY script.sh . +# Copy the binary to the production image from the builder stage. +COPY --from=builder /app/server /server +COPY script.sh ./ # Run the web service on container startup. -CMD ["/invoke"] +CMD ["/server"] diff --git a/docs/serving/samples/hello-world/helloworld-shell/README.md b/docs/serving/samples/hello-world/helloworld-shell/README.md index 0cb6ba22b..28f6383b4 100644 --- a/docs/serving/samples/hello-world/helloworld-shell/README.md +++ b/docs/serving/samples/hello-world/helloworld-shell/README.md @@ -42,64 +42,75 @@ cd knative-docs/docs/serving/samples/hello-world/helloworld-shell package main import ( - "fmt" - "log" - "net/http" - "os" - "os/exec" + "fmt" + "log" + "net/http" + "os" + "os/exec" ) func handler(w http.ResponseWriter, r *http.Request) { - cmd := exec.CommandContext(r.Context(), "/bin/sh", "script.sh") - cmd.Stderr = os.Stderr - out, err := cmd.Output() - if err != nil { - w.WriteHeader(500) - } - w.Write(out) + log.Print("helloworld: received a request") + + cmd := exec.CommandContext(r.Context(), "/bin/sh", "script.sh") + cmd.Stderr = os.Stderr + out, err := cmd.Output() + if err != nil { + w.WriteHeader(500) + } + w.Write(out) } func main() { - http.HandleFunc("/", handler) + log.Print("helloworld: starting server...") - port := os.Getenv("PORT") - if port == "" { - port = "8080" - } + http.HandleFunc("/", handler) - log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil)) + port := os.Getenv("PORT") + if port == "" { + port = "8080" + } + + log.Printf("helloworld: listening on %s", port) + log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil)) } ``` 1. Create a new file named `Dockerfile` and copy the code block below into it. ```docker - # Use the offical Golang image to create a build artifact. + # Use the official Golang image to create a build artifact. # This is based on Debian and sets the GOPATH to /go. # https://hub.docker.com/_/golang - FROM golang:1.12 as builder + FROM golang:1.13 as builder + + # Create and change to the app directory. + WORKDIR /app + + # Retrieve application dependencies using go modules. + # Allows container builds to reuse downloaded dependencies. + COPY go.* ./ + RUN go mod download # Copy local code to the container image. - WORKDIR /go/src/github.com/knative/docs/helloworld-shell - COPY invoke.go . + COPY invoke.go ./ - # Build the command inside the container. - # (You may fetch or manage dependencies here, - # either manually or with a tool like "godep".) - RUN CGO_ENABLED=0 GOOS=linux go build -v -o invoke + # Build the binary. + # -mod=readonly ensures immutable go.mod and go.sum in container builds. + RUN CGO_ENABLED=0 GOOS=linux go build -mod=readonly -v -o server - # The official Alpine base image + # Use the official Alpine image for a lean production container. # https://hub.docker.com/_/alpine - # Use a Docker multi-stage build to create a lean production image. # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds - FROM alpine:3.10 + FROM alpine:3 + RUN apk add --no-cache ca-certificates - # Copy Go binary - COPY --from=builder /go/src/github.com/knative/docs/helloworld-shell/invoke /invoke - COPY script.sh . + # Copy the binary to the production image from the builder stage. + COPY --from=builder /app/server /server + COPY script.sh ./ # Run the web service on container startup. - CMD ["/invoke"] + CMD ["/server"] ``` 1. Create a new file, `service.yaml` and copy the following service definition @@ -122,6 +133,13 @@ cd knative-docs/docs/serving/samples/hello-world/helloworld-shell value: "Shell Sample v1" ``` +1. Use the go tool to create a + [`go.mod`](https://github.com/golang/go/wiki/Modules#gomod) manifest. + + ```shell + go mod init github.com/knative/docs/docs/serving/samples/hello-world/helloworld-shell + ``` + ## Building and deploying the sample Once you have recreated the sample code files (or used the files in the sample diff --git a/docs/serving/samples/hello-world/helloworld-shell/go.mod b/docs/serving/samples/hello-world/helloworld-shell/go.mod new file mode 100644 index 000000000..6245e6cf6 --- /dev/null +++ b/docs/serving/samples/hello-world/helloworld-shell/go.mod @@ -0,0 +1,3 @@ +module github.com/knative/docs/docs/serving/samples/hello-world/helloworld-shell + +go 1.13 diff --git a/docs/serving/samples/hello-world/helloworld-shell/invoke.go b/docs/serving/samples/hello-world/helloworld-shell/invoke.go index 352bf2dd5..f4ba32ddb 100644 --- a/docs/serving/samples/hello-world/helloworld-shell/invoke.go +++ b/docs/serving/samples/hello-world/helloworld-shell/invoke.go @@ -9,6 +9,8 @@ import ( ) func handler(w http.ResponseWriter, r *http.Request) { + log.Print("helloworld: received a request") + cmd := exec.CommandContext(r.Context(), "/bin/sh", "script.sh") cmd.Stderr = os.Stderr out, err := cmd.Output() @@ -19,6 +21,8 @@ func handler(w http.ResponseWriter, r *http.Request) { } func main() { + log.Print("helloworld: starting server...") + http.HandleFunc("/", handler) port := os.Getenv("PORT") @@ -26,5 +30,6 @@ func main() { port = "8080" } + log.Printf("helloworld: listening on %s", port) log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil)) } diff --git a/test/sampleapp/config.yaml b/test/sampleapp/config.yaml index 1bd311cdf..188a4660b 100644 --- a/test/sampleapp/config.yaml +++ b/test/sampleapp/config.yaml @@ -58,6 +58,9 @@ languages: - "Dockerfile" - language: "shell" expectedOutput: "Hello Shell Sample v1!" + preCommands: + - exec: "cp" + args: "../../docs/serving/samples/hello-world/helloworld-shell/go.mod helloworld-shell_tmp/go.mod" copies: - "script.sh" - "invoke.go"