Shipping (apps in) containers
Software containers intensively developed devops crowd and are starting to catch on as a mainstream technology. But I think more pervasive adoption is hampered by another round of platform wars (Docker is not like Kubernetes is not like (fill in the blank). This forces application developers into tough choices, and reduces or complicates options available to users who would like to invest more in container-managed environments.
Triggered by reading this excellent summary, I finally got a clear idea of what a container is, abstracted from the jargon and confusing configuration interfaces that I've dabbled in, especially Docker.
Examples of how Docker and Kubernetes implement the same concept differently: different jargon, usually different details too. Poses a quandry for developer of an application which might be a candidate for packaging and distribution in a container (not all are).
Review of the things containers hide and expose.
Limitations on what kinds of applications would be appropriate for running in a container. Main thing is containers represent (one or more) processes. If your application doesn't run its own process, it's not a good candidate. So libraries are not a good candidate.
Promise of the container to the user integrating them into systems: abstracts details of app configuration, offers promise of one stop shopping for configuring the interfaces between containers. But containers focus on network and filesystem mapping from the container to the host. And the application developer doesn't need to change much to leverage these. However, ff the application has other top-level configuration controls that most users should set 1, the container platform doesn't make it easy to expose these settings as part of the container configuration. Docker uses environment variables for some of this, but application developers have to embrace it, and it's redundant for them if they already have some other configuration paradigm (
Abstracting config settings
E.g strings and numbers that might be URIs, port numbers, booleans.. Seems there are 2 ways here:
- extend the API that the app uses to fetch config settings from their natural home, and inject these values into the app at run time from some extended version of the container config. There are many of these settings frameworks: json, python settings, linux
argparse, toml ...
- get the container daemon (or other container initialization function) to inject the values into the containerized config file that the app will read from when it starts. This is pretty similar to how environment variables are injected into the app.
Either way, the goal is that the app developer does have to say which settings can be injected. To minimize the disruption to the existing settings framework, I imagine this declaration would take the form of a new, additional file exposed to the container platform.
How much detail is defined is an open question. At a minimum, it might simply name the files used for configuration and allow the container to set everything. This is how containers interact with files: they can remap any file or file system folder. It would be better, IMHO, to advance the discipline of application development by asking the developer to call out particular configuration items (and particular files) that most (container) users should configure. Many apps don't presume to know this and so leave it entirely to user's judgement, leading to a lot of confusion and follow up questions (always with fewer followup answers). So this would be a good thing, containers or not.
Improving configuration process for containers
(This is grounded in my limited experience with Docker, I have not played with Kubernetes at all and don't know whether it's better).
So now there's a way do do fine-grained configuration of the app from the container platform. This exacerbates the configuration problem for the containers. We'd like to have a single configuration experience, so users can master one paradigm and not necessarily have to go mucking about within the container. Desirable features of this config experience:
- Hierarchial, but mostly global names for files, ports other configuration items. Use (container) namespace to disambiguate if different items have the same name in different components. Deal with multiple instances of same container, too. (e.g each new instance of some server container needs a new port number. How to generate and how to specify?). But mostly, the names will be distinct or the values will be identical for different containers, so most names won't have to be qualified.
- Be able to represent any kind of configurable item. Simple config values like strings or numbers, file paths and uris, maybe even arbitrary structured objects with nested values. At the same time, have some data typing, so values can be validated at config time (at least partially). This builds on the presumption that container knows how to inject these values into the app at runtime. To do the validation in general, you'll need assistance of the application. For example, if app requires port number to be not only a positive integer but also to be > 1000 and divisible by 2, then perhaps app developer could publish a validation routine that container config can access as part of the container-friendly packaging. Perhaps this routine is executed in the container context by the daemon, so we don't have to force the application developer to write it twice.
- Finally, do something about the rest of the container configuration experience to standardize terminology and maybe even syntax across container platforms. I certainly found Docker config complicated and unnecessarily mysterious. I don't know anything about Kubernetes config, but I understand orchestration makes it a bigger space. Maybe they've already been forced to simplify and organize the config?
Conclusions and next steps
All I've got so far is the germ of an idea. I doubt it's a new idea. I'd love to hear feedback, and maybe pointers to existing efforts or at least existing complaints along these same lines.
Need more examples of what I'm talking about here. Think about plugging port numbers or URIs into an Ngnix config file, or django settings.py, ... ↩︎