Yes, Docker is weird. We already have a process management thing - it is called an operating system. But processes are misbehaved sometimes. They are not configurable enough, what if two processes want to listen on port 80? What if two processes want to save stuff at /var/abc.txt? And so on. In this case Docker might have a point. Otherwise it is just saysadmin's lazyness.
Hi, I'm the creator of Docker and came across this post. It's always fun to see other engineers think about how you designed a system. I haven't been involved in developing Docker in many years, but it's a fun trip down memory lane.<p>I'm happy to answer any questions you may have.
I'm a super fan of docker and I also want to say thanks for designing it.<p>I think docker is not weird, it is very linear.<p>Docker has the merit to take a bunch of tools and to create an organized view of it.<p>I want to point you to Misterio <a href="https://github.com/daitangio/misterio" rel="nofollow">https://github.com/daitangio/misterio</a>
which is a very thin layer on top of docker compose.<p>It simplify my homelab and works like a charm, and it is a waaaaay easier to use than k8s.<p>Thank you again, and let me know if you plan a trip in Milan :) for a meeting
I was in the audience when you gave the 5-minute docker lightning talk at PyCon US Santa Clara in 2013. I remember chatting with a friend/colleague about it (<a href="https://nvie.com/about/" rel="nofollow">https://nvie.com/about/</a>) and we both agreed it was the most interesting lightning talk that day.<p>What’s funny, though, is that since it was “just” a lightning talk, it didn’t even make it into the roundup of notes I sent to my team after PyCon. But a mere year later, Docker was how my team (and seemingly everyone else) ran projects locally.<p>Any interesting memories from that day in 2013? From your perspective, what happened in the year that followed that caused docker to be adopted so widely? Were there other key moments or turning points?
> <i>Any interesting memories from that day in 2013?</i><p>That day is forever engraved in my memory... Off the top of my head:<p>I signed up for a lightning talk expecting an audience of 10-20 people, for a confidential demo of our unfinished project that we had so far only showed in 1-1 demos. Imagine my surprise when I learned Pycon does lightning talks on the main stage!<p>The previous speaker didn't show, so I started early. In the recording you can hear me joke that perhaps I should get his time allocation too - the MC was not amused.<p>I went over time and had to speedtalk through the end.. The MC once again was not amused and practically shoved me off stage :-D<p>We had a small sponsor booth at the even, where our small marketing team was prepared to pitch our product (DotCloud) but was thoroughly confused when a horde of people showed up after the talk, to ask about "Docker" - which as far as they knew was the founder's side project.<p>I drove down to Santa Clara on my newly acquired motorcycle - my very first trip on the freeway. I remember telling myself, "today is the day to take all the risks!"
Whenever I am anxious about a presentation, a motorcycle ride to the presentation usually puts everything in perspective.
I agree with this take, even not riding as much as I'd like these days.<p>I had a pretty much near death motorcycle accident I happened to mostly walk away from which really made me restructure my perspective on things I'm afraid of.<p>It also managed to make my then to be wife realize she really couldn't live without me when I sent her a photo of a mangled bike and the text "ouchies", so that accident really changed my life positively and radically.<p>Although I'm still sad it destroyed my OG Surface Pro. It was a maxed out launch model with the year of the dragon touch cover I bought at a Microsoft store at a mall that doesn't even exist anymore. Worn in a messenger bag on my back, and ended up like a crazy twisted piece of metal in the end.<p>So yeah. Motorcycles. They'll change your life.
I was there as well, and while I was really impressed; I was also weirdly weirded out that this wasn’t a bigger deal to all the folks in attendance. And so that made me doubt that what I saw was that impressive, as surely other folks in the audience would know better than I would.
That literally was history in the making. Much respect.
How much have you ridden since that day? Any new bikes?
now imagine what the guy who invented AI must've thought on his first motorcycle ride back from work
The Video in Question: <a href="https://www.youtube.com/watch?v=wW9CAH9nSLs" rel="nofollow">https://www.youtube.com/watch?v=wW9CAH9nSLs</a>
This is wild to see. I remember how exciting this was when I eventually learned about this tech. To see it minimized to a five minute surprise intro like this and then shuffled off stage is amazing. Thanks for sharing the video in this context.
Thanks for sharing this, a really interesting piece of history. It’s always nice to look back at the beginnings of great technology that powers the modern world. Also, thank you, Solomon!
The recording of that lightning talk session is at <a href="https://pyvideo.org/pycon-us-2013/friday-evening-lightning-talks.html" rel="nofollow">https://pyvideo.org/pycon-us-2013/friday-evening-lightning-t...</a>. I was there too and was among those who didn't get it immediately. I do recall more and some mentions of that talk during conversations through the remainder of PyCon though.
As a backend developer, I am hopelessly grateful for docker and containerization in general. The old days with stateful application servers were AWFUL.
I'm a big fan of docker and mainly just want to say thanks for bringing it about.<p>I remember my first time trying to use a container was about 2015 on a beach cafe's wifi in Bocas del Toro, Panama. You can imagine how it went...<p>After a brief hiatus though I was back to it and since then it's been a core part of many a local dev stack and even production stack (compose) I've set up. I recall the magic moment for me being when I first realised you could mount src to use all your local native dev tools while completely virtualising everything else, including and especially whatever combo of runtimes and dependencies you need.<p>It was just a lightbulb moment, like it entirely solves 'works on my machine', setting new people up on a project, it just seems like how software engineering ought to work and once you have experienced it it's difficult to go back.<p>I'm curious, as its creator are you still using it, or as someone who can clearly look ahead to experimental ways of doing things are you on to the next thing whatever that may be? If so, what is it? :-)
Thank you for sharing that!<p>Yes, I still use Docker. Although my way of using it has changed over time, like many others I assume.<p>My new project, Dagger, although it doesn't directly compete with Docker, does implement its own container runtime and orchestrator (for CI pipelines), and we recently added compatibility with Dockerfiles and Docker Compose files... So increasingly I find myself using Dagger instead of Docker, in the context of my CI pipelines.<p>On the other hand, I use docker compose on almost every personal project - like a minecraft server for my kids, home automation, AI hacks, etc. These days I just let my AI agent set it up for me, though :)
Love Dagger! Not sure how I missed the connection here until now.<p>“You’re overpaying for CI” (<a href="https://www.youtube.com/watch?v=tsH3eTo2GLI" rel="nofollow">https://www.youtube.com/watch?v=tsH3eTo2GLI</a>) from KubeCon 2024 seems especially pertinent these days with AI.<p>Was one of my favorite talks that year and really made Dagger click for me.
I'll check out Dagger, sounds interesting.<p>Yeah I've really been enjoying using AI to write docker/compose config and related ad hoc scripts. It was all pretty understandable anyway, but now you can just set up whatever you can think of in literally minutes, even if you just want a particular configuration as a one off. It's a great era for devops!
> <i>does implement its own container runtime</i><p>I take it vito talked you into adopting Garden? </injoke>
I’m curious if your background gave you experience with other operating systems, such as TandemOS?
Thank you for inventing Docker, it truly changed the life of many developers.<p>I was there when dotCloud announced Docker in 2013 and it was truly pragmatic. I had previously burned my hands on LXC, Juju Charms and Vagrant to containerize the apps, but it was all a house of cards. I remember helping a friend ship his whole Vagrant Box to the interview panel for a job!<p>It’s incredible to think about how much boilerplate Docker removed right at it's launch. Thank you.
Hi Solomon,<p>Docker completely changed my life. When I started using it in 2014, I really appreciated how well it solved certain problems I had for web development.<p>It spawned a near endless stream of contract work and video courses for about 10 years, along with being introduced to the Docker captain's program early on. Met so many great people and had a chance to visit a few countries around the world through Docker.<p>It's one of those pieces of tech that has followed me around for half my career and will likely continue until the end. It's the best community I've ever been a part of.
In my opinion, Docker is probably the defining computer technology of the 2010s.<p>I know that containerization on Unix-like systems didn't begin with Docker, but I definitely think Docker was the first accessible interface for it.<p>I think app containerization is something that has so many benefits and it's the obvious correct approach for its use cases once you wrap your head around it. This was already understood at big tech companies pre-Docker (e.g. Borg, Tupperware, user app sandboxing on iOS and Android), but I think it really took something like docker to make it mainstream.<p>As far as I'm concerned, you can probably consider yourself like the Ken Thompson or Dennis Ritchie of your era in terms of the impacts of your contribution.
Since we're reminiscing, I was working for Engine Yard when Docker was released. I remember engineering and product leadership huddled around a desk wondering aloud whether we needed to do something about it.<p>In retrospect, of course, it was earth-shattering for the company, despite a valiant effort. The entire expertise of deploying long lived Linux servers and carefully shepherding them through change management with Chef became a relic to most developers. Totally changed the way applications were deployed.<p>Was an exciting time!
Hi, question from a sysadmin / network engineer. Why localhost with port forwarding? Why not native mechanism like routing and mdns? I’ve gave Docker and other container managers which do networking the same way a try a few times and I always found the network unnecessarily complicated. Eventually I came across OrbStack which uses the aforementioned mechanisms. Every container gets an IP address in the local bridge and responds to mdsns queries. This plays especially well in “compose” scenario when services on containers can all use original port numbers. And containers can be accessed with hostnames, so there won’t be conflict between port numbers especially if I run multiple composed stacks.
I definitely enjoy learning other people's opinions on things I didn't realize I had an opinion on until I learned there was something to opine about.<p>To me the arbitrarily complex docker networking makes perfect sense. Especially in a compose setup. I want my containers to be able to talk to each other, but I don't want them on my local network or even accessible (sometimes) from the local machine. The various internal networks offer isolation of containers from the rest of the network stack. If I have a rails app in a docker compose configuration with PG, Redis, Elasticsearch, etc, in a development environment, most of the time I don't want the service/accessory containers anywhere near anything other than the app's container. And if I want several compose stacks to work together, I just put them on the same named network. I apologize if I misunderstood your point.
I'm curious what made think of it in the first place? What was your thought process that made you think that these Linux primitives give the opportunity to make it a platform for distributing and deploying packaged applications and eliminating a lot of the issue around "it works my machine" argument?<p>You may have already answered this somewhere, so feel free to tell me what to search for or if you have a link to hand, that works too :)
So you are responsible for my career and the reason i can put food on my table. Thank you.<p>People are underestimating now big of a tech shift it was back in the day.
Thank you.<p>For one, did you get rich beyond all comprehension and did you start a band with your wealth?<p>Second, do you still program ?<p>I was lucky enough to get in this industry when Docker was new. Sure beats trying to figure out why X happens on machine A and doesn’t on machine B.
I did make a bunch of money with Docker, something I am eternally grateful for.<p>I did not start a band, but I did build a nice house, help my family etc.<p>I still program everyday, working on my second startup, <a href="https://dagger.io" rel="nofollow">https://dagger.io</a> (please forgive the plug). We have a very active discord if you want to come say hi.
I work heavily with CI/CD. From a quick glance Dagger looks very promising and I might experiment with it this weekend.<p>I guess my follow up question is once you’re financially independent, what continues to motivate you?<p>Is it fun?<p>Do you feel like you’re creating tools that the industry needs.<p>I imagine if I ever get rich I’d work on music and small games.<p>Video games that you buy once and get to play forever, self host, etc. With a full open source commitment within 5 years or so. I’d probably create a game studio in a lower cost of living country though.
If you do try Dagger, please join our Discord and tell us how it goes! There's a very friendly and active community of CI/CD nerds, who will be happy to help.<p>We actually use the same Discord server for community and private team communications. So we are literally there all the time.
Commenting to be able to find your CI/CD project when back at my desk.
You can favorite messages, then check them out from your profile page just like you check on your previously posted messages.<p>Hit on a message's permalink (which is the "X hours ago" link), and in there you'll find the action to Favorite it.
>I did make a bunch of money with Docker<p>Shortly before this (the weekend after you secured YC funding, IIRC), I['m almost certain I] met you in downtown Oakland at Saagar & Tiffany's /r/bayarea meetup [0] – won't go into further details, other than <i>I was one of their co-conspirators</i> =P<p>My point of writing this is dualfold:<p>1) Thank you for sharing your design – I literally just installed my first Docker module (last week) and am floored at all the problems Docker might help me solve (I am not employed in tech)<p>2) My recollections of you, this decade+ later, was of a humble young man (we're the same age) that didn't know what else to do with his newfound techfame (and money) than keep'on keepin'on.<p>After watching your Docker Debut video, I'm fairly certain it WAS you: we chatted about dirtbikes (and just what the hell you were going to do now that you "had money" – then <i>such a foreign concept to us both</i>)... if this wasn't you it still seems to echo in your mannerisms/tact/approach. May your humbleness and cleverness prevail!<p>[0] It might have been at Gustafson's NYE party (I was the guy remorselessly conjuringbitches; "Volcano"); we had a mutual friend at MalwareBytes?
How’s dagger’s k8s and/or rust story?
We are working on making Rust builds much faster, and easier to distribute on a cluster.<p>When self-hosting Dagger, you can run it on Kubernetes. Beyond that, we don't use Kubernetes at all ourselves.
Given all the popularity and use cases you know today. Is there any fundamental design choice you would have done differently?
I remember going to a demo of Docker in South Carolina before it hit 1.0. Came back and wrote the “Docker is the Heroku Killer” article on my blog and it was the first thing I wrote that made the front page of HN.
Why did you make compose silently rewrite firewalls?
Docker ended up as a primary way of delivering, packaging applications etc., for the web and beyond.<p>What was your imagined use case when you first came up with it?<p>Did you think Docker as it is used in the industry right now is where you imagined it would be used?<p>Any use cases for it that the industry missed but you think would have made things even better?
I appreciate what docker did in pushing a more accessible UX on top of containerization and getting people to think more about reproducible setups and sandboxing. Its popularity was definitely one of the catalysts in that direction.<p>I'm curious if when you were originally designing it, what tradeoffs you chose between, for example did you consider a non-daemonized design or was it daemonized from the beginning?<p>Having had some time now and also seeing how other people have riffed off of the idea and refined it, what would you have done differently? If you have a retrospective at some point already, I'd be interested to read it.<p>I have some accumulation of personal architectural guidelines that I built up from trial-and-error + reading others' experience and reflecting on how their design could've affected something I made. As a result, I really value those kinds of discussions about tradeoffs.
What made you decide to use a URI as the namespace for images? I like it, but I think it's been very misunderstood which has caused people to dislike it.
I was inspired by Go's use of URI as a namespace for user packages, and short names for the standard library. I thought it was an elegant way to allow everyone to host anywhere, and dodge a lot of complicated namespacing issues.<p>One design principle that was very important to me, was portability and avoiding fragmentation. I wanted every image name to have the same meaning in every engine, so that when writing a Dockerfile, you could have confidence that it would actually behave the same on every docker installation. In this we disagreed with other platforms (like Red Hat) who sought to "embrace and extend" Docker by changing the meaning of short names. We always fought this to avoid fragmentation of the platform. This did not make sense from Red Hat's perspective, since <i>they</i> were the platform - who cared about fragmenting Docker? That led to some negativity which is probably what you're remembering.<p>At the same time early Docker users wanted the ability to host their own images without being forced to use our central registry. Using Go's system solved both problems at once.
Thank you for taking the time to reply. Yes, it was the short names and the way people were trying to run local mirrors that I remember.<p>I personally never use the short names and have really come to like your solution. I host my own registry and I can glance at a build or compose file and immediately know if I’m depending on any external resources that I shouldn’t be.<p>I originally disliked it, but it’s been my favorite namespace solution for a long time now.
Did it though? The amount of grief I've had because `foo/bar` gets silently expanded to `docker.io/foo/bar` is extensive.
Any regrets about the namespacing or things you’d do differently with it now looking back?
My only regret is that so many users had to run local docker registries on each node of their cluster, then write `FROM localhost:1234/myimage` in all their Dockerfiles - all to avoid unnecessary re-fetching of remote images. My goal was to make image distribution a native feature of the cluster, so that you wouldn't have to choose between portable Dockerfiles and proper image caching. But Kubernetes ended up dominating the cluster layer, and as far as design goes, we were not invited to that table. So as far as I know, the problem was never solved, at least universally for all Docker users.
I've been actively using Docker for most of my projects over the past few years and I sincerely thank you for brainstorming and getting it out in the market.<p>The sole idea of containerising an application, its utils and dependencies all into one container is a real big deal in early 2010s. The product has been so visionary that it has been re-pivoted as secure sandboxes which is most needed right now. Kudos!
The main primitives that underlie Docker were originally intended to facilitate security and isolation. Docker's innovation was combining filesystem-in-a-box with those security primitives, and delivering all those capabilities with highly intelligible UX. That's not meant to minimize; I think those are monumental (and monumentally impactful) achievements. But there was no "re-pivot" to secure sandbox isolation; that's what things like cgroups and namespaces were created for!
Not really a question, but just saying "hi!". You might not remember this, but in 2012 I was about 13 years old, interested in computers, and had no one to really talk to about them. By some miracle my father (who is in no way in tech!) found some connections to YC and organized for us to come out to California to see a bunch of companies. dotCloud was one such company, I still have the t-shirt! I remember chatting with you and you taught me how to use pip, it's a fond memory I look back on often.
The weirdest part of docker, to me, is that it was setup as a client/server system. Why was that? Podman for quite some time didn't support it.<p>Was it all for the `docker.sock`?
Would you consider writing Docker/moby in a different language, if you were to create it scratch today?
Oh gosh, the choice of language is such a context-specific design decision. The first versions of what became Docker were written in Python. The choice of Go was a mix of nerdy excitement ("it's like the best of Python and C!"), and adoption strategy: back then devops tools were segmented by language runtime: ruby, python or Java mostly. Shipping a compiled binary allowed us to be adopted by all tribes.<p>None of these things can be transposed today, so I guess I can't answer...<p>For what it's worth, my current project (dagger) is written in Go.
I interviewed Solomon about the Go history (plus some others) for this talk <a href="https://www.infoq.com/presentations/languages-cloud-native/" rel="nofollow">https://www.infoq.com/presentations/languages-cloud-native/</a><p>Actually there are some longer unedited versions I might release.
That's a good answer that effectively rebuts the article's claim that Go was a bad choice imo.
The article's point that Go is a bad fit for some of the low-level interactions with the kernel, is absolutely correct though. We had to do a lot of juggling to get it to work properly. But in the end it was fine. I would say it was the correct choice of language at the time, and it certainly contributed to Docker's early success.<p>Another explicit goal was to facilitate contribution. We thought Go syntax was "vanilla" enough to attract a broader set of contributors than a more niche, opinionated language like Erlang, Haskell, Clojure etc. I think that also worked out well - Docker was known for attracting many contributors, many of them making their very first open source contributions. We even ran special meetups to help people become contributors, that was fun.
I think that's so true and it was one of the keys to success of the project. I contributed the very first simplistic implementation of referencing linked containers by name. I never would have bothered if the project was written in C or C++ (I'm more than capable, I just don't enjoy torturing myself). Go made it MUCH easier for a fly-by-night contributor such as myself to join the party.
This is the coolest set of contributions to HN this month, most likely.<p>Thank you.
Were you around for the big Moby open sourcing? What went down from your perspective? If I recall, it was a fairly dramatic move that was not driven by the interests of Docker corp.
Yes, I was around for that. It was one of my skunkworks projects, as I had lost formal authority over engineering and product by then, and mostly used my "founder aura" to convince small pockets of people within the company to build cool things with me.<p>However Moby was a poor choice for a skunkworks project, it involved mostly communications and project management, which requires consistency and scale. Overall it was poorly executed because I failed to build enough support internally ("Solomon's at it again, let him do his thing"). Here I am trying to explain it on Twitter after the keynote, using a picture of a hand-drawn diagram, because nobody in marketing or product was assigned to help. <a href="https://x.com/solomonstre/status/855918630915133440" rel="nofollow">https://x.com/solomonstre/status/855918630915133440</a><p>I think the goal of Moby was fundamentally correct: we were trying to replicate the Red Hat model, with well-scoped upstream components (linux -> runc, containerd..) integrated into a commercial product (Docker -> RHEL), with a faster-moving community project in between (Fedora -> Moby).<p>This was a way for us to clarify that Docker was a <i>product</i>, with a community of users, and Moby was an <i>open source project</i>, with a community of contributors. This clarity was very much needed, because different communities were projecting very different expectations on the brand "Docker", and these expectations conflicted with each other.<p>In a way, Moby aspired to be what CNCF ended up becoming - the "big tent" where the broader community meets to hammer out the general shape of the container stack. It seems obvious now that a single company can't be the sole authority over such a vast scope. But in the first years of Docker, we really did have that level of influence, because we literally invented the market, and brought the community together in meetups and an ever-growing Dockercon. It's only when Google and Red Hat pushed Kubernetes and CNCF, that our influence over the stack started to wane. Maybe it was for the better, I don't know if we would have been up to the task as designers and engineers. But at least there would have been a consistent design, with a Linus Torvalds figure willing and able to say "no" to stupid and redundant features. For a while I played that role - but then I was replaced by SIGs and committees.
> I'm happy to answer any questions you may have.<p>Why doesn't docker respect unix filesystem permissions? I use docker on a shared server, i can delete docker images of other users. This is bonkers.<p>Is it a defect of a particular docker setup (following standard instructions on ubuntu), or it's an intrinsic feature of docker itself?
The docker daemon runs as root by default which IMHO is a security issue on machines with multiple users. For those machines, consider a rootless docker set up where each user runs their own docker daemon. (This is a supported configuration.)<p>All of the above applies to Linux, ymmv on other OSes
><i>Why doesn't docker respect unix filesystem permissions? I use docker on a shared server, i can delete docker images of other users. This is bonkers.</i><p>Same reason a Postgres root can delete tables of other users.<p>It could, but it would be a shim on top of Docker to respect them.<p>Docker is a service daemon running as root, and the images of other users are just entries created by the other users in its registry, not server files that have permissions of each user.<p>When you're creating a new docker image, you just send a command to that daemon process - you're not passing your user account credentials to create. As far as docker is concerned, it's just one more image it knows, not an image belonging to you specifically.
having access to the docker daemon is equivalent to root
Back in 2012 we used to give talks about how we ran all our CI builds in LXC containers, that came about because a bunch of us came from the BSD / Solaris world of jails and it just felt natural.<p>The folks at infracoders / DevOps meetups would think we were a bit "out there", then what do you know - 2013 rolls around and we quickly started to shift to Docker (too early some might say), but not long after shifting from LXC to Docker it seemed many others finally started to come round to containerisation.<p>Fast forward to 2026 and I've recently done some work with a client who is only just "getting into containers" (a Windows shop).<p>Thanks for your early work to bring better containerisation to Linux Solomon. It's funny to think we're 13 years from Dockers release. Time flies.
I was a dotcloud customer around 2012. You might have responded to one of my many support emails.
Ha ha, thank you for your trusting us back then! Hopefully it was a good experience? Scaling reliably on AWS was not so simple back then...
Haha, well, let’s say the experience motivated me to learn how to run nginx and uwsgi on my own :)<p>(And as a result that, with ansible, continues to be my preferred way to deploy while the rest of the world passed me by…)
Digital meet cute right here!
You're actually the coding GOAT btw.
General question. When you were designing Docker, did you anticipate the success it would achieve?
To give a sense of time: Docker launched in 2013, but it was one of many iterations of the same project, which I had been working on continuously since 2008. Over those 5 years, virtually nobody cared or understood what the hell I was working on. I lived in France and had no connection to the tech industry.<p>So, not only did I not anticipate this kind of success, I did not even have a reference frame for what success might even look like. All I knew was, I had an itch that I had to scratch, and I had nothing better to do :)
I remember in 2013 the first time someone showed me Docker [im in Mexico]. My first thought is that we already had Vagrant for setting up and running virtual machines through console.<p>I didnt get it at that time haha.
In those years in the systems group I was working in at a fortune 500, we were very interested in this type of technology. Mostly using Solaris Zones and cgroups and trying to do this ourselves with limited results.<p>When Docker came out it solved so many issues we were having. Thank you for scratching that itch.
Was it always called Docker? Do you think the branding played a larger role in success than you would have expected?
I believe Docker was always called Docker, but it grew directly out of the previous generation of the technology used by dotCloud (the company Solomon founded), which was using LXC with AUFS.<p>I think the breakthrough with Docker was bundling the AUFS-based image layer format with a centralized container image sharing registry. This was revolutionary at the time. But another huge element of success was Solomon and others evangelizing the technology relentlessly at meetups and conferences. I distinctly remember attending a demo in 2012 where the crowd was very excited to see the Docker workflow that we now take for granted, in large part because Solomon was so good at presenting it. At the time, I was working at a cloud PaaS company where we developed a similar technology on top of LXC and BTRFS (but no image registry). Docker really made me think hard about what we were doing, although I didn't end up making any moves.<p><a href="https://jpetazzo.github.io/2017/02/24/from-dotcloud-to-docker/" rel="nofollow">https://jpetazzo.github.io/2017/02/24/from-dotcloud-to-docke...</a>
You are correct :)<p>> <i>the previous generation of the technology used by dotCloud [...], which was using LXC with AUFS</i><p>One small note, the earliest versions (2007-2011) were based on vserver then openvz, which predated lxc. Back then you had to patch the kernel to get container primitives. And since virtualization also required patches (eg. Xen), we had to carefully combine both sets of patches, which was poorly supported because nobody else was crazy enough to stack 2 kinds of virtualization!
It used to be dotCloud iirc
Given how things have changed since your creation and the way things are going, are there any things you would have done differently?
There are many. But there is an alternative universe where I remained CEO instead of transitioning to CTO, and continued pursuing my product vision obsessively instead of compromising on it because of lack of self-confidence and a desire to be loved. I think I would have avoided a lot of the mistakes that the company made - but on the other hand, I would have made a fresh set of mistakes instead, so who knows what the outcome would have been!
Thanks for making Docker :)<p>Prior to the creation of Docker, did you have experience with other containerization technologies like Solaris Zones and FreeBSD Jails?<p>Did you at some point, either prior to or after making Docker for Linux, consider building something like Docker on top of FreeBSD Jails?<p>As a user of both Linux and FreeBSD, running Docker containers and Jails on each of them respectively, it would be interesting to see what FreeBSD Jails could be with something like Docker built on top of it while also taking advantage of other features on FreeBSD like fully using ZFS snapshots, ZFS send/recv, ZFS clone, vnet, and so on. Such that spinning up a container would under the hood receive ZFS snapshots from the “Docker registry” equivalent server, and it might clone the snapshot locally before starting up a container instance so that multiple container instances would be using the same locally available ZFS snapshot that was received once from the “Docker registry” equivalent.
Thank you for docker.<p>Went from the good old days of vagrant (xen/kvm) to lxc/lxd to docker, and docker truly clicked all the way from development to production.<p>But honestly, thanks to Docker hub even more. The CLI is only one part of the puzzle, the worldwide registry is an immense undertaking.
I’d love to hear more about some limitations/tradeoffs of docker that you made at the time that you regret in hindsight. Was there anything that you wish didn’t get baked into the “default norms” for containers, or areas that would benefit from more attention and redesigns?<p>I’ve been following dagger and it’s been really interesting to see the evolution of the design, and new set of abstractions. There’s also nix which has seen popularity, with their approach of building layered oci containers.
I hope one day I can say something like “I made Docker” :,)
How did MirageOS end up powering parts of Docker stack?
We acquired a small team of Cambridge-based computer science & systems engineering wizards, called Unikernel. We then worked together to apply systems engineering to improving and expanding Docker in various ways.<p>The most successful project that we worked on together was "project Piñata" which later became Docker for Mac. It turns out bundling a Linux VM in a native Mac app, and integrating it into the host filesystem, networking stack etc requires lots of magic..<p>Now, most of the Unikernel team were very active OCaml developers, and created MirageOS among other ocaml projects. While working on Piñata, they simply reached for the tools they were most familiar with.
(Unikernel cofounder here)<p>When acquiring our company, Solomon took us to a remote farm in France for a week for an offsite, fed us fantastic food and wine, and the first prototype of that Docker for Mac VM was working by the end of the week! It took a few months to hack together the shell. There's a video of Solomon and the pinãta launch party on my blog ;-) <a href="https://anil.recoil.org/notes/cacm-docker-cover#getting-involved-in-docker" rel="nofollow">https://anil.recoil.org/notes/cacm-docker-cover#getting-invo...</a><p>There was a whole other slice of work we did for project Piñata too in the form of datakit (<a href="https://github.com/moby/datakit" rel="nofollow">https://github.com/moby/datakit</a>) that was well ahead of its time. I was looking at this archived code again just last week while thinking about agentic git workflows!
(Joining the reunion thread) I was just explaining to a new starter yesterday why Docker Desktop used the codename "pinata". Also I reckon some of the more advanced ideas from back then are still relevant today, probably even more now that everything is changing (or can be changed) with agents. Hope all is well!
Thanks for making so many lives easier!<p>Docker is probably the highest-profile software written in Go. Are you happy with that choice? Would you do it in Rust if it was available at the time, or Zug?
Hi Solomon! Great product. How do you feel about the need for a central registry and not a p2p approach for distributing images? I always felt like p2p was the better and more scalable approach. Any reason why you decided on the centralized approach?
Love docker, it changed the development ecosystems for the better.<p>In recent years I have shifted over to Podman, primarily because it defaults to rootless without a daemon.<p>Is that something you considered for docker early on , and if so why did you decide on running as root?
Thanks for your innovation and helping developers! If Docker hasn't been your focus in recent years, what have you mainly been working on and what's been your favorite?
Thanks for developing such a valuable tool!
Thank you for making it :)
How does it feel to have fundamentally changed how many/most enterprise software runs?
I feel grateful for having seen from the inside one of those rare "hypergrowth" moments, it's a terrifying and exhausting experience but I would do it all over again without hesitation.<p>I also feel lucky that people are still using my work, that it endures without me, and that it generates (mostly) positive reactions. There was a time where Docker had a lot of haters, which was hard on me. But with time I've noticed that the negativity gets mostly washed away, and what remains is positive interactions like the ones in this whole thread. So now Docker is this cool experience I share with lots of people around the world, and when we meet we get to talk about this shared interest. I love it.
A while back you had this tweet which often gets cited, or at least _i_ personally think about it a lot.<p>> If WASM+WASI existed in 2008, we wouldn't have needed to created Docker. That's how important it is. Webassembly on the server is the future of computing. A standardized system interface was the missing link. Let's hope WASI is up to the task!<p>How are you feeling about WASI today?
Not related to the topic but. Do you have any book recommendations? Not necessarily programming or system related, looking for great books ~
basically my whole career has revolved around being good with docker and other related tech, so thank you! started on 0.7 :D
Legend, thank you!
Do you think e.g. students learning docker syntax at a uni is beneficial in 2026 or you think LLM-assisted programming means that Docker will become an abstraction under an abstraction and its setup will be mostly automated by LLMs? I find myself very rarely debugging or handwriting dockerfiles nowadays!
This is a strange question because you could learn Dockerfile syntax in a single night. There are only 18 directives, and the average Dockerfile uses like 6 of them. 90%+ of Dockerfiles is just "run this shell command" and "copy this file into the docker image". The only time it flirts with complexity is multi-stage Dockerfiles, but 90%+ of Dockerfiles are a single stage.<p><a href="https://docs.docker.com/reference/dockerfile/" rel="nofollow">https://docs.docker.com/reference/dockerfile/</a>
> The only time it flirts with complexity is multi-stage Dockerfiles, but 90%+ of Dockerfiles are a single stage.<p>And multi stage builds are just a directed graph short hand for having separate intermediate dockerfiles. There’s nothing special about them either.<p>If I had to pick one thing that is tricky for someone new to docker to understand, it’s how the filesystem state is cached using the previous state, the env, and the raw command text.
Indeed, the one mistake I keep seeing new people make when writing Dockerfiles is writing them in a way that doesn't optimize for caching. For example, they'll copy their code into the container first and then start installing packages and dependencies. It's an easy mistake to make because the end result is still a functional Dockerfile, they're just wasting time and stressing the poor package servers unnecessarily.
Or multi-container compose files with atypical networking, or troubleshooting daemon permission issues.<p>Docker is much more than memorising a handful of Dockerfile directives.
I think the key thing for a university student is to get the big ideas down: what is a container exactly, how does it work, how does it differ from a VM, what assumptions does it make about what you're running (and how do you run something that doesn't fit that pattern), why do images exist in layers and how are layers implemented, what are the performance benefits/tradeoffs, etc. etc.<p>When I was learning Docker I can't tell you how many people would describe it to me by analogy to a standardized shipping container, and start going off about shipping container dimensions and supersized cargo ships and trucks and railcars... and finish by smiling beatifically, like they had just explained the whole thing in a masterstroke. Let's... uh... not do that. :-D<p>In a problem set, the student might learn a bit about dockerfiles or docker-compose.yml... but only, I think, so they can try building and running a container of their own!
If you're going to fully delegate something so trivial as Dockerfiles to slopmachines, why go to university at all? You don't need to learn anything if you delegate everything to the slopmachine.
I'm gonna be real with you. No one needs to know docker syntax. Most engineers just copy and paste chunks of Dockerfiles around anyways.<p>Docker syntax is one of those things that just immediately falls out of my head when I close the editor. I don't care about it at all.<p>Even better: there are many, many tools that build OCI images without using the Docker syntax. I haven't hand-written a Dockerfile in at least six years.<p>LLMs have not loved the needle here in my sphere, it was already bouncing off of the zero on the gauge.<p>edit: this isn't to say the syntax is good or bad (though there are several questionable parts of it) but extremely simple, and concise enough that you can just look up literally any command with great ease. It's surely a large part of its success, for better or for worse.
I like to tell people the story of how I got a pre-release peek and frankly didn't understand what I was looking at. You emailed me in reply to a comment I made around that time[0].<p>Funny how little has changed except the names, I guess.<p>[0] <a href="https://news.ycombinator.com/item?id=5347255">https://news.ycombinator.com/item?id=5347255</a>
Do you feel that docker was done for as of about ten years ago and something better should have replaced it?
If you were implementing an operating system (free from compatibility concerns), what would you do differently to better support lightweight containers?
What learnings did you take from Docker when conceiving Dagger? Or is it more about unlocking BuildKit?
Oh wow, hi! I think my biggest “gripe” with docker is that everyone grabs it as a hammer and views many problems as a nail. Am I way off base with that? What was your original vision for how docker might be used in the wild?
Seems like this thread has become an AMA lmao
[flagged]
[flagged]
Thanks but I still run LXCs /s<p>You're a genius well done making containerization actually happen.
[flagged]
I am firmly convinced that had Rust been more mature at the time, the pivot from Python would have beem into Rust instead of Go.<p>Am I on the right track?
Why?<p>Python and Go are both memory-managed languages. That is perhaps the hardest part of programming (outside of getting the code to do what is intended).<p>Go and Rust are both compiled, but Rust requires the developer to figure out all of the memory management before compilation, which slows down development to a crawl.<p>Almost no company will rationally choose Rust over Go if they know how the development speed tradeoff looks like.
Because Go is a badly designed language that only took off thanks to Docker, and as the article points out, a few C workarounds were anyway required to make it possible in first place.<p>I would have chosen C++, but given that isn't the new darling any longer as in the 1990's, that begs the question of the new kid in town that everyone is now rewriting everything into.
This obsession with Rust is very hard to understand
Yeah but the post criticized Go for a project like Docker, so it makes sense to ask what else could have been used. At the time there weren’t many system languages fit for the purpose.
The obsession isn't with Rust, the obsession is with Go not being a good programming language and the only reason it took off was thanks to Docker.<p>So they would probably never rewrite from Python into C or C++, because not cool, too hard kind of motivation, otherwise they would not have picked Go.<p>So that begs the question, if the obession as you call it, was already a thing back then, would Rust have been the lucky candidate?
It didn't really need Docker to "take off", I'm not even sure if it actually ever did the take off...<p>It's a language with its pros and cons, I like the simplicity, it's a good choice for services that just expose an API/GRPC/etc... and the performances are not that bad.<p>This "but rust is faster" obsession often comes from people that don't even know what they are talking about or are even able to consider if thinking about performance make sense for a specific use cases. Sometimes, or at least it did before LLMs, having something simple to modify was more important that chasing supposedly higher performance because the rust people keep blabbering about it.<p>> would Rust have been the lucky candidate?<p>Probably not, considering that the author give me a "simple solutions are best" vibe.
I generally agree with your comments, but do you really think that a language created by such luminaries as Ken Thompson and Rob Pike and endorsed by Google really needed Docker to "take off"?
Yes, see Plan 9, Alef, Inferno and Limbo, such luminaries as Ken Thompson and Rob Pike aren't always right.<p>As for endorsed by Google, see Dart and Flutter, Android Things, Fuchsia.<p>Now everything combined, plus Docker and Kubernetes, yes it was definitely a factor.
It's not hard to understand. It's just not rational to anyone who actually calculates how performant it is (very fast, I agree) with how long it takes to write.<p>Once I realized how difficult it is to write complex code that actually satisfies the borrow checker, I was perfectly happy with writing somewhat slower code in Go or Python.
Anyone that has written enough systems software in various kinds of languages, using Rust isn't that bad, only when coming from scripting languages.<p>Anyway, I clarified on a sibling comment the reasoning behind my question.
What made Docker unique IMO is not the container technology itself. I used chroot 20 years ago and it worked just fine. Yes, no network namespaces; no process namespaces, but I don't even think these are that important.<p>What made Docker unique were there things:<p>1. Dockerfile concept. Building images layer by layer. Caching layers. Everything in a single file. It made possible to iterate on image quickly. It made possible to implement CI builds efficiently.<p>2. Docker network registry concept. Putting universal images onto a server and share them with the world.<p>3. Momentum. A lot of software that was traditionally complicated to deploy, suddenly appeared in docker servers. I remember how fascinated I was, when I could deploy wordpress website with tiny docker-compose. And how contained it was. I could just delete every trace of it from my host. I always felt uneasy installing various things onto my host and docker just solved that uneasiness.
Interesting, I would probably say more-or-less the exact opposite.<p>The main draw for me was that it made containers <i>absolutely trivial</i>. Sure, you <i>could</i> spend ages figuring out how to DIY some isolation, but in practice an awful lot of people stopped at having Apache fork its workers with a non-root uid. You want isolation and a repeatable setup? Spin up another VM and have Ansible set it up! Docker provided a batteries-included lightweight way to isolate and manage multiple applications at once.<p>Dockerfile? I would've been happy with a Bash script, or handing it a tarball. Caching and fast iteration? Compute is basically free. A single file? Well, there's already a whole bunch of app source code files sitting next to it, so what's a few more in a `setup/` directory? The registry? A shared base could've also been achieved with, say, a `deb` file providing the right dependencies, files, and post-install scripts.<p>I do agree on the momentum, though. Having every piece of software reduced from a multi-page setup guide to a single command and not risk screwing over your entire machine is absolutely magical.
Dockerfiles are completely optional. It's just one way to build images.<p>You can absolutely build images with a bash script, here's an example (its vibe slop, but it works): <a href="https://github.com/andi0b/vibe-todo/blob/main/docker-build.sh" rel="nofollow">https://github.com/andi0b/vibe-todo/blob/main/docker-build.s...</a>
> You can absolutely build images with a bash script, here's an example<p>That script is just calling docker to build layers manually via `docker create`/`docker commit`/`docker run`/etc, using a Dockerfile as a rudimentary DSL over it. It's still building images "the way docker does", but in a more error-prone way.<p>What GP is trying to say with "I would've been happy with a Bash script, or handing it a tarball", is that it ought to support giving it a <i>literal tarball</i>, like you'd get via `make install DESTDIR=./out && tar -czf image.tgz -C ./out .`. Or just tar'ing up the build artifacts of any other existing, competent build systems. There's no need to treat building an image as some "containerized" thing where you have to run inside the bottom layer of the container to build the artifacts.<p>In fact nowadays with the best practice of split container builds, there's no benefit of saying "the container is guaranteed to have the dependencies because it's the container you built with", because in practice nobody wants to ship their runtime containers with an entire build environment in them. So they do one container to do the building, then pick out the artifacts they need and place them in the runtime container. At that point, what's the point of using containers to build again?
You absolutely can do that. Very easily in fact: <a href="https://blog.ttulka.com/building-container-images-without-dockerfile/" rel="nofollow">https://blog.ttulka.com/building-container-images-without-do...</a><p>And for most people, that's a bad idea. Most people don't have to know what RPATH, ldd, multiversion/simlink library discovery, etc are. And even if they did, Dockerfiles give you an easy way to do something you couldn't easily do before: multi-stage builds and a highly robust way to say "drop the parts of my transitive hull that were only relevant at build time". Dockerfile semantics kind of descend naturally from needing the behavior of stages, parallelization, cache keying for image layers, semantic layering (FROM), and making simple use-cases relatively at-a-glance/contained.
Nothing stops you from doing that either.<p>Edit: or is something stopping you from doing it this way? It seems like people just don't like Dockerfiles, but instead of just doing it differently (which is possible, it's just a tar file and a manifest), they keep complaining.
In generally build minimal images file by file with bazel. Fully hermetic.
I agree, that #1 and #2 are what made docker "unique" technologically, but I don't believe Docker they were a docker innovation.<p>Basically both described in <a href="https://www.usenix.org/legacy/event/lisa11/tech/full_papers/Potter.pdf" rel="nofollow">https://www.usenix.org/legacy/event/lisa11/tech/full_papers/...</a> (in detail) and <a href="https://www.usenix.org/conference/usenix-atc-10/apiary-easy-use-desktop-application-fault-containment-commodity-operating" rel="nofollow">https://www.usenix.org/conference/usenix-atc-10/apiary-easy-...</a> (in a "sexy" use case to try and motivate it) a few years prior. (and I get annoyed when people say "so you're saying you invented containers?" because they equate docker with containers. And I'm like no, containers existed for a long time going back to logical partition on mainframes in the late 70s/early 80s. All I claimed was a novel way of building and distributing file systems for them that made them much more useful and valuable and in apiary a novel desktop setup that made use of it to improve desktop security)<p>Even the original docker implementation of using a union fs (docker using aufs) was the exact same as described.<p>Even if docker came up with it independently (though conferences like LISA and Usenix ATC are where the papers were presented and were where companies like dotcloud/docker would advertise their wares (and in fact docker inc was an exhibitor there, so it wasn't hidden), the differences between the uniqueness of docker and what is described in the paper are minor (in my perhaps somewhat biased opinion of course), and i was clearly first.
The momentum, I think, matters a lot more than the other two. Makefiles already allowed you to build layered things with caching. Artifact repositories have also long been a thing.<p>But the argument I used for advocating Docker in environments where people were not fans of it was that the Linux container had become the de facto standard unit of deployment. There is so much tooling written under that assumption, and if you want to use any of that tooling, you need to package your deployments as Linux containers, even if you want nothing to do with Docker otherwise. That's why it had so much momentum.<p>Then a fourth point I think you're missing is that the concepts used by Docker are relatively simple. Before I understood what Linux containers were, I used to think things like, "Why would I care about Docker when I can isolate my processes with Linux users, cgroups, namespaces, etc." What I didn't know at that time is that "Linux users, cgroups, namespaces, etc." is exactly the thing Docker was giving a friendly UI to.
It hit a social need more than a technical one it seems.
I see less and less of a need for Docker when running simple linux hosts and building with terraform \ ansible. For any codebase with dep management it is great and I still prefer building code through Docker but that's about all I use it for.
I prefer Podman most of the time, but Docker is/was amazing and a great DX put on top of the so called "5 different linux kernel features in trenchcoat". That's the selling point, it's super lightweight and takes full advantage of the OS features that were already there (or being developed) but were awkward to use and required tons of specialized knowledge.
Always nice to see someone demystifying a complex thing by learning the building blocks it's made from.<p>Knowing this, you might find rootless Podman's fork-exec method of starting containers to be more sensible. I certainly do. No root, no daemon, no socket.<p>If you want to learn more about the Linux Kernel namespaces which work together to make a container, this LWN series is really good: <a href="https://lwn.net/Articles/531114/" rel="nofollow">https://lwn.net/Articles/531114/</a>
> Docker’s container runtime, runc, is written in Go.<p>I worked at Docker from 2014-2019. The most important part is actually written in C.<p>[I wrote a whole comment here about to explain how the hack works because I was too fixated on how technically incorrect "written in Go" is. Then I went back to read the rest of the article only to see that the paragraph immediately after this kind of explains it in its own way! Let that be a lesson to always finish reading the article before posting about it.]
Not to contradict anything you wrote, but if you look at the language stats for <a href="https://github.com/opencontainers/runc" rel="nofollow">https://github.com/opencontainers/runc</a>, it has 68.5% Go, 27.1% Shell and 3.5% C, so it's fair to say that it was "written in Go", even though the most important part was C - same as e.g. Doom was written in C, even though it used assembly for optimizing the performance-sensitive parts.
True! there are lots of layers of abstraction written around that core `nsenter` piece of libcontainer. I just take issue with the "Go is kind of a terrible language for a container runtime" claim made by the OP. The maintainers' choice to use an expressive high-level language for most of the codebase is a practical one, I think. They also knew when it was not the right tool for the job and when to pull out the C bindings or how to work-around issues with forking the process. The OP mentions this, but for fork/re-exec helpers in the engine, this is where it lives now: [1]. I specifically remember needing to use something like this for the `docker-untar` helper during image pulls (I worked primarily on the container image filesystem-setup part of Docker) so that extraction of the image layer archives could be done in a chroot with fewer privileges. It was a security-sensitive part of the docker daemon and previously there were all sorts of malicious ways that a container image could be built so that contents are extracted _outside_ of the place they should be. This is the "images are just folders" part of OP's article. Another part I find funny is the "Containers really aren’t real". I think the best part of this is that when you use docker to "create" a container (`docker container create`), it mostly just creates the container's rootfs directory (it's actually multiple directories combined using an Overlay Filesystem) and its configuration file. The container doesn't actually "exist" until the process starts which is a separate command (`docker container start`) because Docker doesn't actually instantiate the namespaces or launch the container task until start time (and generally in Linux, namespaces are tied to living processes unless explicitly held open via bind mounts or another process reading a `/proc` file).<p>[1] <a href="https://github.com/moby/sys/tree/main/reexec" rel="nofollow">https://github.com/moby/sys/tree/main/reexec</a>
Hi Josh!
Every statement in the article make me ask: "what's weird about it?"<p>Everything in that list feel natural when you know how things evolves over many years. Maybe it is just me getting older and less curious.
And not a single mention of the actual weird decision, a client / server model which complicates permission management by at least two orders of magnitude.
I’d argue in 2013, the client / server model is what made docker a success. It allowed for a seamless, and mostly identical, experience for docker on Mac, Windows and Linux for one. It met developers where they were, daily-ing a Mac or a Windows and deploying on Linux headless servers. It had benefit on its native Linux system too that took all the alternative solutions another 8 or 9 years for the entire Linux ecosystem to develop enough solutions around containers to make a daemon unnecessary while still offering docker DX.
Oh yes docker-machine was quite good. You can create a machine on a Mac by using VMware, VirtualBox, or using the cloud such as EC2. Then your docker CLI can work with all of these machines seamlessly without knowing any details about the machine.
That's actually a design decision made to work around the limitation of having to run as root. Since the container had to be started as a privileged user, if you want non-privileged users to be able to start contianers you either need a setuid binary or a client/server interface like docker has. There are pros and cons to each of those options.<p>Now it's possible to create containers without elevated privileges (assuming user namespaces are allowed), but that wasn't possible until long after docker had established the client/server model.
lxc never had a daemon but Canonical added one (lxd in 2015) and lxc forked it to incus to be community managed.<p>rkt (2013) was CoreOS's alternative to Docker and was daemon-less and failed.<p>Podman came along relatively late (2018) and benefited from a lot of Linux kernel and systemd improvements since Docker was designed.<p>So while arguably the client/server model is outdated for container management tools, I'm not sure it's weird. This is my workstation for example:<p><pre><code> schmichael@fedora:~$ ps -e -o comm= | rg 'd$' | wc -l
67
</code></pre>
Daemons are maybe the least weird paradigm you can choose for a Unix program.
Yeah, the daemon is the real problem with Docker.
This is why I prefer Podman.
A lot of people start using Docker as a black box and have the mental model of a VM, and when they start digging into the internals all the "weirdness" starts to exhibit itself.
Most of them don't seem that weird to me. Except the use of go. It definitely seems strange to pick a language that can't natively call clone, one of the most important syscalls for using namespaces and implementing containers.
Poke around in bocker[1]. For technical people, it makes the same points the article makes in a way that's very clear.<p>[1] "Docker implemented in around 100 lines of bash"
<a href="https://github.com/p8952/bocker" rel="nofollow">https://github.com/p8952/bocker</a>
Lots of positive stuff in this thread which I won't bother repeating. Instead, I'll add a few ambivalent points:<p>- Today, a lot of functionality still in Docker has been upstreamed into the (Linux) kernel, so containers can be much simpler (and rootless). Docker is still carrying around some of that cruft, which is what makes it slower and heavier than Podman.<p>- As a devex technology, Docker/containers have been massively successful, but not as infrastructure. Containers never became secure enough to run multitenant workloads without some other form of isolation, so they ended up being redundant with KVM (or gVisor, or a similar second layer) in production a lot of the time.<p>That second contradiction led to lots of inefficiency. For example, on Google App Engine, for years when you ran a deploy it would create a VM just to run a single container.
I would also point to no secrets primitive.<p>K8s requires some sort of tool to have any hope of storing secrets in a way that isn't trivallly findable from the rest of the cluster.<p>But, perhaps I am being too harsh, its not like there are secrets primitives in linux that are easily deployable to namespaces/cgroups.
I created Range (for fun). No daemon. No root.<p>A few cool tricks:<p>`range shell python:3.12` - opens a shell image without pulling the entire image.<p>`range shell ubuntu --commands` - you are in Ubuntu. Type any command Ubuntu doesn't have and it comes from the image that has it. On the fly.<p>`range run --network none ubuntu` - network-isolated sandbox<p>range run ebs://snap-... -- cat /etc/os-release - opens an EBS snapshot with no EC2 instance<p>Another cool trick:<p>`range run python:3.12 --mount hf://moonshotai/Kimi-K2-Instruct:/model -- du -sh /model` says 959G instantly :)<p>Check it out here - <a href="https://getrange.sh" rel="nofollow">https://getrange.sh</a><p>Most importantly, Range doesn't need any daemon, any container runtime, any registry or any image conversion. One binary only. On a Mac it boots its own tiny Linux VM per session, and on Linux it uses KVM.
> I decided to make my own container runtime for fun [...] Unlike VMs, containers are just processes<p>Try to make your own VM runtime next, you might be surprised!
I started hating Docker after seeing all the cargo culting on Reddit. Whenever someone asks about deploying an app on Linux, there's always at least one comment saying, Just use Docker. We finally ended up building our own deployment automation tool for our entire stack that doesn't use Docker at all.
That comment invariably comes up because for most people it’s the objectively correct and most well supported option. If you’re asking redditors how to deploy something, you’re precisely the person docker is for.
Even when I'm not using Docker to deploy something, I'm _probably_ using oci images at the least, but I'm generally running my local dev stack with Docker compose. Not always, but I use it in a lot of projects.
That part about the threading was a huge source of issues back in the early days. Goroutines could hop threads and it's the threads namespace/cgroup configuration that gets inherited when forking..<p>One of the gnarliest issues I recall was where network namespaces could occasionally not be cleaned up correctly. So "randomly" (but more likely under certain loads) the networking of a reused thread would get jacked and Docker could no longer pull images.
Plus Go's function for locking a goroutine to an OS thread was broken to the point where you could not safely rely on it for quite a while.
Never, ever, ever, write your own userland threading library.<p>(rule broken by almost every language in common use, unfortunately)
It worked out pretty well for Go. Nothing else besides Erlang cracked the parallelism UX/runtime-performance code as well as Go did, and it didn't have the drawbacks of Erlang.<p>> rule broken by almost every language in common use<p>I don't think so. Go/Erlang/Java do break it (Java very recently). C/C++/Rust/C#/JavaScript/Ruby/Python/Perl/TCL don't break it. PHP ... sort of breaks it, (IMO they just hide cooperative nonparallel concurrency in a nice API, but I'm not well-informed on php)?
That’s an absurd statement. Optimizing every language around what a runc-like program would need is absurd.
Where does this advice come from? Most web servers would use a lot more resources if they didn't use userland threading, wouldn't they?
This advice comes from threads on Linux being second-class citizens. As TFA itself states, there are some syscalls that really should only be made in a single-threaded process which is frankly <i>insane</i>... but that's the legacy of starting with the processes-only model and patching it years later to have threads as well.
I think you're confusing userland threading (also known as green threads) with a regular thread pool implementation (that uses regular OS threads).<p>Because most web servers use OS threads. Nginx, Apache, litespeed, they all spin up `core count` threads but they can all work single threaded just fine as well.
No, I mean that Tokio, Go, etc., were built with general-purpose web servers in mind, and they decided that lightweight threads were necessary for that purpose because OS threads had too much overhead to be used per-request.<p>NGINX uses a state machine per task, which as far as I know is kind of what Rust's async functions end up desugaring to.
Tokio's not a lightweight thread/green thread system. It's an event loop, just like Javascript's, optionally with a fixed number of threads running work underneath.<p>For Go: you're likely right that OS thread overhead was the main reason for Goroutines, but I don't think it was the only one. There is also a ton of ergonomic efficiency to be had via green threads; like async/await, they're kind of a syntactic unlock that allows you to very liberally use goroutines/channels as a means of <i>semantically modelling</i> actors/state/data flow in your program, where doing that with regular OS threads is both dangerous and (given the start/stop overhead of threads on lots of other platforms) feels like kind of using a howitzer for a flyswatter. Golang saying "yeah, create a million of these, we don't care, it's 4 machine instructions per to start one" was pretty liberating for a lot of people.<p>The goroutine architecture also unlocked some nice performance at the OS level: GC latency improvements became easier, and some IO multiplexing efficiency <i>a la</i> epoll became almost free to implement due to the ability to cheaply move and suspend goroutines.
> Tokio's not a lightweight thread/green thread system<p>It's not green threads (and maybe not lightweight threads; there are so many names for things that may or may not be considered the same...) in the sense of stackful coroutines, but either way, it's a userspace implementation of multitasking on top of a smaller number of OS threads, which is the part that's relevant to my question.
IMO packaging is the best part of the Docker ecosystem and what really made container workloads take off
I worked at one of the early "container companies"; and wrote large parts of an in house mostly docker-compatible container engine. It was going to be part of a container orchestration platform pre-k8s and docker swarm.<p>This guy is totally correct. We also used Go for everything -- as it was hot stuff at the time -- and also very frustrating to deal with early version. Dependency management nightmares, bugs in the runtime, etc.<p>He also had to have a C shim that got loaded first, or shelled out to.<p>The hype around Google tools was pretty fascinating. I felt like that was the primary reason around using such an immature language at the time. There were better systems languages around for that kind of work.
Docker and containers are amazing. They definitely have their caveats, whether that is security, bloat, you name it. But the fact that I can produce an artifact and have it run pretty much anywhere without much overhead is amazing.<p>For me firecracker has mostly taken over most of my hosting needs, as i can actually take a docker image and unpack it into a firecracker image, and still have a slim process (vm), with great performance, though with a bit extra bloat, but now also have a secure workload that I've got better control over.<p>Docker and docker compose however, is still the core of my development workflow, and has been for many years, in my eyes, docker compose is the best we've got for simple composition of various services.
From the bits that I've looked into, the namespace, cgroup and filesystem tricks seemed relatively easy to understand - but there seems to be a whole lot of highly specific networking configuration going on (including lots of IPTables rules) that I couldn't make sense of yet.<p>Is there any writeup about those, or why they are there? Is this just to separate the different "networks" in a compose setup, or is there more going on?
To solve the networking setup, typically some sort of "slirp" is needed. Slirp on one hand takes (fake or real) packets from <i>somewhere</i> and then on the other side pass it to a normal Linux process that does CONNECT / BIND / SEND / RECV.<p>It turns out you can do all the packet processing magic (connection tracking, syn handling, etc) in userspace totally fine, and then indeed hand it over this to userspace syscalls.<p>Being upset with classic C-based slirp and rust smoltcp (not enough features) I've dug up Fuchsia userspace tcp/ip stack - netstack - and wrapped it in slirp a-like envelope.<p><a href="https://github.com/cloudflare/slirpnetstack" rel="nofollow">https://github.com/cloudflare/slirpnetstack</a><p>So this beast is basically that - on one hand you pass it packets (potentially from inside container) on the other hand it does connect/bind/etc to host OS.<p>This approach, in one form or another, is used by tailscale, podman and many other container runtimes.
> There’s not really a linux feature that’s just “containers” either. Instead, containers are really 5 different linux kernel features in trenchcoat.<p>Well said. At some point i was toying with doing a http server that will containerize itself on top of the directory it's serving and put it on the back burner because the list of features needed seemed never ending.
Docker is great. I entered into the post-Docker era (mid 2010s) and it is amazing how much sense it makes to imagine Docker as like a single task “mini computer”. I appreciate the insights of this article a ton: I feel after getting used to Docker, we take it for granted, but it’s great to see how someone junior to it would react.
A good talk on the tech behind containers.<p>Containers From Scratch • Liz Rice • GOTO 2018<p><a href="https://www.youtube.com/watch?v=8fi7uSYlOdc" rel="nofollow">https://www.youtube.com/watch?v=8fi7uSYlOdc</a>
Thank you for writing this up! For years I’ve been thinking of Docker as “some VM magic”, and in fact, I could have asked and know more in 5 minutes :)
I am a huge Docker fan! I would reiterate what several commenters have said already that it had a huge impact on my career. My question is relatively pedestrian compared to what others have asked already. I absolutely loved the "adjective-scientist/nerd" container names Docker generates. In fact, that is one of my most favorite things about Docker. How did that come about and who chose those combinations?
I'm glad you enjoyed that! We wanted a way to make container names reasonably unique and reasonably memorable by a human, so this was a fun way to do it. I picked the original combinations, then over time it became a ritual for contributors to propose fun new values.<p>There's a fun little easter egg: the combination of "Steve Wozniak" and "Boring" is explicitly forbidden, because Steve Wozniak is not boring :) <a href="https://github.com/moby/moby/pull/4902" rel="nofollow">https://github.com/moby/moby/pull/4902</a>
Thank you for Docker.<p>>>Containers aren’t real<p>To me a Docker container is less like a sealed box and more like a 'beam' of processes running through a set of isolation boundaries.
> And if you know where to look, you can even find that process in /proc.<p>This is very important for debugging! Not just <i>that</i> process, but the processes running in that Docker can be found in /proc.<p>Why this is useful is that you can run <i>gdb</i> outside of that docker and point it to a process in the docker, including setting the file system root to the docker one, so that it gdb reads the correct objects from the correct paths, to get the right symbols and addresses.
I have recently discovered INCUS, very nice alternative to docker when a simple container is not sufficient <a href="https://linuxcontainers.org/incus/" rel="nofollow">https://linuxcontainers.org/incus/</a>
Please don't make scaling the font size with page width a standard thing.
Interesting read, I run Gitlab on Docker at home. Thanks for the breakdown of the Linux features behind it. I never knew what was underneath
Interesting read! Thanks.<p>Though it would be better if it compared Dockers ways to say Podman, which does things a little different I think.<p>For others, like me:<p>Footgun:<p><i>A footgun is a programming or system design term for a feature, tool, or API that makes it very easy for a user or developer to shoot themselves in the foot—meaning it causes self-inflicted damage or severe errors while working exactly as intended.</i>
When Docker came out, I was a heavy user of OpenVZ.<p>My bash build scripts looked like Dockerfiles.<p>Most of the container code in Linux came from those russian guys.<p>Took me 6 months to find out the difference between stateless and stateful containers, after Jerome Petazzoni published a blog post opposing the usage of an SSH server inside containers.
To know that container technology is weird you only have to type "mount" (without arguments) on a modern Linux system. A whole list of leaking abstractions right in your face.
If you're old enough to remember some techniques that people used before docker (like chroot(2)-ing daemons for security), the "containers aren't real" observations are not really new info. When containers came on the scene it felt like an outgrowth or evolution of that technique, which was extremely crude and simple.
Yes, Docker is weird when we had Plan9 for 20 years already before Docker was created.
Docker question. Who prefers docker for local dev vs. run the thing directly. I usually prefer run the thing for debugging and hot reloading. Sure: build the containers and test them in CI. Dependencies like PG sure run in containers as they change less often and you save the install.
Run the thing directly. Doing everything with Docker is what leads people to build bloated images with dev dependencies in them like test runners, dev servers etc. Too many people think containers are some magical thing but you can usually get exactly the same isolation using more specific dev tools. For example, in Python we've had virtualenvs forever and now tools like uv make it easier than ever to do the right thing. A docker image is just an artifact that you build for deployment to container-based platforms like Kubernetes.
some people do all of their software development in a container. It really only works well if you are comfortable using TUIs instead of desktop apps though.
This only scratches the tip of the iceberg. People's minds are blown when they realize Linux has no concept of a container.<p>It's not a vm: It's all namespaces, baby! Unshare one or more of your mnt, pid, net, ipc, uts, user, cgroup, or time namespaces and you have a "container".
This is a better way to understand it: we can think of a container as an isolated process. When deploying containers, having a clear understanding of the boundaries between containers and the host machine in terms of permissions, resources, and data is extremely helpful for troubleshooting issues.
Today, I would definitely choose rust over go. And I lament that so much container software uses go rather than rust. But back when docker started rust was a lot less mature and probably wouldn't have been a good choice.
C was and is a good choice for that kind of software. I don't understand the prevalence of Go in these tools.
Easy: far few footguns.<p>Performance is basically irrelevant because you're not really interacting with the running application. You're running as root, so security-critical. You're talking to the internet for things like fetching images. You need rather complicated business logic to deal with all the possible options, protocols, and file formats.<p>Sure, you <i>could</i> do it in C, but dealing with dependencies is a major PITA and you're permanently one <i>tiny</i> mistake away from getting pwned, while not needing any of C's strengths. Go is safe, easy to write, and ships as a single batteries-included binary: what's not to like?
Go has grown too, since 1.25 it knows it’s in a container, uses all cores on CPU for go routines without hiccup.
That isn't really relevant for the tool starting the container. The biggest problem with go here is that it can't natively perform the operations necessary to set up a container, due to the nature of the runtime, so it has to resort to complicated workarounds like a shim in c, and starting spawning from /proc/self/exe instead of forking/cloning.
CTRL+F "rust"
I can't use Docker locally only because lack of enough space on my SSD.
Oh man, what a fun thing to do! I may have to replace what used to be my fascination with programming languages and compilers with virtualization or containerization now.
dokku is built on docker and dokku is the cat's meow. thank you :)
> Go is kind of a terrible language for a container runtime<p>I love Go and use it for everything I can but will absolutely concede this point. It's clearly <i>possible</i> to write the most successful container runtimes on earth in Go, but you absolutely have to fight the language/runtime sometimes. Since containers are based on processes, handing off a container spec to a minimal rust runtime seems like what we should all be doing by now. crun has just proven good enough that AFAIK no one has RIIR.
Just use Podman
For as "terrible of a language" Go is alleged to be for a container runtime, its not like crun or youki are exactly faster in many meaningful ways unless you count churning containers running true and exiting.<p>And implying the system kernel still has to run the container kinda ignores kata containers and gvisor runtimes.
It's about using go to develop container runtime being terrible and not that "if it was C it would be faster". OS runs the container, docker just does the setup and some managmenent.
For me it's not about the cpu time, but the memory. If you spin up hundreds of containers the docker overhead becomes very real.
> Next up: Databases are weird<p>> Did you know that databases are just a file?<p>oOoOoOoOo<p>Mostly joking. It's cool to see tech demystified, but I feel like a lot of things we use and take for granted are like this.
Docker does not need root.<p>Side note almost nothing about Docker is weird. This article chooses rather boring design decisions and picks on them.
> Unlike metal servers, VMs are just operating systems being gaslit by a hypervisor. Your actual CPU is still executing those instructions! And if you know where to look, yyou can even read the other VMs’ memory in L1D
Agree!
interesting read as a relatively less experienced developer.
Honestly it took me so long to pick up containerisation because of how it's marketed. "Orchestrate a zillion fake computers, ultralight VMs, livestock not pets" big whoop.<p>"It's an idempotent language for OS level dependencies so you can be sure <i>exactly</i> what is running on your server"<p>Gimme gimme gimme!
Docker hasn't required root for 7 years, I wish people would stop repeating that. It uses a root daemon by default because it makes things easier. Also, Containers are only as fake as a "Desktop" in an OS, which isn't real either. It's a user, network & process namespace with a control bus and a bunch of other weird things. A Desktop is a Container with a GUI.<p>Other weird facts about OSes: a filesystem is a database, the Linux kernel is a monolithic program, "hidden" dot-files were a Unix bug that got carried forward, deleting a file doesn't remove the file from your machine, virtual memory is a lie, your computer can't run multiple programs at once (it's just running one at a time real fast), in 12 years most systems will crash due to one number getting too big, you technically never need to reboot because you can launch a different version of Linux while already running Linux, you can freeze a program to a file and then later resume running that same program in the same state (but nobody uses it), files aren't actually stored in directories, there's a maximum number of files (and size of file) on most filesystems (which you can use to lock up a machine, despite file quotas existing and nobody using them), you can lock up most systems by forking too many times / using too much RAM / accessing disk too much, there's a default number of open files and/or TCP ports which is artificially low and you can use to again lock up a machine, pipes are just two file descriptors connected to one memory buffer, an IP address is just one long number split up into bytes, etc.
The rootless Docker experience used to be pretty bad and it was less friction to use something that was rootless by default (like Podman). Has this changed?
it changed and its better now.
rootless dockerd wants newuidmap/newgidmap + subuid range before it start, and cgroups only work with cgroup v2 + systemd.
also, on a host that already has those, its fine on one without systemd, and podman is still less friction, mostly because there is no daemon to babysit
[flagged]
> your computer can't run multiple programs at once (it's just running one at a time real fast)<p>Of course it can.
This list is from back in the day pre-multi-core, multi-CPU computers
Give them a break, machines with multiple CPU cores have only been around for 40ish years!
One of my deeply unpopular opinions is that Docker only exists because Linux as a bad operating system that is incapable of deploying Docker. I have not once worked on a project where “we’ll solve this with Docker!” didn’t result in never ending Docker fixes and workarounds and hacks.<p>This is not a slight on Docker itself. It’s a slight on the conditions that induced Docker to exist.<p>One of the great selling points of one of my projects is “this is easy to run without needing Docker”.
> docker requires root!<p>Podman has not required root in years, just saying.
[flagged]
[flagged]
[flagged]
[flagged]
[flagged]
[dead]
>>Images are just folders that Docker puts somewhere and then calls chroot (or pivot_root) to make that folder your container process’s new root directory.<p>And folders are graphical representations of directories--sometimes, not always--and not directories themselves. When will the newbies get this?
The high level abstraction is more important than the low level implementation unless the low level implementation is leaking through, or there is a significant advantage conveyed by understanding the low level implementation.<p>I know a lot about how http works, and it comes in handy, but I can understand how juniors get away with not knowing it as fully as I do.
Directory is a bad metaphor too.