Hacker News new | past | comments | ask | show | jobs | submit login
Breaking up the Container Monolith (redhat.com)
104 points by perpetualcrayon on Aug 26, 2017 | hide | past | favorite | 32 comments



They complain about Dockerfiles and have a broken link to some project with 288 commits, without even acknowledging that a Dockerfile isn't needed to build a docker image. It is just as easy to build from a regular old disk image, a chroot, etc. I don't blame RedHat for trying to capitalize on the container frenzy, but this doesn't reflect well on them. Also, kind of expected more from the SELinux Coloring Book.


I also feel like Docker's multistage feature already solves the container size flaw.

>This tool also allows us to build containers without all the container development tools inside it (yum, GCC, secrets, etc). Basically, Buildah produces clean containers, which means the container can be much, much smaller.

With docker you basically have one stage where you load all the dev tools to build the application or library. Then you have a second stage where you merely copy your application and run it. I often have a Dockerfile that builds a java library which then merely copies the .jar file into an empty docker image. The end result is usually a docker image smaller than 10MB. Then I add this image to the dockerfile that actually needs the library by adding it as an empty multistage and as part of the last stage I just copy the files of the library image into the application image. This way you can "inherit" multiple docker library images into one application image.


>>> The end result is usually a docker image smaller than 10MB.

You forgot to install the JVM to run the .jar, didn't you?


A possible option for containers that all run JVM applications is to have a volume mount for all of them that points to an external filesystem containing the JAVA_HOME contents. This somewhat violates certain containerization principles but can help reduce some disk usage across dozens of containers on a host.


You could base all the images on the same layer, then the disk space wouldn't be an issue, right?


It is an advantage in specific situations when you can't rebuild every container or you want to try to selectively update containers without rebuilding them. You should try to update the running containers as a rule but having options is helpful from time to time. In a properly managed container infrastructure it should be faster to update the container image reference before resorting to tactics like this.


It would be interesting to consider what it'd be like to swap out layers directly, instead of having to "rebuild" the final image.

Perhaps a hack for a free weekend.


That would lead to a small image size because you would just apply the .jar to a base Java install but it doesn't do anything for the container size because they all will have their own JVM copy.


I don't understand what you mean for the container size. If they share the same base layer it won't use more disk space to store than splitting it up, surely.


You're missing the fact that if they're all using the same layer (base image) for the JVM all the images will be deduplicated (well, CoW) so you could have a hundred different apps and they would only use the equivalent of a single image for the JVM (in terms of storage).


The final stage usually uses the tomcat docker image or just the alpine java image and copies the jar/war files in there without building anything.


> They complain about Dockerfiles and have a broken link to some project with 288 commits, without even acknowledging that a Dockerfile isn't needed to build a docker image.

They literally say that a Dockerfile isn't necessary in the same sentence as the broken link you mention:

> This brings us to Buildah, which is an open source tool for building containers without using Dockerfile at all.

What's the significance of the number of commits?


> They literally say that a Dockerfile isn't necessary in the same sentence as the broken link you mention.

They say "It has been four years and we still have to use Dockerfile, which is a horrible version of bash." They say "we still have to use Dockerfile". They _never_ _had_ to use Dockerfile.


I don't put expectations on coloring books.


Also no mention of https://github.com/rkt/rkt ?


Oh yeah, what's happening with that? Haven't heard anything about it lately


Dockerfile is the best thing Docker has to offer. Simple, text-based, easy to learn, consistent enough for practical use. What's the problem?


* Single inheritance. Dockerfiles cannot be easily composed, you need to arrange them in particular order. This leads to either kitchen-sink images or deep, brittle hierarchies.

* Leading to: inheritance for construction. Lots of images include a bunch of irrelevant material because it was easier to FROM an existing image than to tease apart the kitchen-sink into the brittle hierarchy.

* Meaning: using composition isn't really "a thing" in the sense that it's commonly used. I'm given to understand that OCI layers can, if you recalculate the hashes, be layered in arbitrary order. In an ideal world the build tool can check that there won't be layer conflicts, meaning you can treat layers as immutable mixins, rather than immutable parents. Instead of FROM, you could have UNION or PLUS.

Then of course the less abstract stuff:

* Mystery meat. Dockerfiles make development solely responsible for managing all dependencies from the OS up. An awesome tool and a problematic responsibility. You've graduated from worrying about XSS holes in your web framework to fretting about kernel bugs and glibc glitches. Where I work we have an entire team devoted to tracking CVEs that affect code we ship. Do you?

* Mystery meat, at scale. Now you have 5,000 containers running ... what, exactly? What versions of what OSes? Are the runtimes up to date? You're going to need to either rigidly control Dockerfiles -- in which case, what did it buy in terms of dev flexibility? -- or you're going to need to buy tools to scan all your images. Docker sells such a service, as it happens.

Dockerfiles are a simple, clean exposure of the original concept of layered FSes, processes and ports. But they are not without limitations.

Disclosure: I work for Pivotal, we compete with Red Hat and Docker in the PaaS space.


As a sibling mentions, Nix is has support for working on building Docker images. The syntax is declarative by default but does allow for an escape-hatch if required to run custom commands[1].

The support is decent and has a couple of interesting properties.

The first is bringing all of the stateful code `apt update` etc. out of the image. It is not necessary for it to be there in the first place. Because of the packages being updated out of the container, and the way nix caching works we don't need to worry about security fixes being missed because of the Docker caching.

Another benefit is declaratively building the image, This gives us a guarantee that we will get the same image on two machines. They are currently working towards reproducible builds meaning we will get to a point where two builds will produce _exactly_ the same docker image.

I agree with all that you're saying, Dockerfiles seem to be artificially constrained and a poor interface for building images.

[1] https://nixos.org/nixpkgs/manual/#sec-pkgs-dockerTools


I don't know if the problems you describe can be solved by anything less than fully declarative approach; and even NixOS isn't there yet.


I've elsewhere put the view that configuration management tools more or less fill this role, as they build on the existing nature of filesystems: spread your stuff horizontally into tree structures, so it doesn't collide.

Most of the ordering dependencies don't show up until runtime. The bits at rest can generally be played in any order.


The Dockerfile language has some very frustrating limitations.

One I've found frequently frustrating is the inability to do any sort of globbing on COPY commands. This can make it very difficult to do some types of layer optimizations. For example in the Java world I have multi-project Gradle builds which consist of a tree of directories each of which contain a "build.gradle" file. I would like to copy all of these files, preserving the directory structure, into the container so that I can run a preliminary "gradle assemble" command which installs third-party dependencies, then only after that copy the remaining contents of these directories. That way I only need to re-download dependencies if any of the "build.gradle" files change when building the container.

This turns out to be impossible to do in the Dockerfile language without manually listing out every "build.gradle" file in the directory tree.



I've not really been a fan of the Redhat ecosystem for years. Fedora, RHEL, etc. while "stable" always feel like if I want to build something a bit more modern requires contortions that even Debian Stable did away with years ago.

As for "Buildah", what about Deis and build packs deployed to Kubernetes? RH has gotten better in recent years with Openshift syncing closer to Kubernetes releases, but are still a far cry from how CoreOS handles things with Tectonic.


You are choosing the wrong distro if you want modern. Red Hat Linux is about stability over a long period of time.

Don't have a clue what you're talking about with Fedora, it does exactly what you want.


I've worked on Cloud Foundry buildpacks. Something that does a better job at assembling OCI images than Dockerfiles is still welcome.

Buildpacks have the advantage that the developer doesn't need to care about anything below their own direct dependencies. The runtime and OS are kept up to date by the platform, so you're relieved of the broadest angles of attack.

It's not a panacea. Just as with Dockerfiles, you have other upstream dependencies (Ruby gems, NPM modules, JARs etc) that need to be tracked and updated. Some of that can be delegated to the buildpack (ie, setting version range specifiers like '^1.1.2' or '1.1.*'), but that introduces some uncertainty about what is actually running in production.

Deis I believe did what we originally did in Cloud Foundry, which is to use Heroku's buildpack code. We ran soft forks for several years, adding only enough to allow execution in disconnected environments.

The Buildpacks team have since adopted a hard fork policy and have been replacing Heroku code with a uniform codebase called libbuildpack[0]. The new ones pass the same test suite we run and should work for Deis.

[0] https://github.com/cloudfoundry/libbuildpack


Huh? Fedora is one of the most bleeding edge, "modern" distributions you'll find.


And then you can move to Rawhide if that still isn't new enough.


Unikernels are a better simpler tech than containers but somehow we're stuck with containers.


Containers don't require a per-technology implementation, so it's easier to adapt existing systems to use them.


How does a unikernel solve all of the same problems as container?


Embrace and extend?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: