diff --git a/.ko.yaml b/.ko.yaml new file mode 100644 index 0000000000..6ccd2d5eb9 --- /dev/null +++ b/.ko.yaml @@ -0,0 +1 @@ +defaultBaseImage: gcr.io/distroless/static:nonroot diff --git a/README.md b/README.md index 750d2984f1..f4f1492cf5 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,8 @@ paths like `github.com/google/ko/cmd`. **One of the goals of `ko` is to make containers invisible infrastructure.** Simply replace image references in your Kubernetes yaml with the import path for -your Go binary, and `ko` will handle containerizing and publishing that -container image as needed. +your Go binary prefixed with `ko://` (e.g. `ko://github.com/google/ko/cmd/ko`), +and `ko` will handle containerizing and publishing that container image as needed. For example, you might use the following in a Kubernetes `Deployment` resource: @@ -58,26 +58,19 @@ spec: containers: - name: hello-world # This is the import path for the Go binary to build and run. - image: github.com/mattmoor/examples/http/cmd/helloworld + image: ko://github.com/mattmoor/examples/http/cmd/helloworld ports: - containerPort: 8080 ``` -### Determining supported import paths +### What gets built? -Similar to other tooling in the Go ecosystem, `ko` expects to execute in the -context of your `$GOPATH`. This is used to determine what package(s) `ko` -is expected to build. +`ko` will attempt to containerize and build any string within the yaml prefixed +with `ko://`. -Suppose `GOPATH` is `~/gopath` and the current directory is -`~/gopath/src/github.com/mattmoor/examples`. `ko` will deduce the base import -path to be `github.com/mattmoor/examples`, and any references to subpackages -of this will be built, containerized and published. +The legacy behavior of detecting import paths is deprecated and will be removed +in a coming release. -For example, any of the following would be matched: -* `github.com/mattmoor/examples` -* `github.com/mattmoor/examples/cmd/foo` -* `github.com/mattmoor/examples/bar` ### Results @@ -89,14 +82,14 @@ seconds (dominated by two `go build`s). ```shell $ ko apply -f config/ -2018/07/19 14:56:41 Using base gcr.io/distroless/base:latest for github.com/mattmoor/warm-image/cmd/sleeper +2018/07/19 14:56:41 Using base gcr.io/distroless/static:latest for github.com/mattmoor/warm-image/cmd/sleeper 2018/07/19 14:56:42 Publishing us.gcr.io/my-project/sleeper-ebdb8b8b13d4bbe1d3592de055016d37:latest 2018/07/19 14:56:43 mounted blob: sha256:57752e7f9593cbfb7101af994b136a369ecc8174332866622db32a264f3fbefd 2018/07/19 14:56:43 mounted blob: sha256:59df9d5b488aea2753ab7774ae41a9a3e96903f87ac699f3505960e744f36f7d 2018/07/19 14:56:43 mounted blob: sha256:739b3deec2edb17c512f507894c55c2681f9724191d820cdc01f668330724ca7 2018/07/19 14:56:44 us.gcr.io/my-project/sleeper-ebdb8b8b13d4bbe1d3592de055016d37:latest: digest: sha256:6c7b96a294cad3ce613aac23c8aca5f9dd12a894354ab276c157fb5c1c2e3326 size: 592 2018/07/19 14:56:44 Published us.gcr.io/my-project/sleeper-ebdb8b8b13d4bbe1d3592de055016d37@sha256:6c7b96a294cad3ce613aac23c8aca5f9dd12a894354ab276c157fb5c1c2e3326 -2018/07/19 14:56:45 Using base gcr.io/distroless/base:latest for github.com/mattmoor/warm-image/cmd/controller +2018/07/19 14:56:45 Using base gcr.io/distroless/static:latest for github.com/mattmoor/warm-image/cmd/controller 2018/07/19 14:56:46 Publishing us.gcr.io/my-project/controller-9e91872fd7c48124dbe6ea83944b87e9:latest 2018/07/19 14:56:46 mounted blob: sha256:007782ba6738188a59bf21b4d8e974f218615ee948c6357535d07e7248b2a560 2018/07/19 14:56:46 mounted blob: sha256:57752e7f9593cbfb7101af994b136a369ecc8174332866622db32a264f3fbefd @@ -131,7 +124,7 @@ an argument. It prints the images' published digests after each image is publish ```shell $ ko publish github.com/mattmoor/warm-image/cmd/sleeper -2018/07/19 14:57:34 Using base gcr.io/distroless/base:latest for github.com/mattmoor/warm-image/cmd/sleeper +2018/07/19 14:57:34 Using base gcr.io/distroless/static:latest for github.com/mattmoor/warm-image/cmd/sleeper 2018/07/19 14:57:35 Publishing us.gcr.io/my-project/sleeper-ebdb8b8b13d4bbe1d3592de055016d37:latest 2018/07/19 14:57:35 mounted blob: sha256:739b3deec2edb17c512f507894c55c2681f9724191d820cdc01f668330724ca7 2018/07/19 14:57:35 mounted blob: sha256:57752e7f9593cbfb7101af994b136a369ecc8174332866622db32a264f3fbefd @@ -144,7 +137,7 @@ $ ko publish github.com/mattmoor/warm-image/cmd/sleeper ```shell $ ko publish ./cmd/sleeper -2018/07/19 14:58:16 Using base gcr.io/distroless/base:latest for github.com/mattmoor/warm-image/cmd/sleeper +2018/07/19 14:58:16 Using base gcr.io/distroless/static:latest for github.com/mattmoor/warm-image/cmd/sleeper 2018/07/19 14:58:16 Publishing us.gcr.io/my-project/sleeper-ebdb8b8b13d4bbe1d3592de055016d37:latest 2018/07/19 14:58:17 mounted blob: sha256:59df9d5b488aea2753ab7774ae41a9a3e96903f87ac699f3505960e744f36f7d 2018/07/19 14:58:17 mounted blob: sha256:739b3deec2edb17c512f507894c55c2681f9724191d820cdc01f668330724ca7 @@ -218,9 +211,9 @@ spec: It is notable that this is not the default (anymore) because certain popular registries (including Docker Hub) do not support multi-level repository names. -`ko resolve`, `ko apply`, and `ko create` accept an optional `--selector` or `-l` -flag, similar to `kubectl`, which can be used to filter the resources from the -input Kubernetes YAMLs by their `metadata.labels`. +`ko resolve`, `ko apply`, and `ko create` accept an optional `--selector` or `-l` +flag, similar to `kubectl`, which can be used to filter the resources from the +input Kubernetes YAMLs by their `metadata.labels`. In the case of `ko resolve`, `--selector` will render only the resources that are selected by the provided selector. @@ -323,7 +316,10 @@ If neither is present, then `ko` will rely on its default behaviors. ### Overriding the default base image -By default, `ko` makes use of `gcr.io/distroless/base:latest` as the base image +> Notice: the use of `:latest` will be deprecated in favor of `:nonroot` in a +> coming release. See https://github.com/google/ko/issues/160 for more info. + +By default, `ko` makes use of `gcr.io/distroless/static:latest` as the base image for containers. There are a wide array of scenarios in which overriding this makes sense, for example: 1. Pinning to a particular digest of this image for repeatable builds, @@ -383,7 +379,7 @@ This produces identical output to being run within the container locally: ```shell ko publish -L ./cmd/test -2018/07/19 23:36:11 Using base gcr.io/distroless/base:latest for github.com/google/ko/cmd/test +2018/07/19 23:36:11 Using base gcr.io/distroless/static:latest for github.com/google/ko/cmd/test 2018/07/19 23:36:12 Loading ko.local/github.com/google/ko/cmd/test:703c205bf2f405af520b40536b87aafadcf181562b8faa6690fd2992084c8577 2018/07/19 23:36:13 Loaded ko.local/github.com/google/ko/cmd/test:703c205bf2f405af520b40536b87aafadcf181562b8faa6690fd2992084c8577 @@ -395,7 +391,7 @@ docker run -ti --rm ko.local/github.com/google/ko/cmd/test:703c205bf2f405af520b4 ```shell ko apply -f cmd/ko/test/test.yaml -2018/07/19 23:38:24 Using base gcr.io/distroless/base:latest for github.com/google/ko/cmd/test +2018/07/19 23:38:24 Using base gcr.io/distroless/static:latest for github.com/google/ko/cmd/test 2018/07/19 23:38:25 Publishing us.gcr.io/my-project/test-294a7bdc57d85dc6ddeef5ba38a59fe9:latest 2018/07/19 23:38:26 mounted blob: sha256:988abcba36b5948da8baa1e3616b94c0b56da814b8f6ff3ae3ac316e375e093a 2018/07/19 23:38:26 mounted blob: sha256:57752e7f9593cbfb7101af994b136a369ecc8174332866622db32a264f3fbefd @@ -419,7 +415,7 @@ ko completion To use the completion script, you can copy the script in your bash_completion directory (e.g. /usr/local/etc/bash_completion.d/): ``` ko completion > /usr/local/etc/bash_completion.d/ko -``` +``` or source it in your shell by running: ``` source <(ko completion) diff --git a/cmd/ko/test/test.yaml b/cmd/ko/test/test.yaml index 2ce60f6b94..462345446d 100644 --- a/cmd/ko/test/test.yaml +++ b/cmd/ko/test/test.yaml @@ -15,10 +15,8 @@ apiVersion: v1 kind: Pod metadata: name: kodata - annotations: - sidecar.istio.io/inject: "false" spec: containers: - name: obiwan - image: github.com/google/ko/cmd/ko/test + image: ko://github.com/google/ko/cmd/ko/test restartPolicy: Never diff --git a/pkg/build/gobuild.go b/pkg/build/gobuild.go index 231e4ee5e5..04c128e625 100644 --- a/pkg/build/gobuild.go +++ b/pkg/build/gobuild.go @@ -165,6 +165,20 @@ func NewGo(options ...Option) (Interface, error) { return gbo.Open() } +const Deprecation158 = `NOTICE! +----------------------------------------------------------------- +We will start requiring ko:// in a coming release. Please prefix +the following import path for things to continue working: + + %s + +For more information see: + + https://github.com/google/ko/issues/158 + +----------------------------------------------------------------- +` + // IsSupportedReference implements build.Interface // // Only valid importpaths that provide commands (i.e., are "package main") are @@ -177,6 +191,9 @@ func (g *gobuild) IsSupportedReference(s string) bool { } return false } else if p.IsCommand() { + if !ref.IsStrict() { + log.Printf(Deprecation158, s) + } return true } else if ref.IsStrict() { log.Fatalf(`%q does not have "package main"`, ref.String()) diff --git a/pkg/commands/config.go b/pkg/commands/config.go index b5f34cc15e..5fe409b232 100644 --- a/pkg/commands/config.go +++ b/pkg/commands/config.go @@ -80,9 +80,19 @@ func createCancellableContext() context.Context { return ctx } +const Deprecation160 = `NOTICE! +----------------------------------------------------------------- +We are changing the default base image in a subsequent release. + +For more information (including how to suppress this message): + + https://github.com/google/ko/issues/160 + +----------------------------------------------------------------- +` + func init() { // If omitted, use this base image. - viper.SetDefault("defaultBaseImage", "gcr.io/distroless/static:latest") viper.SetConfigName(".ko") // .yaml is implicit viper.SetEnvPrefix("KO") viper.AutomaticEnv() @@ -99,6 +109,11 @@ func init() { } } + if !viper.IsSet("defaultBaseImage") { + viper.Set("defaultBaseImage", "gcr.io/distroless/static:latest") + log.Print(Deprecation160) + } + ref := viper.GetString("defaultBaseImage") dbi, err := name.ParseReference(ref) if err != nil { diff --git a/pkg/commands/publisher.go b/pkg/commands/publisher.go index 3326baa9c9..9b611d9290 100644 --- a/pkg/commands/publisher.go +++ b/pkg/commands/publisher.go @@ -18,6 +18,7 @@ import ( "context" "fmt" gb "go/build" + "strings" "github.com/google/go-containerregistry/pkg/name" "github.com/google/ko/pkg/build" @@ -50,6 +51,9 @@ func publishImages(ctx context.Context, importpaths []string, pub publish.Interf return nil, err } } + if !strings.HasPrefix(importpath, build.StrictScheme) { + importpath = build.StrictScheme + importpath + } if !b.IsSupportedReference(importpath) { return nil, fmt.Errorf("importpath %q is not supported", importpath)