top | item 38185241

Ko: Easy Go Containers

113 points| bamazizi | 2 years ago |ko.build

40 comments

order

ImJasonH|2 years ago

Hey, ko maintainer here! I'd love to answer any questions or hear any feedback folks have.

Ko's simplicity comes from focusing on doing exactly one thing well -- it doesn't have to run containers to build code in any language, it just builds minimal Go containers, and that means it can focus on doing that as well as possible.

Another powerful benefit of focusing on Go (IMO) is that ko can be used to transform a Go importpath to a built image reference.

A common simple use: `docker run $(ko build ./cmd/app)`

This is also how Kubernetes YAML templating[1] works, and it's also how the Terraform provider[2] works -- you give it an importpath, and ko transforms it into a built image reference you can pass to the rest of your config. I don't even "use ko" day-to-day most days, I mostly just use terraform. :)

1: https://ko.build/features/k8s/ 2: https://ko.build/advanced/terraform/

anuraaga|2 years ago

Ko works ok but lacks a lot of configurability, compared to something like jib, that does end up important. There are a few open issues on it but the commit history is basically dependabot, not much action for UX. Better than nothing I guess but it really does give off the feeling of a project spun off from Google to let it die.

Despite that it's probably still the best tool for building containers in Go, but it's not pleasant.

flimsypremise|2 years ago

I'll be honest, I just don't think this is a great way to do development in any language:

`ko builds images by executing go build on your local machine`

If you've done any sort of work with service or application development on a team, you will no doubt have encountered issues with relying on local machine build dependencies. Enforcing dependency versions across the team is basically impossible even in cases where the entire team is using the same OS and hardware, so you're going to run into problems where users are building the codebase with different versions of tools and dependencies. This is one of the core problems that containerization was intended to solve, so if you are using containerization in development and not building inside the container, you are missing out on one of the major advantages of the paradigm.

arp242|2 years ago

Unlike languages that take a lot of stuff from /usr/lib/ system directories, this is not a huge problem in Go, as it doesn't do that. I'm not saying it's never a problem; but it's fairly rare

ImJasonH|2 years ago

I do agree with you in general. However, while containers were being invented to solve this problem, Go was also solving this problem.

For the most part, for the most common simple Go applications, if you build the same code with the same version of Go installed, you'll get the same dependencies and the same artifact.

Building Go applications in containers is not necessary in general, and doing so makes it much more complicated to share a build cache. You can of course do it with enough additions to your Dockerfile, but why bother?

If your developer team and CI environment are all using a similar recent Go, they shouldn't have different behavior using ko together.

hknmtt|2 years ago

I have used something like this in the past:

FROM alpine:latest AS base # Scratch does not have shell so we have to create non-root user in here and later copy it into scratch. RUN adduser -D -u 123456 appusr

FROM scratch # Copy the binary. COPY foo.bin /foo.bin # Copy the user and set is as active. COPY --from=base /etc/passwd /etc/passwd USER appusr # Non-root user cannot bind to "privileged" ports(<=1024). EXPOSE 1234 ENTRYPOINT ["/foo.bin"]

Simple. But i can see ko being good alternative if you for some reason do not want to install docker on your computer but still be able to build docker containers.

015a|2 years ago

Or, if you don't want to install it in your CI/CD. Which could be extremely valuable; some CI/CD providers make "building a docker image" a weirdly hard (and sometimes, even much more expensive) step due to docker-in-docker madness.

chickenbane|2 years ago

> But i can see ko being good alternative if you for some reason do not want to install docker on your computer but still be able to build docker containers.

Docker is a much bigger dependency than ko, involving a daemon and a socket you have to manage and secure. ko is a only a go program, and builds are straight-forward and lightning fast compared to Docker.

Importantly, ko also removes the need for a Dockerfile. Yes, as you point out a Dockerfile can be simple, but but the best part is no part. Dockerfile has plenty of foot guns and best practices to learn so if at the end of the day all you need is a go binary on a container ko will serve you much, much better.

ImJasonH|2 years ago

That works, but it also means maintaining a Dockerfile that does the COPYs, when all you're really doing is assembling image layers. This is more or less exactly what ko does, without using the Dockerfile language to describe it.

Not having to run a Docker daemon is just a nice bonus! :)

jadbox|2 years ago

I thought that go doesn't work in Alpine because of shared libs?

traceroute66|2 years ago

> i can see ko being good alternative if you for some reason do not want to install docker on your computer

The already established good alternative to Docker desktop is Rancher Desktop[1].

[1] https://rancherdesktop.io/

riv991|2 years ago

I love ko, so simple to get a container running in one line and now integrated with GoReleaser.

`docker run $(ko build -L main.go)`

ithkuil|2 years ago

I love `ko`. I wish there was something similar for rust but I haven't found it quite yet

bambambazooka|2 years ago

I have a very opinionated library that builds Docker images in pure Rust.

I don't think building something like `ko` with it should be that much work. (I know, famous last words)

I'll have to check with $employer if it's ok to open source it.

ImJasonH|2 years ago

I'd love to build a ko-for-Rust. I'd just need to learn Rust a bit more. :)

pachico|2 years ago

Dammit, why didn't I know about this? In general, I always have the feeling I'm not aware of great applications out there, and I confirm this sensation every time I find them, like now!

How do you all stay tune of the great apps out there?

seanw444|2 years ago

I track GitHub's trending page for Go, Rust, and occasionally Python projects. Limiting to these languages tends to yield the kinds of projects I'm interested in, just by the nature of the demographic that uses them. Sometimes I browse recent repo activity on Sourcehut too.

avtolik|2 years ago

I am building an app right now and looked into this. Unfortunately the support for including static assets is limited for my case.

ImJasonH|2 years ago

What's your use case? Static assets are fairly limited today, but even within those limitations we've been able to get pretty far with symlinks.

If that's not enough or not desirable I completely understand, there's probably something we could do to improve it.

https://ko.build/features/static-assets/

arccy|2 years ago

depending on what sort of support you need, you can also consider embedding the static assets into the go binary