Disclaimer: I work at Google but I do not work on the product, so this is my personal experience.
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.
Good question, I actually hit this problem. In one of my projects, I build 3 microservices out of a single GitHub repository. So I had 3 different Dockerfiles. What didn't work out for me was that Cloud Container Builder does not let you specify the Dockerfile name (but it lets you specify the Dockerfile directory, so if your dockerfiles are in separate dirs, you're good; however it's not very helpful if you need to host all your dockerfiles in the repo root.). If you think providing a custom Dockerfile name would be a useful feature, please let the folks know here. I am sure they would be interested in your feedback.
We've tried to satisfy the 90% case with the UI and "easy" options, especially those that transfer well from other push-to-build products.
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.
What size is the project? Trying to guesstimate if it's worth investigating using 3rd party vs. [google] cloud container builder - speed tradeoffs, convenience, friction etc. Cheers.
I am simply building a Python container with about ~15 dependencies installed via pip and some ~50 MB of static assets added to the container. The base image comes from Docker Hub (hosted on S3/AWS CF).
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.
I tried setting up Docker deploys to K8S today on CircleCi v2 beta. I had a horribly difficult time getting it to work because running docker in the docker runtime is nearly impossible to do in a way that is compatible with Bazel.io. I ended up having to use the VM mode and it just felt like Circle v1.
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.
I'm so surprised that both Docker's as well as Google's solution to this problem involves 0 caching.
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?
Full Disclosure: I work on the Quay team at CoreOS
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.
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.
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.
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.
I tried to compile tensorflow recently, it uses Bazel as the build system.
When compiling it downloads external dependencies to be used during the build.
It failed to retrieve some dependencies and I had to restart the proceeds only to fail on other dependencies and it seem to download all of them again (even though it was successful in downloading the other dependencies).
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"...
One approach to this problem that I like is storing these dependencies in an intermediate image. Then, you can do an incremental build by referencing (rather than rebuilding) this intermediate image, and pay only the cost of downloading the raw data which should be cheap compared to the normal install process.
I think the idea here is that the docker level caching isn't well suited for this. Eg for us we install all relevant gems with `bundle install`. If you update one gem, that the whole layer is rebuilt. Since the whole `bundle install` layer is rebuilt, every gem is fetched again from rubygems.
I like what I understand to be the core ideas of NixOS to be, but i have to say:
There might be a chance that some century, people both in the industry and outside understand that new syntax, or languages, are rarely necessary, or even beneficial.
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.
The alternative is co-opting an existing language, which is what Ansible and Saltstack do with YAML. I find that to be much worse, since a lot more is valid as just YAML than ansible/salt files.
Agreed, Nix the language is probably unnecessary. (The main benefit I can think of is avoiding depending on the moving target that is basically any other scripting language they could have tried to co-opt.)
To be fair, Nix language is completely different from other languages out there -- it employs only immutable data structures -- so using another language would not be possible.
It does not excuse Nix to have such a braindamaged^W esoteric syntax.
> To be fair, Nix language is completely different from other languages out there -- it employs only immutable data structures -- so using another language would not be possible.
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.
This looks great. One question: We're currently using Drone (the open-source self-hosted version), which allows us to define a number of parallel sidecar containers ("compose") as part of the build pipeline.
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?
My general advice is to do integration testing after push.
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.
Hm, that's a bit much. In particular as various apps have a different setup (we're a microservice shop and have tons of them, although a minority needs external dependencies for tests like these). Splitting it up like that also generates a dependency, which adds a burden on an already complicated workflow. Drone just solves that so much better by keeping everything in a single, simple build file.
I agree, the semantics required to define the build in GCCB seems really limiting, going to stick to Drone until this matures a bit. The plugin ability of Drone really outshines the current as well.
Very glad that you are offering this service.
A key feature needed is speed, i.e. minimal time from check-in through build/unit & integration tests/image/deploy.
Questions:
- What delay can we expect from check-in to start of build (seconds, minutes?)
- What kind of compute power/memory is available for the build? if I run on fast CPU vs slow CPU that makes obviously a difference. What does this service run on?
- Is there a way to allocate more vertical resources (more CPU/memory)?
- Can parts of the pipeline be parallelized, e.g. run certain tests in parallel (using more than one core/machine)?
In my mind, at least for custom builds, the most widely-applicable optimization would be providing the build environment with a FUSE-mounted build-cache GCS bucket. Such a mount could then be used in ways similar to the way Heroku's buildpacks use their build artifact cache directory.
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).
We don't have any direct support of GitHub status updates. You can make whatever requests from within the build (presumably at the end), but we don't (yet!) have a supported way to get secrets into the build for access to POST the new status.
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.
I'm not quite a novice but not a real developer by any means. I'm interested in learning more about containers and using them with my RoR side projects.
Is this new product a good place to start that would be relatively pain free for someone new to containers?
If you're new to containers, I recommend starting by learning all about Dockerfiles. You can build them on your own machine, or with GCCB (using the `gcloud` command-line tool).
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.
The cloudbuild service operates some other services on your behalf, and their relevant charges apply.
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.
How are secrets intended to be managed? E.g.: NPM auth tokens (for private NPM modules), Github tokens (e.g. for private Ruby gems or submodules), Slack webhooks, etc.
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.
We currently don't have direct support for secrets other than your service account's access tokens. We hope to support more arbitrary secrets in the future.
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).
The problem with uploading them somewhere is that you introduce an implicit dependency that must be documented and dealt with as part of the whole devops universe — it's just one more thing on top of a heap of other things.
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.
Thank you for the input -- we do recognize the importance of being able to manage secure inputs to your builds and are investigating good solutions for this.
I really like rocket, and technically you can build and push rkt images right now, though it would require a lot of rocket knowhow.
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.
rkt supports running Docker Images[1], Open Container Initiative (OCI) Images[2], and appc images.
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.
Hi,
How does this work with regards to build parallelism? For examples builds that make use of outside parallel services such as ElectricAccelerator or Incredibuild?
GCCB does inside-VM parallelism with build steps, but the service itself does not support fan-out to multiple machines.
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).
While we are focused on building Docker containers, you are not required to produce a container in your build. Any other built artifacts will need to be copied to persistent storage in one of your build steps.
Just as with Amazon solution, this seems to not have caching. Baking deps into a separate image is a good solution, but oftentimes you want to rely on docker caching itself. For example docker caches `npm install` quite nicely if you split up the copying of package.json to a separate layer, which allows for a very neat flow where small app diffs result in a fast build, while adding new npm packages results in a slightly longer build. Not possible with GCCB or AWS CodeBuild.. For now, a self-managed Atlassian Bamboo instance (which can and does do caching for each worker) seems to be the best way?
With appengine exposing instances and cloud container facilitating the deployment of software packages, i wonder how long it'll take until the two merge.
That's basically what App Engine Flexible [0] is. It's yet to reach General Availability, but all you have to do is define a bunch of containers and a dispatch.yaml file [1], and App Engine then takes care of deploying/routing/scheduling it for you.
This sounds useful and revived my interest in GAE. The Go example has health check code. It makes sense. Are there equivalent offerings from AWS and Azure? This looks likes a unique GAE feature.
I think it's sort of container building as a service. It moves the burden of building Docker container from your laptop (or from your CI tool) to the GCE. It takes away the docker push, as it goes straight to the GCE registry (I guess).
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.
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.
I went through the doc. Yes, in addition to Dockerfile, there is a way to run tasks in parallel. I'm not sure how killing of a feature that is, when every build tool lets you pass a job count. And beside that, I can't think of a legit use-case of what to run side by side in a container build. Maybe someone else knows/cares?
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.
The difference between including the JDK vs only the JRE in your deployable image can mean hundreds of megabytes saved. If you're trying to roll out this image to hundreds or thousands of nodes, this can save a lot of resources.
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.
Agreed, my node builds tend to build to a ./dist including a separate package.json with all test/dev bits completely removed. From there I pretty much use the -onbuild containers from the dist/ path.
I'd imagine it's the same problem companies like Circle CI or Codeship solve with their Docker-focused products - testing, building and deploying containers.
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.
The problem is that it's tough to push code and have it just start running on a server. Docker makes packaging and running easy. Google has docker hosting. There's still a missing intermediary of building and registering the container, and this seems to solve that need.
Really interesting. Is it possible that you'll remove the "one build at a time" restriction at some point? I'm imagining builds across a large org some of which would need to be run in parallel. Or am I misperceiving things in one way or another? Thanks!
No, that's not all it does, though you can certainly use it to do that.
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.
I'd love to see that target the market for CI/CD tools which cost an arm and leg while offering a shiny UI but only a minor convenience. That would require an extended tutorial section and an ecosystem of plugins.
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.
Disclaimer: Codeship employee. Glad you like our approach. We are constantly working on performance, for sure. Since we offer dedicated build machines, there are always options for better performance.
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.
I did have a call some 3 months ago with your support rep and a sales person and provided extensive feedback - which was acknowledged and ignored. Which is precisely why I welcome new competitors that could wake you up from your comfy slumber ;)
Could I use this to build images and push them to Docker Hub? The auto build feature at Docker Hub is awfully slow and often fails. Could this be a good alternative or am I missing the point of what this is?
Hah, interesting to note how much dogfooding happens at Google before they make these technologies available to outside customers. This is a really smart move on their part.
Not exactly. I worked at Amazon back when code piplelines/ecs came out. What happens at Amazon is that they have a system in place, but it's very specific to amazon tools, and dependent on so many things. So they take they idea and reimplement it more genericly. But they don't then re-use the new product.
You end up sometimes with something great, and othertimes not so much. Pipelines internal to amazon is awesome. One of the best things about working there. I still haven't found anything like it, though gitlab is getting close. AWS pipelines on the other hand, was built by the same people, but it really isn't great at all IMO, not even the same thing.
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.
It's been around for a while, just under the radar. The service has backed App Engine Flexible environments for almost a year, it's been GA for months, but this is our first public spotlight.
We haven't had many projects exceed their daily free tier so far, and we've been backing all App Engine Flexible deployments for a while.
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.
I've ran medium sized projects (not hobby projects) on the GCCB, and they took about 5 minutes to build and test. Unless I want to build >24 times a day, this means GCCB will be free for my business in most cases. Personally, I think it's a great gesture, I didn't ask for it and yet it's free.
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.
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.