Bocker – Docker implemented in around 100 lines of Bash (2015)
github.com
github.com
wget https://bla/image.tgz
tar xzf image.tgz
rm image.tgz
chroot image/start
and the product would be installed and up & running. A lot of clients thought it was magic. No Apache install? No MySQL install?? It works on Fedora & Centos & Debian & Ubuntu & ... ?I use this currently still a lot to run new software on unsupported hardware/kernels. For instance, I run a lot of new (Ubuntu) software on my OpenPandora under the default OS on that device; I have an SD with a chroot with Ubuntu and things like dotnet core. Runs fine. Gives devices like that a second youth.
On top of all this, they designed a new programming language / build system for making those tar files. They invented a container registry so that instead of just "downloading a file", you have to use their particular protocol to download a file. They have their own version of systemd so you can see what programs are running. They tacked on some very complicated networking stuff. They tried to build a couple of container orchestration frameworks on top of all this. I think all the "extra stuff" is where people run into problems, and it's isn't even the core of the value it provides.
People have realized that it's all a little much and the good bits have been distilled into their own projects. Many build systems can just generate an OCI registry file directly (remember, it's just a tar file, and you don't need all that 1970s JCL stuff to make a tar file). Various runtimes (containerd/CRI-O) exist for running containers. And there are orchestration layers on top, for actually managing sets of containers, network rules, etc. (ECR, Kubernetes, etc.).
(Worth noting is that Docker itself does use all these spin-offs. It uses containerd as the runtime, it uses buildkit for building containers now, etc. They even ship a Kubernetes distribution, at least on Mac and Windows.)
Personally, I preferred my home brew “Kube” that would ssh updates to cgroups from a central control server.
Which is basically the Chef model, and Salt model of clients pulling desired state.
Docker & Kube aren’t novel and weren’t as specific things. Tons of home brew options operating in roughly the same style existed around the net.
Their adoption in industry, use at scale, simply gives them a grander appearance of somehow being truly novel
Basically, "it's just chroot with [tons of useful features]"
Docker allows the programmer to write more code to build and maintain their environment, cutting the system administrator out of the loop; the sysadmin just has to provide a server able to run generic Docker containers, and doesn’t have to care about what’s in them.
Basically it’s a bit of a power grab, and a bit of developers being upset about slow processes in their companies (“why does it take two weeks to deploy a new version of this dependency”) and finding a workaround. Then the rest of the world started cargo-culting them.
The enterprise is about supportability, scalability, and ease of maintenance. Officially support software and common tools/platforms/SOPs are a must unless we're building something brand new from scratch. DIY charoot jails may work just fine... until the two admins who really know it go on vacation or quit or get fired for mining BTC on company gear. Now Johnny-New-Hire needs to unravel it, and it may not be documented well, or even work that well without an admin kicking it occasionally.
Were I to put a job advert out for DevOps roles needing Docker I could usually get someone with a base level of competency, and get them reasonably quickly. Likewise if I need to outsource this to contractors or even offshore budget IT support it's a lot easier to find a Docker guy then it is running someone through whiteboard exercises to figure out how much they know about jails and makefiles. And if we're way out of our league with issues there is Enterprise Docker which is expensive but gets us official support from Marentis (or whoever owns them now), which may not be justified in terms of cost, but absolutely makes management sleep easier knowing we can escalate things if we can't fix it internally.
Docker lets you build all the dependencies once, and then run it anywhere. You can run your container on your Mac in a (managed!) VM. You can send it to Amazon to run on a random EC2 instance that you don't have to manually update. Or you can just run it on your normal server, without affecting anything else on that server.
It isn't about developers wanting to write more code. It's about developers getting annoyed with the difficulty of installing software.
In my experience, systemd-nspawn provides a nice alternative. It's mainly a chroot that abstracts the low-level details, and it fixes some security concerns (with cgroups, etc) and adds some nice features: e.g. networking, or `systemctl status` from the host that will display the sub-tree for the processes of the sub-host.
I was left puzzled.
The only time this is reasonable is when a container needs to manage services on the host a la what Portainer does for Docker.
You have a lot of options for accomplishing what you want.
* To run a service with a given root filesystem add RootFilesystem=/path to your unit file.
* Run a service from an image of a root filesystem use systemd portable services.
* To run your service using the init system in your root filesystem (could be systemd but doesn't have to be) use systemd-nspawn --boot.
I mean, as long as you have /proc, /sys and etc bind-mounted you should be okay, right ?
Running a systemd service means talking to the /org/freedesktop/systemd1 object on the system bus typically listening on /run/dbus/system_bus_socket and asking it to start your service. This is all that systemctl really does.
mkdir ./rootfs
curl -O https://cloud-images.ubuntu.com/minimal/releases/bionic/release/ubuntu-18.04-minimal-cloudimg-amd64-root.tar.xz | tar -xJPC ./rootfs
mount -o bind /proc ./rootfs/proc
mount -o bind /sys ./rootfs/sys
mkdir ./rootfs/run/dbus
mkdir ./rootfs/run/systemd
mount -o bind /run/dbus ./rootfs/dbus
mount -o bind /run/systemd ./rootfs/systemd
chroot ./rootfs bash
# See that it works just by sending dbus messages.
dbus-send --system --print-reply --type=method_call --dest=org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager.ListUnits
# Now do the same with systemctl.
export SYSTEMD_IGNORE_CHROOT=true
systemctl list-units
THIS IS ALMOST CERTAINLY NOT WHAT YOU WANT. You're just talking to the host systemd. You won't see any of the services in your chroot since how could systemd know about them? Your chrooted root is also now just root on the host. Just use systemd-nspawn. # undo all the bind mount junk.
chroot ./rootfs bash
useradd ubuntu -G sudo
passwd ubuntu
exit
cd ./rootfs
systemd-nspawn -x --private-network --boot
# login
sudo systemctl list-units1. Put files on a device
2. Start a process
The scale at which containerised scheduling of this outcome saves more time than it consumes is much higher than many have been led to believe. I measure it in sysadmin FTE. If you have >0.5 FTE dedicated to managing deployments then there may be a payoff, because (amortized over a reasonable period e.g. 12 months) it takes at minimum half an FTE to setup, manage, and maintain a PaaS properly.
I've become accustomed to folks claiming things like, "I spend 5 minutes a week managing my kubernetes cluster". Then it turns out it took them a solid month to get it going properly, two weeks to containerise their application reliabily, and then next quarter they're stuck for days on some weird networking or logging issue, and nothing else progresses. Basically, they either don't value their time, or they're misjudging how much they've actually allocated.
It's often the same people who boast about how cheap their bare-metal servers are vs public cloud instances.
In these distributions, you have tools ("pbuilder/*builder" in deb base distributions, "mock" in rpm based distributions) which create a chroot, grabs the build dependencies and install them from the repo, build the package and then throw away the chroot.
It's really convenient for many reasons:
1) tracking and referencing build dependencies is far better as you have to declare them explicitly, no more "but it used to compile on the old machine... what am I missing".
2) you don't add kludge on the host running the build as you start from a fresh chroot every time.
3) you can target many distributions/versions from one building host (I'm regularly building RHEL 7 and 8 rpms and Debian 7, 8, 9, 10 debs from my Debian sid for example, without too much worry of weird side effects due to my particular setup.
The downside is that builds can take a bit more time, but that's clearly something I'm willing to trade-off for more systematic and (semi-)reproducible builds.
I even spent a few nights a month ago to have a newer version of mock that supports EL8 available on my Debian (for those interested: https://github.com/kakwa/debian-rpm-build-tools)
We should never forget that at the root of containerization is a desire to keep everyones shit sorted. That's been a Unix thing forever.
EDIT: "Gives devices like that a second youth."
Hell yeah, long live the OP!
That's literally the point of operating systems: To allow many people to share the resources of one machine without being able to interfere with each other. Modern containers and VMs are just reinventing operating systems, and unfortunately they're doing it on top of existing operating systems rather than building -- you know -- a better operating system.
I feel I don't know enough to see the issues with an approach like that, or know why it's not already mainstream.
Been keeping an eye on GPD's other thingies, but I'm just jaded now. I just want a revised version of the Pocket1 that doesn't suck.. totally with you on the track-pointer.
You can make a "spectrum" of environments where you run code. One one side is everything running on a single server in a single OS, on the right is everything having its own machine and OS. In between you have chroot, docker, blade servers, virtual machines, and other isolation techniques. chroot falls somewhere between everything running in one system, and everything running in docker containers on one system.
That does not mean you can slap chroot syscalls everywhere and call it secure, of course. But it is still an important part of dropping privileges, together with seccomp-bpf, control groups and the various ACL systems.
It is an important part of things like the OpenSSH privilege separation, where the early protocol is handled by a dedicated process in a read only chroot. It proven both simple and effective in practice, contrary to the idea that chroots are escapable.
I too thought you can't easily escape unprivileged chroot, but in reality you need to think about quite a few things to make sure it's true.
And once you need to think about those things... Why not apparmor/selinux instead.
If an untrusted process can escalate to root, ptrace to unrelated processes, or access memory outside your process, it was never really contained in the first place.
Do also note that none of the listed methods works in what the presentation itself calls a "reasonable chroot".
> Why not apparmor/selinux instead
It's not either or. Dropping privileges is something you preferably do in more ways than one.
The illumos ecosystem in particular got a lot of work from Joyent in this container vein—like how Windows can now run Linux binaries natively because they implemented the Linux system call table, illumos has Linux-branded zones that do the same “our kernel, Linux’s API, no virtualization” approach to Linux containers.
Running on a hypervisor originated at IBM, on its 370, and is very mature technology. Arguably, an OS running on bare metal is practically an embedded system, these days; There are just so many things that make a hypervisor useful or essential.
The key insight IBM had was that the hypervisor runs under the control of one of its VMs. That means the hypervisor doesn't need to provide a full-featured, comfortable work environment; that is the job of guest OSes. Instead, it manages resources according to policies implemented in an "executive" guest OS not used for, or vulnerable to mistakes or malevolence in, regular user programs.
A modern example of such a system is Qubes, security-oriented OS that hosts and orchestrates Linux, BSD, and even Windows VMs.
It’s actually a pretty neat architecture— I’m on my phone right now and can’t track down a link, but it’s worth reading about if you’ve got the time. Kind of a shame that they moved on to the virtualization approach, but understandable— they’re trying to solve the same sort of problem as Wine, where you’ve got to mimic all the quirks of a foreign OS and it’s also a moving target (so you’re never “done”).
That’s not really that new. Windows 3.x, running in 386 Enhanced mode, was based on a 32-bit pre-emptive multitasking hypervisor (the VMM). Windows apps shared VM 0, cooperatively multitasked, and were mostly 16-bit. VM 1 and above were for DOS apps, including 32-bit DOS apps using DPMI.
(In Windows 3.0, it is possible to start a subordinate instance of the Windows UI in VM 1 or above. This possibility was removed in later versions.)
This architecture was introduced in Windows/386 2.1x and maintained through Win 95,98 and Me. (In Win 95 and later, most of the 16-bit code in VM 0 became 32-bit.)
Just wanted to point out that this is true for Docker containers as well.
Something that has actually come in handy from time to time trying to diagnose things.
I think from within the container you can only see that container's processes, but outside (as root) you can see all processes, even those inside the container.
Unless you make your Dockerfiles `FROM scratch` you do have an OS too.
Vulnerabilities in libc (eg: dns resolver) bundled Sendmail, databases... They can be independently patched (good) or they can be independently left on ancient unpatched versions (bad).
If you use the system/distro library services, it can be easier to verify patch levels and know if any given hole (eg this week's sudo hole) affect your system or not.
Also... can someone weigh in on why the likes of Linux VServer and OpenVZ became dormant??
After KVM appeared, it was a little better, so people who were already using it continued to do so.
FreeBSD is probably used to serve more data over the internet than any other OS distribution. All Netflix streams go through FreeBSD.
So yeah, still going strong.
SmartOS is an open source operating system that is widely used commercially as a kubernetes node (among others). It has native ZFS and DTrace, in addition to zones, etc.
So is kubernetes second-tier? I don't understand your point.
FreeBSDs success is invalid because its Netflix that heavily use it? Get real...
The SmartOS is just yet another OS with limited adoption. Whether it's "used commercially as a kubernetes node" doesn't mean much. Itself is second-tier, not Kubernetes (an OS doesn't magically adopt the success/adoption rate/etc of the tools it's used with. Most Kubernetes nodes remain Linux).
As for FreeBSD, which I use to run back in the day for a spell, it has hugely declined in use from the late nineties.
>FreeBSDs success is invalid because its Netflix that heavily use it?
You got it backwards. Your argument that "Netflix uses it" as proof for FreeBSD success in 2020 is what is invalid.
One company (however big) using an OS doesn't mean the OS is a success, or hasn't declined in adoption.
There's bunch of companies that use and regularly contribute to the code:
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/n...
Also: https://www.freebsdfoundation.org/donors/ (I would imagine that company that donate have interest too keep it alive because they use it)
Apple doesn't disclose much about their infrastructure, but they did post jobs looking for FreeBSD admins so I would imagine they don't have a negligible number of them.
WhatsApp was running primarily on FreeBSD (not sure how it is now)
So? As a feat is even less impressive that the one we just rejected as some major sign of it being a success (Netflix running FreeBSD).
I'm sure it also runs a lot more of servers. But it's less prevalent that it used to be, and Linux has eaten almost everything in that space.
Enumerating success stories is the first sign of a project with few of them (Linux doesn't have to enumerate how many companies use it). It's the same for language. C or Java don't need a "success stories" page. But niche languages will invariantly have one, and tout it as some proof that they're widely used...
[[ $# -gt 0 ]] && while [ "${1:0:2}" == '--' ]; do OPTION=${1:2}; [[ $OPTION =~ = ]] && declare "BOCKER_${OPTION/=*/}=${OPTION/*=/}" || declare "BOCKER_${OPTION}=x"; shift; done
If the ambition is to write lines like this, you can make it into ~1 line of code.Just because something doesn't follow general rules for readable code, doesn't mean it is actually unreadable.
I can definitely guess the pattern and I do write bash regularly, but I see at least 2 things I'd need to double-check the man page for the behaviour.
Heck, by this definition i'm not sure any code is really good enough. In my job i have to write php daily, i still need to regularly look at docs to figure out order of arguments for various library functions. I wouldn't be able to tell if explode($a, $b) in php has the right argument order at a glance without looking it up. But i understand the intent and generally assume the superficial aspects of the code are right unless that part appears not to work.
And furthermore, adjusting the number of newlines isn't going to help with the question of if that piece of code is using bash syntax correctly.
Other languages seem to've made things at least somewhat more predictable.
(and then, being software, suck in different ways of course)
Perl gets a lot of flak for being unreadable, but I personally have more difficulty understanding bash code than perl (not implying that perl is super readable).
if [[ $OPTION =~ = ]]
then
declare "BOCKER_${OPTION/=*/}=${OPTION/*=/}"
else
declare "BOCKER_${OPTION}=x"
fi
Going from here, if you rewrite this in golang you'd probably improve readability.But the readability has not been "thrown out of the window" yet, like in this case:
[[ $OPTION =~ = ]] && declare "BOCKER_${OPTION/=*/}=${OPTION/*=/}" || declare "BOCKER_${OPTION}=x"Yeah, that was unnecessary. Ironically now I remember that I was once frustrated by someone who was using Boolean logic to emulate if/else in Python.
for (i = 0; i < argc && (arg = argv[i]).startswith("--"); ++i)
if (sep = arg.find("=")) opts[arg[..sep]] = arg[sep+1..]; else opts[arg] = "x";
It might be too much for one line, but it doesn't seem to be super complicated either. In fact that line is (as of now, commit 0006330) only the second longest in that file.Sure, if you're coming from structured Pascal 101, that might be an issue, but in the day where deeply nested functional rat kings tend to replace the humble WHILE loop, is a Schwartzian transform that confusing?
And implicit variables. Also, implicit variables. Composed types didn't make it any easier; and references, that broke all the logic implicit on the sigils.
Oh, and did I mention implicit variables?
They don't break the logic, they just follow different logic than many people assume. Either you're indicating a collection (a hash or array), or you're indicating an item. @ is a plurality indicator, while $ is an individual indicator. You reference the single item of the @foo array with $foo[0] for the same reason you say "the first apple of the bunch" instead of "the first apples of the bunch" when you want the first one. Yes, it's probably better not done that way (it's not something you can usefully change in Perl 5 at this point), but it does follow well defined rules, apparently just not the ones you assumed.
Implicit variables can usually be avoided (except for $_, but that's pretty normal these days, and I'm pretty sure it topical variables didn't begin with Perl), and often they're lexical so usually other people's code messing with them is contained. Except for $_ itself which isn't lexical, which is it's own story and a pain point. :/
C works similarly. What was the error from the last system call? "errno".
Certainly there are problems with this; we've all seen the programs that output "Error doing something: Success". But it isn't Perl that invented this. It's a UNIX tradition.
As for implicit variables, I rarely see anything else than $?, $|, $_ and @_, of course. And I'd argue that $_ often makes code a bit easier to understand than cluttering it up with a variable declaration. No worse than point-free programming in more modern languages.
Don't get me wrong, I don't think that Perl is that well architected and that Perl5 would've required some more courage at dropping backwards compatibility, but what I don't get is why Perl is singled out here. It's not that radically different like e.g. APL or ScalaZ.
Compared to other languages of its day, this feels a bit like the "Reformed Baptist Church of God, reformation of 1915" joke. Then again, perfectly fitting into similar conflicts about brace styles or 1-based indexes…
Both of what never got as much popular.
Perl is singled out because it was used. And too often on short scripts that grew into thousands of lines, so the problems showed up.
Now, Python on the other hand...
It fixes a hole lot of more important problems, but it's mostly aimed at problems that will make your code misbehave, not the ones that will make it hard to read.
But the end result was horrible: everyone did "it" every possible way, and that, IMO, is the underlying reason for Perl's reputation for being unreadable.
I also think it had a great deal of impact on the development of later languages and principles, which tend to focus much more on removing freedom from the programmer and enforcing idiomatic ways of doing "it". Today, you're far more likely to encounter modern code written by different programmers which looks very similar -- at least on a line-by-line basis, anyway. At the architectural level, it's still a big game of Calvinball.
In my mind, it's down to it having been popular, attracting many amateurs. You'll find equally unmaintainable bash or PowerShell scripts and definitely as much garbage, WORN JavaScript code. Writing maintainable code requires both knowledge and effort.
[0]: https://metacpan.org/pod/Modern::Perl
[1]: https://metacpan.org/pod/Moo
[2]: https://metacpan.org/pod/Mouse
Here's a small IO::Async + Moo app that I still consider to basically be how I'd write it today - I invite people to browse the source code and tell me what they do/don't find unreadable compared to more "raw" perl.
I worked in a company that had huge Perl codebase, which made extensive use of the Moose library. After trying to make sense of it, I gave up and used plain Perl, writing it as unidiomatic and simple as possible, so that hundreds of other devs, also new to Perl, would be able to understand the code I wrote. This was the common sentiment - most of the people followed the same path.
The library is just a nightmare - Perl is dynamically typed, there is NO adequate IDE support (compared to the one statically typed languages have), so good luck with working out how the library works underneath. And if I cannot understand that, how on Earth will I understand what even my code is doing? (Never mind the others')
In my mind, the amateurs are those that created the libraries without any idea on how they are going to be abused, thinking everyone should use unreadable incomprehensible syntax coupled with unapproachable internals.
I apologize for the rant, I had no idea this topic moved me so much.
I mean types do make software engineering craft a little tolerable and its not exactly a new thing to say here.
But how would this situation be any different than using Python or Clojure?
Talking of artificial bolt-on's. We are living in an era where we do 'from typing import *' and core.spec for Clojure all the time these days. How does this change only when it comes to Perl?
However, I still reach out to Python and Bash and Perl for some one-off tasks or gluing scripts and I do appreciate the brevity and clarity they bring for this sort of problems.
Except when it comes to building somewhat large systems (I am talking ~5 mil LOC here) - then every kind of "abstraction", like this disaster of a library Moose, only increases the complexity of the project by a large margin, and acts only as job-security for the original authors of the code, making most of the codebase impenetrable for the rest.
I have not worked with similar large systems in other dynamically-typed languages, so I cannot compare other languages to Perl in that regard. I do know, however, that Perl is simply a disaster to use in that scale.
I think most Perl developers would agree that if you expect you code base to reach in the millions of lines of code (at least if it's all one code base and not an ecosystem using an API), Perl (or any dynamic language) may be stretched to the point where its benefits are outweighed by its drawbacks, similar (on the other side of the spectrum) as if you used C/C++ to build a simple web app.
Perl is great for text manipulation and one offs, not large, production systems.
return $foo->bar->baz;
to return Dwarn $foo->bar->baz;
which will 'warn' out the dumped structure and then return it, so you can instrument code for debugging trivially.DDCWarn also provides a DwarnT so you can add a tag that gets printed but not returned, i.e.
return DwarnT TAG_NAME => $foo->bar->baz;
There's not really a book on Moose, but the Moose::Manual pages plus Modern Perl plus The Definitive Guide to Catalyst work out pretty well between them for bringing people up to speed.Over-use of meta stuff is something people often get tempted into when they first use Moose and can make things a bit more complicated, but the core syntax is honestly simpler and easier to use than raw perl OO and I've found it much easier to cross-train non-perl devs to Moo(se) style OO.
If you want an opinionated/terse syntax that encourages you to only be as clever as strictly necessary, I'd suggest looking at http://p3rl.org/Mu
LOL, WUT? Why do you need IDE support to figure out how the library works underneath? You have the code, you have the docs, what else do you need to figure it out?
I guess if you do deliberate golfing/obfuscation you can make anything unreadable.
#Before enlightenment,
use strict;
use warnings;
#After enlightenment,
use strict;
use warnings; use strictures 2;
use Moo;
since strictures fatalizes most warnings as well as turning strict on for maximum "telling perl if I made a mistake to barf immediately rather than trying to be helpful and guess"Interestingly, I didn't know you could do this without an `eval`:
declare something${something_else}=whatever function bocker_help() { #HELP Display this message:\nBOCKER help
sed -n "s/^.*#HELP\\s//p;" < "$1" | sed "s/\\\\n/\n\t/g;s/$/\n/;s!BOCKER!${1/!/\\!}!g"
} target1: ## Do this
target2:
target3: target2 ## Do that
would be nicely formatted as the output of `make help` into Available targets:
target1 Do this
target2 Do that
and if you want to see all targets along with their origin file, even those without help messages, type `make help-all` to render Available targets:
target1 path/to/Makefile Do this
target2 path/to/Makefile
target3 path/to/Makefile Do thatThat certainly counts as reflection in the context of shell scripting... :-P
Can we really say it’s a reimplementation of Docker in 100 lines, though, when it requires other dependencies that probably total in the hundreds of thousands of lines? That’s still code that has to be audited by people so inclined. Not to mention the other setup specified in the readme and maybe having to build one of the dependencies from source. Usage doesn’t sound necessarily trivial.
Makes me appreciate Docker that much more though. Getting up to speed using it at my job and it certainly abstracts away many things, simplifying our workflow and conceptual models.
You know the comment from a guy who thought Dropbox could be easily replaced with a few Unix tools? https://news.ycombinator.com/item?id=9224
There's a difference between fulfilling a use-case well and having a technically minimal solution.
I actually wrote the core of an ansible class tool in 200 lines of Perl 20 years ago. Perhaps I should have been bought by red hat by now :)
Its almost like several of these projects existed for long until people came around took them a little more seriously and built businesses around them.
This also reminds me using the Unix DBM's do all kinds of key-value store work. Long before things like Redis and Memcached were around.
Yes, and that's a big problem.
Nowadays huge numbers of developers pick choose technologies because they are hyped up (aka marketed) rather than being wary of them.
Same for other projects (not programming languages).
http://eliot-jones.com:5690/Home/Trend?id=rkt&allwords=true
http://eliot-jones.com:5690/Home/Trend?id=docker&allwords=tr...
I mean heck, here we are 137 comments into a thread about an alternative to docker and I was the first to mention rkt.
Plus I think by providing infrastructure services and technology, they get valued much higher because other tech companies are their customer and they're usually rich as well
Perhaps not 'unicorn' valuable anymore as it went through that phase of adding enterprise shovel features. These days all cloud enterprise software companies must badly incorporate the features of other products because most Enterprise software buying criteria are just boxes to be ticked.
More seriously - it’s not a complete docket of course, but lines of code in a project are a liability, not an asset. If you can reduce your project size with reasonable dependencies, you should.
Certainly makes the technology interesting to investigate if it could be a fit for you as well.
It's being a toolset to build and deploy containerized applications.
In other words, being able to docker-compose up --build on any Linux, Windows and MacOS box is what's useful.
>The problem of waiting for a database (for example) to be ready is really just a subset of a much larger problem of distributed systems. In production, your database could become unavailable or move hosts at any time. Your application needs to be resilient to these types of failures.
absolute bullshit. docker compose thinks that it can excuse its bugs by dint of the fact that we're supposed to build "more resilient" applications to accommodate them.
and, their proposed workaround with "wait for" is disgusting. their tool should be able to handle readiness detection. it's so fucking basic.
it's not only this but this is an example of the bullshit in this shitty tool excused with shitty reasons.
Are you working with tools where this is a problem in practice?
Most web frameworks I've used will keep trying to connect to the DB in a loop until it either connects and things start normally, or it times out after X amount of seconds where X by default is configured to some number that's way higher than it would normally take for your DB to be available, even if it's starting from scratch with no existing volume.
No "wait for it" script needed (and I do agree that type of solution is very hacky). Although to be fair the same page you quoted said the best solution is to handle this at the app level, which is what most web frameworks do.
100% of the solutions ive seen to address this problem have been hacky - either polling bash scripts or explicit waits.
docker compose is a piece of shit.
https://blog.alexellis.io/building-containers-without-docker...
It does seem like Docker will be holding back containers from achieving their true promise, as it flounders looking for profitability and chasing k8s. Its sad that we're still moving around tar balls without advancing some of the tooling around it.
One of my biggest gripes as a non-k8s container user are that we are still keeping all this versioned cruft with every container. I would like to see an easier way to just get the latest binaries not dozens of tar hashes with versions going back to the first iteration of the container. Probably closer to singularity https://singularity.lbl.gov/
Another area is the ability to update containers in place. Hass.io https://www.home-assistant.io/hassio/ does some of this with the ability to manage the container version from within the container, but seems like a little bit of a hack from what I've seen. Watchtower is closer to what I'd like https://github.com/containrrr/watchtower, but why can't we have a more integrated system built into the default tooling?
Docker is a good tool and deserves some resources to continue developing the product and funding marketing team. I wish docker hub to be more competitive among other rivals.
I didn't say it wasn't. Docker makes sense because everyone uses it.
However, I would prefer a Docker alternative that is purely local and doesn't require so many permissions.
In FreeBSD you would be able to also remove such restrictions if needed (not sure if something is also available on Linux) alternatively you could have your app listening on a higher port and use iptables to forward port 80 there.
Most public images I see on Docker Hub run on default ports. Sure, a lot of these are configurable, but then you need to reconfigure all the consumer services to use a non-default port. FreeBSD is not an option, unless you are willing to run on your own hardware. As for iptables, does podman provide network isolation where you can define iptable rules per container? I know it wouldn't work with docker.
Docker stopped publishing builds of their own registry many years ago. So if you want to run the official registry, you need to build it from source. This leads to a fun and exciting bootstrapping process; to launch the registry, you have to pull it from somewhere. Since your registry, which is where you'd like to store it, isn't running, you can't pull it from there. So you have to use some third-party registry to bootstrap. Or do what I did, and give up, and just watch their registry crash randomly when it receives input that confuses it.
People will make fun of me if I go into the great details of the workarounds I have to make a DigitalOcean managed Kubernetes instance pull images from a registry that's hosted in the cluster. But it's fun, so here we go. I use a DigitalOcean load balancer to get HTTP traffic into my cluster. (This is because the IP addresses of Kubernetes nodes aren't stable on DigitalOcean, so there is really no way to convince the average browser to direct traffic to a node with any predictable SLA.) I configured the load balancer to use the PROXY protocol to inform my HTTP proxy of the user's IP address. (I don't use HTTP load balancing because I want HTTP/2 and I manage my own letsencrypt certificates with cert-manager, which is not possible with their HTTP load balancer. So I have to terminate TLS inside my cluster.) Of course, the load balancer does not apply the PROXY protocol when the request comes from inside the cluster (but the connection does come from the load balancer's IP). Obviously you don't really want internal traffic going out to the load balancer, but registry images contain the DNS name of the registry in their own names. The solution, of course, is split-horizon DNS. (They should seriously consider renaming "split-horizon DNS" to "production outage DNS", FWIW.) That is all very easy to set up with coredns. It is easy to make registry.jrock.us resolve to A 104.248.110.88 outside of the cluster, and to make it resolve to CNAME registry.docker-registry.svc.cluster.local. inside the cluster. But! Of course Kubernetes does not use cluster DNS for container pulls, it uses node DNS. Since I am on managed Kubernetes, I cannot control what DNS server the node uses. So the DNS lookup for my registry has to go through public DNS. I created an additional load balancer, for $5/month, that is only for the registry. That does not have the PROXY protocol enabled, so when someone DoS's my registry, I have no way of knowing who's doing it. But at least I can "docker push" to that DNS name and my cluster can pull from it. This is all fine and nice until you make a rookie mistake, like building a custom image of your front proxy and storing it inside your own registry. What happens when DigitalOcean shuts off every node in your cluster simultaneously? Eventually the nodes come back on and want to start containers. But your frontend proxy's image is stored in the registry, and to pull something from your registry, it has to be running. This results in your cluster serving no traffic for several hours until you happen to notice what happened and fix it. (I do have monitoring for this stuff, but I don't look at it often enough.)
And that's why I have 99.375% availability over the lifetime of my personal cluster. And why smart people do not self-host their own docker registry.
But do the images have to be co-located with their registry?
Can't the images be somewhere else, and the registry replicated among the nodes, so any node can find its image through the registry and fetch from that location?
For me, the hardest thing about Docker was running my own registries. Or rather, configuring credentials so Docker would use them. Not to mention the hassle of doing that through Tor.
So maybe Bocker isn't so picky about registries.
"Bob¹*, unless we've solely staffed the organization with folks from coder camps a lot of the folks here should be able to carve out a couple of namespaces in the kernel. That's not interesting and that's not why we asked CoreOS to come in today. Let's talk about the actual problems they're trying to solve."
<3 <3 <3 <3
That being said, it's great that folks continue to dig in to decompose the tooling and show what's actually happening behind the scenes.
¹Bob was definitely not that guy's name.
EDIT: Added note of context appreciating the work by the author.
Once you have that then you want to deploy it in whatever way you like it. Nixpkgs has functions to for example generate a docker image that contains only your app + essential dependencies. You could deploy it using nix package manager as you would install a typical app in the OS. You could also describe configuration of NixOS that has your application included and it could generate an image of it.
Community also came up with other generators [1].
The advantage of Docker is that you can verify the container works locally as part of the build process rather than finding out it is broken due to some missing dep after a deployment. If you can verify that the image works then the mechanism for fetching the deps can be as scrappy as you like. Docker moves the dependency challenge from deployment-time to build-time.
I ask because I read your comment as saying “the advantage of Docker is that it uses (explanation of what containers are)” and the parent comment as saying “all I want from Docker is (explanation of what containers are)” and I am confused why (a) y’all are not just saying “containers” but rather “the part of docker that packages up my network of scripts so I can think about it like a statically linked binary” and (b) why you think this is a competitive advantage over other things you might have instead recommended here (Buildah, Makisu, BuildKit, img, Bazel, FTL, Ansible Container, Metaparticle... I am sure there are at least a dozen) to satisfy the parent comment’s needs.
Is there really any container ecosystem which has write-an-image-but-you-can’t-run-it-locally semantics? How do you finally run that image?
Again, Bazel is basically this already. But it would be nice to have something like OP's tool to integrate in other build systems.
I could just make a Dockerfile and say that's my build system. But then I'm stuck with Docker. The only way to run my program would be through Docker. Docker doesn't have a monopoly on the idea of a fully-realized chroot.
My build server is x64, but target output is ARM. Can't exactly just run that locally super easily. Perhaps somebody has created a container runtime that will detect this, and automatically spin up a qemu container, running an arm host image, and communicate my container run request (and image) to that emulated system, but I haven't heard of that feature. (Not that I actually looked for it.)
https://www.mgasch.com/post/scratch/
Typically a minimal Alpine distro image will allow you to pull in deps however you want (either via package manager, manual download, or copy), run a build, and then copy only the artifact over to a scratch image for a final image that's only a few MB in size.
https://medium.com/@chemidy/create-the-smallest-and-secured-...
I wonder.... is there a service (Maybe a chrome extension) that lets you ask questions on the page you are in? For example, I want to highlight:
`btrfs-progs` and ask... "What is a quick summary about this package?
`ship a new enough version of util-linux` and ask.... "What features in the new util-linux allows this to work?"
Then maybe someone who also visits this page with more knowledge can answer my questions.
This tool would augment my learning 10x and I would be a paying customer. Does something like this exist?
As an example, WikiWikiWeb (http://wiki.c2.com/) has integration with it. I've never used it, but it seems quite powerful.
Just chroot the damn thing if you need to and keep it simple.