Introducing Google Cloud Container Builder
cloudplatform.googleblog.com
cloudplatform.googleblog.com
I recently tried out Cloud Container Builder before it went public. I host a lot of small personal Docker projects on my private GitHub repositories and build Docker images for them using CircleCI and push them to GCR (Google Container Registry). Once you figure out how to do this with $your_favorite_CI_tool, it is easy. However it took me about an hour to build this Circle CI and I had to do some tasks like set up Service Accounts, copy keys around etc.
Google Container Builder eliminates this completely, you just connect your GitHub account, pick what you want to build (every commit, branch or tag) and specify the image name you want to build and forget about it forever.
It runs faster compared to free CI services I've used in the past (probably because image pulls are fast b/c Google Networking, but I'm not sure how much CPU is allocated for builds). Also if you're pushing to GCR, then it'll be faster to push images as well. So overall pull/build/push cycle is just fast. To compare, build for a very simple image I have (base image docker.io/library/python) takes 3m30s on CircleCI vs 1m10s in Google Cloud Container Builder. That's 3x faster.
If the final destination of your Docker image is GCR, it is really fast. You're basically not waiting for your build box to start up. Based on my experience the build starts almost right away after you push to the source control system, whereas CI systems like TravisCI/CircleCI spend quite some time preparing the build env (i.e. container) and running some preliminary commands, collecting artifacts/logs etc. Google Container Builder is looks like it is designed to build containers (not to run tests) and it does that quite fast.
Saw that you didn’t have 2.0 beta access; we’re actually opening that up to everyone this week, so keep an eye on our docs over the next few days. Biggest features you probably care about are the faster speeds/improved caching and native Docker support.
In a GCCB build, we volume-mount in the VM host's docker daemon socket, so you can use the docker CLI, and related CLIs, with no additional setup.
We initially tried a docker-in-docker approach here, but it was a bit too fragile. This attempt was quite some time ago, so it's possible things have improved.
That said, I was easily able to unblock myself because Cloud Container Builder does not actually rely on Dockerfile. You can in fact specify build steps arbitrarily, like Travis CI (or other CI services) by writing a json/yaml file. See https://cloud.google.com/container-builder/docs/api/build-re... and https://cloud.google.com/container-builder/docs/api/build-st.... In that file, you can specify what you want to build and how you want to build it. It is quite flexible.
To keep the UI simple and understandable for everyone, we decided to drop some options and require that you use a config for the more interesting cases.
There are lots of examples of config files (often named `cloudbuild.yaml`) in our github repo: https://github.com/googlecloudplatform/cloud-builders
Much of our container building includes fetching dependencies from various package managers which rarely changes across builds, yet takes up the majority of the build time. Most of the time thats good enough, but for cases where we want to immediately deploy a fix, it can be quite frustrating to having to spend all this time seemingly unncessarily.
Edit: Docker 1.13 has the new --cache-from option so it seems relatively straight-forward to do I guess?
Yarn works the same.
Use different semantics if you must, but please use some existing syntax for your DSL.
I'm so tired of learning a pointless new variety of almost the same thing, only with slightly different syntax, maybe some awkward string quoting, and some rather pointless syntactic sugar.
I'm not saying NixOS is the worst offender, but innovating in (mostly) superficial syntax, or using obscure syntax is almost certainly not well spent time except for a few very narrow niches/contexts. Especially not for prospective users.
I get it, it's fun inventing both languages and tools, I love doing it myself!
However, and in general: Don't invent a language when you need a tool, and vice versa.
It does not excuse Nix to have such a braindamaged^W esoteric syntax.
I don't think the immutability is actually important. Only derivations (which are basically language agnostic) need to be immutable/hashable.
> It does not excuse Nix to have such a braindamaged^W esoteric syntax.
What's so bad about it? The main pain point I've found with it is the lack of documentation for builtin functions. The syntax seems fine to me.
Bazel is a general purpose build system that focuses on reproducibility (same build inputs -> same build outputs) and strict dependency specification (at various levels: file, subsystem, external package fetching etc.) enforced by sandboxing which allows for fast incremental builds. Bazel is the open-source version of Google's internal build-system.
More info here: https://bazel.build/
How external resources are handled: https://bazel.build/versions/master/docs/external.html
Obviously Bazel requires some buy-in which may be unappealing (at least for existing projects: migration/supporting multiple build systems.) There are, however, serious benefits (and a larger, but nascent, ecosystem of related open-source tooling.) The biggest gap at the moment is supported languages/etc.
(I don't work for Google, I just like Bazel.)
It has some major speed benefits. But it's not turnkey. Setting it up is hard. Its dep management in Go isn't compatible with lint, vet, etc. We never got node modules installing with Bazel.
Googling for this issue I found out that if you fail and try you might even be blocked (from the servers) for trying to fetch too many dependencies and the solution was to "try later"...
The Quay build system has implemented caching. The builder preemptively calculates the hashes of Dockerfile commands and then sends them to an API endpoint that finds the tag for the most similar tree of command hashes in a given repository. This tag is pulled before ever attempting to build the Dockerfile.
Google's solution seems far more general than just building Dockerfiles. I'm glad they're pushing for more innovation in this space.
Briefly, you can run any container image as a build step with this service, including one that builds rocket containers, and including one that pushes them. But, we're not currently offering any direct support for this ability.
So, any container image this system builds will run under rkt.
rkt is explicitly designed as a container engine not as a container build system. And this is because build and execute are largely separate concerns. And it leaves the door open for new build systems as demonstrated here by Google.
[1] https://coreos.com/rkt/docs/latest/running-docker-images.htm...
[2] https://github.com/opencontainers/image-spec/issues/126#issu...
In other words, what happens if I build the same source tree twice or if one line changes between one run and the next?
"parallelism": You can indicate any kind of concurrency topology you like with the "wait_for" field on a step: see https://cloud.google.com/container-builder/docs/api/build-st...
"different machines / resources": Currently it's n1-standard-1 GCE VMs. It's possible that in the future we may become more flexible.
We start things like PostgreSQL and Elasticsearch like this because a lot of tests need to exercise the actual data storage instead of (or in addition to) mocking/emulating them. The container builder thus doubles as a CI server, since every build needs to be tested anyway, and tests need to go through very much the same steps (install dependencies, build source and so on). Tests benefit from being run on the exact same filesystem that the final code runs on, guaranteeing that dependencies are identical.
From what I can tell, such a setup is not supported by GCCB?
You say that you value the testing harness having the same set of dependencies as your deployable artifact. With GCCB, you are not limited to one image with your build - it can be any number of them.
So, something like
1. build the deployable as gcr.io/project/service:${REVISION_ID}
2. build the testing harness as gcr.io/project/testing:${REVISION_ID}
3. build the db container as gcr.io/project/db:${REVISION_ID}
Then, you can spin up a test environment using the ${REVISION_ID} tags, and do your integration testing there with the same nice guarantees.That all said, it's certainly possible to do fancier things within the build itself. Using the gcr.io/cloud-builders/docker build step, you can run any docker command. We haven't seen the need to directly support a docker-compose build step, but making it would be easy (different entrypoint on the docker build step) and it would automatically connect to the worker host's daemon.
You can also run several of these docker build steps in parallel, or run one that does 'docker run --name=foo -d ...' and have the others run with '--link foo:foo', etc.
We try not to limit the sorts of things you can do, and provide bonus features like the docker daemon's socket, service account credentials etc.
You don't even need to build a container image, if you don't want to. Just provide some container images and we'll run them for you, pipe the logs back to you, and let you know how it went.
I suppose one could bake that stuff into a base image, or store it in a Kubernetes secret that the build service account has access to.
As you said, you can bake things into a base image (ew) or use your credentials to fetch them from somewhere else (I suggest Cloud Storage).
It's much nicer, and more secure (in terms of locking down just one thing and not having to manage multiple to be able to centralize secrets somewhere. Whereas keeping things like this close the project is of course more convenient for developers.
Drone has tried two different systems, neither of which were ideal, and is working on a third one. I believe the third one also involves encrypted secrets committed to the project repo.
I think of GCCB as a building block on which a fan-out product can be built on. In fact, here is some vaporware: https://github.com/skelterjohn/flargo (a 20% project that is mostly just some ideas right now) (I am skelterjohn).
For example to build a C++ project, run tests, and publish resulting artefacts (binaries, tarballs) in some release repository?
Under the covers, GCCB is an arbitrary execution engine - we run a series of containers for you.
On top of that, we provide a lot of nice dressing to make it convenient and easy to build containers.
https://cloud.google.com/container-builder/docs/api/build-st... and https://cloud.google.com/container-builder/docs/api/custom-b... are documentation on how to use and create your own custom build steps.
Additionally, your build steps have access to the credentials of the service account used to run your build, so pushing to Cloud Storage, for instance, is straightforward (use the gsutil build step).
Is this new product a good place to start that would be relatively pain free for someone new to containers?
Dockerfiles make it challenging to keep your build-time environment separate from the run-time environment. For instance, you need the JDK to build your java app, but only the much smaller JRE to run it. Or maybe you want to use bazel.io for building, and have a completely different base image in mind for your deployment. Or maybe you want to bring in a unit testing harness and not publish the image unless all the tests pass.
Once these issues start to matter, GCCB has a great story. In essence, GCCB runs a series of containers with your source mounted in. So, you can run one step to run unit tests, another to build a binary, and a third to package everything into a container image.
GCCB also will build as many containers as you want in a single execution, so if you have several microservices that are all versioned together, you can build them at the same time and give them a `:${REVISION_ID}` tag - useful for production rollouts.
GCCB will also publish on Cloud Pub/Sub when the build's status changes (including when it goes to "SUCCESS" or "FAILURE"), and you can tell Cloud Pub/Sub to make POST requests with that data, but the format is not flexible so it might not work out for GitHub status updates.
BTW, are there any community or (public) support channel out there? You know a HN thread is not a permanent place.
I searched on SO, but no label of google cloud container builder yet. http://stackoverflow.com/search?q=google+cloud+container+bui...
This most notably includes Cloud Storage (GCR is backed by Cloud Storage). If you use 'gcloud container builds submit' to kick off a build, Cloud Storage is used to get the source in as well.
[0] https://cloud.google.com/appengine/docs/flexible/
[1] https://cloud.google.com/appengine/docs/flexible/python/how-...
We love when Google releases new products - it tends to improve the entire space in general.
Our take is that Google Cloud Container Builder will fit in nicely with the Google ecosystem, but Codeship is trying to solve a different problem by being platform agnostic, and flexible enough to solve the holistic CI/CD workflow.
So if you need to do docker build too often, or maybe your container-release process feels a bit quirky, you might want to do it with the container builder.
It doesn't seem too ground-breaking, people probably already have it automated somehow, or they use sth from Docker hub (https://docs.docker.com/docker-hub/builds/#remote-build-trig...), or quay.
One of the goals is to make it easy to separate the build-time environment from the run-time environment. eg, keep the JDK out of your deployable.
We do this by letting you choose arbitrary container images to run with your source volume-mounted in. We provide some simple ones, like one that runs the 'docker' CLI, and we take care of authenticated docker pushes to GCR.
But, you can use whatever you like as a builder.
I've never built anything with JDK, but is cleanup of build dependencies really a problem in 2017?
For these goodies, you get a nice piece of vendor lock-in.
Additionally, less in your deployable is better from a security standpoint.
re lock-in: We're definitely cognizant of lock-in issues, and were trying to make it as friendly as possible. In the end, our service is running a series of containers with your source mounted in. If you really want out, replicating this process is straightforward.
Tune in at [0] Wednesday-Friday :)
(Work at Google Cloud)
Am I correct in saying that all this does is effectively a:
>docker build >docker push
But builds it all server side, then stores it in Google's Container Registry?
This service runs a series of build steps on your source. It's an arbitrary execution engine with container building dressing on top (UI, CLI, etc).
One of the build steps might do 'docker build'. In fact, most of the build steps that GCCB has executed do just that! But it's not limited. You can provide container images for custom build steps to do whatever you like in a repeatable, automated fashion.
Support is limited, more or less, to what I am really familiar with. If you have other use cases that we could support with other builders, I'd love to see a FR on that GitHub repo.
Also, you can use literally any container image as a build step. Details about how to make that happen are here: https://cloud.google.com/container-builder/docs/api/custom-b...
What I'm missing here is an easy way to link a container being tested with external containers (eg DB).
We like to be the connection between source and registry, with your dev environment being after the registry.
Appreciate the feedback, and feel free to reach out to me directly anytime if you have other questions or thoughts on how we can get better.
Now, core services such as ec2 and S3 are dogfooded for sure, but it is more like amazon doesn't eat their own dogfood until after the product becomes big.
Nice for Hobby projects...
If you do exceed your daily free tier, you're only billed $0.0034/minute, on a per-second basis, so we expect the cost of using this product to be very low.
(disclaimer: I work on this product)
If your builds become much more complicated, and you have an team of developers working with CI, yes, you will exceed the 120m limit. But if you are running at that scale, a couple of dollars per day for the build process is the least of your running costs.