Hacker News new | past | comments | ask | show | jobs | submit login
Dev onboarding, then and now (fahhem.com)
42 points by fahhem on Dec 17, 2023 | hide | past | favorite | 70 comments



I don't see how replacing the "it works on my machine" with "it works in this VM" is much better. It is the same problem.

You just added the overhead of running another whole computer in your computer to solve it.

Also the author states he is locked into using VS Code, which seems like a risky dependency to have.


> I don't see how replacing the "it works on my machine" with "it works in this VM" is much better. It is the same problem.

I can run a VM on both my machine and yours.

> You just added the overhead of running another whole computer in your computer to solve it.

A VM hasn't had the overhead of running a full computer in a long time. Depending on your platform, containers (or hyper-V) are near-native performance. And let's be real, when your dev environment is spending 45 minutes running eslint, a 1-2% overhead isn't going to make or break you.

> Also the author states he is locked into using VS Code, which seems like a risky dependency to have.

Lockin isn't a binary bad thing. Flexibility isn't free. Supporting every possible workflow in every possible environment ends up with catering lowest common denominator, which sucks. If VSCode dies, I'll move onto a replacement, just like I did when we (thankfully) decided eclipse was to go to the farm.


> I don't see how replacing the "it works on my machine" with "it works in this VM" is much better. It is the same problem.

It's not that. It's replacing "it works on my machine and I'm not sure why it doesn't on yours" with "follow these exact steps and it will work on your machine too".


Except when it doesn't, because not all problems are caused by the machine's configuration, and software that displays the "it works on..." feature tend to break due to the most diverse and uncontrollable causes.


If a large portion of the machine's configuration is managed rigorously the software will only break for novel "uncontrollable causes" outside this boundary, requiring learning and permanent process improvement without wasting time fixing the same issues repeatedly: an ideally efficient situation, not a problem.


Software should be robust to most uncontrollable causes. Not fail due to small changes.

It's perfectly reasonable to use containers to solve dependency management. But it's a really bad form to have containers as the only viable way to distribute your software, and a very reliable indicator that your software won't work at all.


> I don't see how replacing the "it works on my machine" with "it works in this VM" is much better. It is the same problem.

I can ship the VM to a thousand people. I can't do the same with my machine.


You can ship a list of your dependencies too.

In my experience, VM centric deployment processes lead to extremely brittle programs.

But I mean, ye, if you got a brittle mess, you better use VMs for deployment. I am not against using that method, as long as I gotta admit I've made a mess.


The problem is that my dependencies depend on OS libraries, which then depend on my OS, which means I have to ship my OS, which... is what I'm doing.


Binary dependencies are the issue. I find it pretty silly that C has 50 years and the deployment story is such a mess that we have multi billion dollar businesses basically just to tame it


What are you talking about? A list of dependencies is less brittle than having a fully fledged env that is ready to go? In what world?

Even if you use hard locked versions of deps there is a whole multiverse of problems you can encounter when compared to having everything ready to go that is identical to your expectations.


> A list of dependencies is less brittle than having a fully fledged env that is ready to go? In what world?

The program is being made less brittle because it is tested in different environments and the practical max amount of dependencies are lower than shipping a custom distro for your program.

I am not arguing that for a given program, it is less likely to execute properly in a shipped and tested VM image, than on a Sparc workstation running Solaris.


So you're arguing something else entirely, gotcha.

> The program is being made less brittle because it is tested in different environments and the practical max amount of dependencies are lower than shipping a custom distro for your program.

If we're talking about web (which is my assumption since images don't make a lot of sense otherwise) there is exactly 0 benefits to testing apps in different environments since they're only going to be deployed in one, right? And either way if that changes you can specifically test for any other envs you want to run your app in, and not let your developers take that pain onto them by fighting deps/configurations along the way.

Either way it's painfully obvious why one is better than the other.


Because unless your entire environment set up procedure is reproducible from top to bottom, something can break along the way. Whereas if you are already shipping a VM (or a container image, which on Linux is much lighter than a VM) you are really only relying on the VM runtime, everything else will work automatically if the VM runtime is working. It's only one thing that can break, only one thing you need to figure out how to fix in order to get the system working, instead of 1000 unknown and unknowable things. And if you're using some kind of hosted solution, you're literally paying for a working VM runtime.


How did people ever got anything done before the era of vms and curling bash scripts from the internet?


Slowly and with frustration.


Not understanding why something doesn't work on other machines could eventually bite you in the ass. Masking a potential failure mode rarely leads to good outcomes.


I understand why something doesn't work: They have an incompatible version of some dependency.


Man sometimes I wonder if people on HN post "stupid" stuff on purpose. OP doesn't see how having something contained in a file (image) and something contained in 3D space (computer) are different just because one is run as a layer on top of another. Sure.


Container, not VM. Containers are relatively lightweight compared to VMs (definitely not "another whole computer"), and they share the Linux kernel with the host.


Except in Mac/windows where they run in a VM, though it's true that that kernel is shared, so it's still lighter than separate VMs if you're running several.


There's a kernel of truth here, which is that "It works in <whatever>" is still just an ad hoc thing when what is really desired is first principles understanding and control over the project dependencies.

But the justification gets muddled. In fact there is no VM in docker and no "another whole computer". Containers are lightweight and great. Even if you have a correctly-engineered bullet-proof hermetic build solution for your bitwise reproducible artifacts... you almost certainly want to implement that using container technology of some form.

Use Docker. It's great. Do the hard work too, sure. But start with an ad hoc Dockerfile.


> there is no VM in docker

There is as soon as you run containers on a different OS (IOW as soon as it's not Linux containers on Linux or Windows containers on Windows)


Yeah yeah, I know. Nonetheless few people are doing hermetic build setups natively on OS X, it's just not part of the Xcode culture. The advice given was clearly for backend development on Linux (sure, plausibly other systems, but let's be honest, all backend deployment is done on Linux at this point and that will be true for the rest of eternity. Solved problems are solved).


I would disagree, tons of people out there develop backend code targeting Linux but do so on macOS machines.

That said, this was not a particular jab at your comment, more like a clarification for readers, as a lot of people are somehow under the belief that Docker for Mac involves no VM (the other belief being that containers themselves are somehow lightweight VMs)


We transitioned one of our repos to devcontainers and that did lock us into VSC (though in theory I think pycharm supports now, it does not successfully build from the same file). Based on how that went, we will not be transitioning our other projects.

It’s been… ok. Devcontianers are a great idea, but the implementation is rough around the edges at times. There is a complex story around making sure your dependencies are appropriately synced. If you want any test reliability, you need to rebuild the container in CI/CD before running tests, which isn’t impossibly complex but isn’t out of the box and can require additional work and really thinking through things at times. While the deduplicated dockerfile multi-stage flow of dev -> test -> prod images works, I’ve found it to take a nontrivial amount of work and background to get this up and running.

There also is the git integration, which is functional but flaky. First, you have to use VSC’s terminal rather than your console. Which I have found is not an issue for junior devs that just do what they’re told, but the crusty seniors who are used to it not mattering which terminal you use seem to find a lot of headache here.

It will occasionally randomly not find the ssh keys git needs and fail to authenticate, and the only fix I’ve found is to open a new terminal outside of VSC and git push (or any other remote authenticated operation), which somehow reenables VSC’s SSH compatibility. Which of course may also fail if you have pre-commits in place that rely on the dev container env having pre-commit installed.

There is also a bit of complexity around bind mounts in general, I can’t recall specifics but we have had some compatibility issues related to this that are difficult lot debug, as there is some magic that VSC seems to do behind the scenes that you can’t replicate outside of VSC. We also had some issues multi-architecture targeting that was made more complex by this setup.

Overall, devcontianers are fine and they will work in most cases, but they are not panacea. They basically take all of the distributed frustration of each user’s individual setup and consolidate that frustration and headache onto your tech/devops lead etc. This is, of course, by design. Solve it once, for everyone. But you don’t magically have less edge cases. And of course the dev and CI/CD setup becomes entirely magic to anyone not involved in configuring it in detail. So when issues pop up, I’ve found devs to be less able to unblock themselves without getting the lead involved.


Seems like you got bit by VS Code, which is why I avoided that dep too. Try devpod.sh, it's independent, has a cli that's working great for me, and you can 'ssh' into the container from your terminal so you don't need VS Code's terminal


> I don't see how replacing the "it works on my machine" with "it works in this VM" is much better. It is the same problem

I do. I no longer need to pollute my machine with thousands of crappy dev packages that I need only to compile next special snowflake.


> You just added the overhead of running another whole computer in your computer to solve it.

Yeah? And? Containers are an easy way of solving the problem of getting a known configuration for everything from the OS on up. You are wasting time and money not taking advantage of that.

> Also the author states he is locked into using VS Code,

You're a professional. Use what your coworkers are using (75% of professional devs are using Visual Studio Code). If you have Vim muscle memory, that can be accommodated quite well with extensions. Otherwise, just fucking switch already, you'll save yourself time and pain.


It's not even remotely true that VS code plus extensions can match my vim muscle memory


Not even the extension that embeds an actual copy of vim?


Is the number really that high? It’s only been recently where I’ve noticed a higher usage of VSCode vs JetBrons in my travels.



If you have a docker file that can reproduce the VM from scratch then that tends to be pretty decent documentation on the requirements. It might still not work on your machine, but at least you have a pretty good idea of where to start to get it to.


Just remember to pin absolutely everything. The amount of times stuff broke or was inconsistent because one machine had a different version of the base image than the other...


I fully agree with you. That said, one thing I've come to hate is the proliferation of version numbers in random dockerfiles and random config files all over the place. It's a pain to know what's out of date and a pain to upgrade it all. I wish there was a single tool to manage it all more simply, something like pnpm for containers plus everything you install inside them.


Nix. It's the best I've seen for this use case so far. I pin the dependencies using flakes and make container images with specific packages I need

It's not 100% perfect for managing exact versions because you update nixpkgs and many packages update as a result, but you can pretty easily pin multiple versions of it or override the version for a specific package


Nix sounds great, unfortunately I never managed to install it reliably.


Author here. I'll try to clarify in the post, but I'm not locked into VS Code, I'm using devpod.sh which is independent of VS Code.


The first issue about the machine being macOS or Windows but the code assuming Linux has never been a problem in my experience. Now containers or Nix do make it easier.

If the system is deployed on Linux then you run Linux in a VM. (Which also deals with some of the other issues) I have done that since the early 2000 or even before we remotely logged in to a machine running the correct OS (X Windows is useful) albeit I was on site so a fast connection to the server.

Now whether it is good design to make assumptions that only Linux matters is another question. I am old enough that I had to use multiple Unix systems SunOS Solaris NeXTStep and Linux. And good practice was to compile C++ with two different compilers as the error messages and edge cases were not very edge.


The hoops people jump through in order to avoid using an operating system that just works in that setting never ceases to surprise me. It was something that started when Macs were popularized among developers and never really stopped.


Depends on what you mean.

If you mean just use Linux then not possible. You need MS Excel for any financial work - the alternatives are just not complete enough, Mail also (well used to) needs the OS. And I suspect most people prefer the GUI of macOS and Windows which do just work.

If you mean why isn't the app written to just work then that is often ignorance of what calls and things are Linux specific - a non GUIO business app should be easily portable;le between macOS and Linux and SunOS etc you don't need low level API calls for that.


What "operating system that just works" can I use to run today my application that I developed eight years ago?


Kind of a long way to say that the author uses Docker for development environments.


Haha, yeah, but I've been using them for years and it's only now getting easier than writing really long scripts over and over again


Containers: Nobody gets the installation right. We give up, let's ship everything!

Nix/Guix: Why? We literally solved this issue 20 years ago.


My favorite quote is: containers and k8s are perfect for shipping poorly architected software that was built to yolo the dependencies and the os configuration it runs on.

In the real world you're going to need to understand what your dependencies are (if only for understanding and closing security holes when they are discovered) and you will be in a world of pain when the yolo approach catches up with you.

I'm not saying to not use containers btw. I think containers are great and can save time when use properly. They are just not the panacea people make them out to be.


With nix, you can't precisely specify versions of all your tooling. You have to choose a channel, and you get whatever that channel gives you. You can't upgrade one tool without upgrading everything else at the same time to whatever version the channel provides. For many dev workflows, that's not enough control.

See https://github.com/NixOS/nixpkgs/issues/93327 (which grew from https://github.com/NixOS/nixpkgs/issues/9682)


That's not strictly true, particularly with flakes. You can easily pin multiple versions of nixpkgs as a flake input. Also it is possible to override the version of a specific derivation


Some painpoints wrt DevPod:

In order to get devpod ssh to work, DevPod injects itself into your host machine (where all the devcontainers run). When you ssh into your devcontainer, devpod's ssh implementation acts as a proxy into the container, allowing you to get an in-container shell without having to run sshd inside the container. But people are already injecting VS Code into remote machines, so maybe this doesn't matter to you.

DevPod's ssh implementation does not handle newlines properly; full-screen displays can get garbled on many terminals. But most DevPod users are using the terminal inside VS Code, which seems to work fine.


Looking at my ssh config, devpod injected a Host and that's it there's nothing extra in the container. Instead, there's a ProxyCommand that runs devpod, which probably ends up in a docker exec somewhere. That's why you're having trouble with newline and larger terminals, I used to as well because the terminal escape codes for resizing weren't getting through to the shell inside the container.

In the past, I had to resize the terminal once manually after execing in, but I think either docker or bash or something in the chain got an update in the past few years that fixed it to automatically work


Not in the container, in the host. If containers are running on your local PC, you'll be fine, but if you're logging in remotely DevPod will inject itself into your remote host. Do a 'ps -aux | less' while ssh'd in to your container sometime and be ready for a surprise.


Ah, I never considered running it remotely. I'm not onboard the 'dev in the cloud' train, mainly because of round trip latency


There's no round trip latency when you use VS Code's remote editing capability.


You're right, though I didn't mean just the editing latency. For web projects, the latency is now between me and some dev server in the cloud vs localhost, and for CLI as well. For GUIs or anything that interacts with my OS (such as "applets") or my hardware devices now I have to download the program to test it.

For web projects, I understand that latency should be considered, but I've learned what's important there and don't want to build/compile/minify my projects in development so I'm wasting time downloading the same MB's of JS over and over when only a few bytes changed so I'm not getting cache hits.


Has anyone faced any challenges integrating these tools with specific IDEs or version control systems? How did you address issues like plugin compatibility or build automation within these environments?


I avoid IDE specific workflows, that's why I'm using devpod. As a result, I can 'ssh' into the container from anywhere, or docker exec, and build automation just gets a 'docker exec' shoved in front of every command


I have found that a nix devshell (with direnv) to be the most miraculous solution to weird such as these.

https://github.com/numtide/devshell


Tbh I've found nix and flakes as remarkable in terms of solving that issue.


This is a solved problem, and the solution is Nix, not Docker


Dev onboarding / dev containers are not a solved problem and Nix alone is insufficient for solving them. Nix also doesn't always work since you are going to be using versions of libraries from nixpkgs instead of the the OS you are targeting. Developers would test against different libraries than end users are using. With the a container or VM you can reproduce exactly the environment the software will run in.


I feel devbox[1] is really good here. And solves the painpoints your addressing. You do not really need to get into the details of nix but get the benefits.

But it do not seems to have gotten the love I feel it deserves from the nix community.

1.https://www.jetpack.io/devbox/docs/quickstart/


Was looking for this one.



You should never run a command you don't understand.

The whole premise of this article is shaky.


Which command do I not understand? Devpod.sh is open source, and while I'm not a master of Go personally I can tell it's basically running docker commands for me. Should I not run docker itself without reading the source code too?


You said dev onboarding was about blindly running a command someone else wrote.


Yes, it is, but I don't think there's a productive world in which new engineers don't onboard by running commands blindly based on a doc somewhere. I just want a world where those commands reliably work with very few host dependencies. With devpod, I think we're close (only 1 dep that's statically built and docker engine)


Again, you shouldn't run commands you don't understand, onboarding or not.

Understand what the command does and why you're told to run it before you run it.


What would you recommend onboarding to a new project entail? Studying thousands of lines of code before doing anything? Should they study containerd or just the docker CLI?




Join us for AI Startup School this June 16-17 in San Francisco!

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

Search: