Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Container2wasm: Convert Containers to WASM Blobs (github.com/ktock)
252 points by api on Jan 3, 2024 | hide | past | favorite | 70 comments


Really impressed by the depth and breadth of this project, well done!

A particularly interesting part is the socket layer inside the browser. Other people solving this problem have previously used a proxy to a server that does the real socket implementation. This means you can't have a "browser-only" solution.

The author has solved this (for HTTP/S only) by proxying HTTP requests and then re-creating them as fetch requests (details here: https://github.com/ktock/container2wasm/tree/main/examples/n...). I'm very interested in using this approach for my own project Runno (https://runno.dev).


That does have some major caveats of course: some headers will be totally ignored by the browser due to web restrictions, some will be added/overridden (e.g. user agent), and CORS will apply (which will seriously surprise most Linux tools!).

Still, very neat, agreed. Almost certainly the best you can do without having some kind of backend proxy running on either the server or the user's own machine.


Shameless self-promotion: https://webvm.io

Powered by a x86->Wasm JIT. Technical writeup: https://labs.leaningtech.com/blog/webvm-server-less-x86-virt...


It's a bit hard to tell, but this isn't open source (well, assuming we all don't consider wasm source :)), right?

I got as far as "powered by cheerpx", which leads me here: https://leaningtech.com/webvm/

And I'm also guessing that you guys just allow free use of the compiled wasm for demos such as this?


Yep! CheerpX's documentation is available here: https://labs.leaningtech.com/cheerpx


Similar project, but open-source: https://github.com/copy/v86


Very nice! Most language playground sites should adopt this approach.


Yup. this is what I use for Yaksha playground (I use v86 though). See -- https://yaksha.pages.dev/


Do any GUI frameworks support WASM?

I've been looking for a way to run GUI applications remotely for a while, specifically on a wlroots compositor. Projects like this (maybe one day) and https://github.com/udevbe/greenfield are interesting since they essentially make access universally accessible.


I'm using Dear ImGui for my cross-platform projects (which includes running in browsers):

- https://floooh.github.io/visual6502remix/

- (start the emulators by clicking the little "UI" icon to get the debugger UI) https://floooh.github.io/tiny8bit/

- (start by clicking the little "UI" icon) https://floooh.github.io/sokol-html5/

Platform abstraction is handled through the sokol headers: https://github.com/floooh/sokol

Dear ImGui is small and fast enough for running in browsers (it will add up to a few hundred KBytes of WASM byte code). If this is too much "bloat", there are smaller, but also less powerful alternatives like microui: https://github.com/rxi/microui)


I don't know about GTK, QT, and the like, but there's a whole budding ecosystem purporting to solve it WASM-native.

Dioxus [1] and about a dozen other libraries are attempting to be write-once, deploy web, mobile, desktop with native performance. They adopt a React-like component UI.

The Rust ecosystem is full of stuff. There are lots of different approaches too - immediate mode drawing, canvas drawing [2], etc.

Choosing a winner is the hard part. There are too many projects and no clear community-elected leader.

[1] https://dioxuslabs.com/learn/0.4/getting_started/wasm

[2] https://www.egui.rs/#demo


GTK+ has Broadway to render GTK applications to the web browser. Qt has some ActiveX support, but you don't want that. Java/Kotlin has a bunch of frameworks, like TeaVM to run .JAR files in the browser, or Vaadin to write web GUIs like you would desktop applications.

I think most languages that have been around for more than five years have some kind of GUI framework that'll run in the browser.

Very worst-case scenario, you could compile a Windows executable and run them in BottledWine :P


Makepad, very ambitious (watch the vid): https://github.com/makepad/makepad


egui [1] supports wasm.

I wrote a simple chord finder for learning to play guitar with it pretty quickly [2], and would use it again to solve a problem like this, though I'm told immediate mode UI frameworks aren't good for things other than quick prototypes, or in my case, scratching a quick itch.

[1] https://www.egui.rs/

[2] https://kelvie.github.io/chord-finder/


Immediate mode UI frameworks are not inherently less appropriate than any other framework. Curious what the source of that is.


In my experience Immediate mode UI frameworks are almost always not very internationalization friendly (right to left text like Arabic, problematic IME support) and, they are almost always not very accessibility friendly. Also things like system context menus to offer features like translation, system level spelling correction with the user's custom dictionary, system password memorization and recall, word lookup, etc

it's not impossible. in fact at an API level, React is an immediate mode gui written on top of a retained mode gui. but it's that retained mode that's providing all the features above.

which immediate mode GUIs have you used that cover these features?


If the issue is that implementations are feature lacking, that's a different story. The world is littered with half baked frameworks. Hell, I've used plenty of retained mode frameworks that lack all of those things too.

My concern was moreso that there is nothing inherent to immediate mode that prevents all of those things. Someone just has to build it.

RTL tends to be more of a layout problem and has little to do with UIs. Most of my experience with immediate mode UI frameworks is in proprietary applications. I will say that we had no issues with localization and we integrated well with screen readers though none of this was in a platform independent manner. And that's usually the root of all of these issues.


I disagree that "someone just has to build it."

For example, when iOS shipped it did not have spell checking, word lookup, translation, password insertion, etc built in as context menus on text. When those features were added by the OS, every app using the native widgets got those features for free with no work on their part.

Apps that rolled their own though, had to re-release their app. If they don't have time or their app is abandoned then their users suffer.

This is arguably one of the reasons flash was killed off. It was designed to render to a rectangle of pixels and it assumed a mouse and keyboard. Then smartphones appeared and no one was going to go back and fix millions of flash pages.

Current apps doing their own thing will have the same problem with the next UI change (maybe vision Pro for example).


Sure, I'm not arguing against using native widgets. I'm not suggesting that immediate mode necessitates eschewing all of those things or hand rolling them. There is a difference between native frameworks and cross-platform frameworks.

Did Qt magically support all of those features on day 1? Xamarin doesn't completely support all of the iOS input properties, for example.

This feels like a straw man.


This was exactly my experience building an app at my last company that used an immediate mode UI. You get so much baseline accessibility 'for free' if you use the DOM.


Flutter is looking to do so, it was just waiting for WASM-GC support which has now shipped on Chrome. Rust is another good one as the other commenter stated. I personally use Flutter for the UI and Rust for the business logic, using libraries like flutter_rust_bridge and rinf as FFI between the two.


I'm curious how flutter apps will do on visionOS. I suspect apps using native widgets will be great because the OS can change to UX for the app. Flutter apps on the other hand may all have to be re-shipped since they're doing it by hand.


Not exactly what you are looking for, probably, but Leptos[1]. Dioxus[1.1], Yew[2] and almost all "frontend web frameworks in rust" run primarily/only on WASM. Larger list here[3]

[1] https://github.com/leptos-rs/leptos, https://github.com/dioxuslabs/dioxus

[2] https://yew.rs/

[3] https://github.com/flosse/rust-web-framework-comparison#fron...


I’ve used ImGui with success. I specially was also using webgpu so I used the glfw+webgpu backends. I had to fix a few issues in both halfs of the backend and there remain some little interaction bugs (mostly because browsers capture some keychords and mouse actions and you have to work around a number of them).

ImGui makes a specific design choice and isn’t amazingly documented. I don’t think it’s a good choice for larger scale apps. But good for tools or UIs in games, etc.

Accessibility is a nightmare with pretty much anything skipping browser layout of course.


COSMIC DE (Rust-based) supports rust-windowing/winit apps, which compile to a <canvas> tag in WASM.

winit: https://github.com/rust-windowing/winit


This seems like an absolute nightmare for people with disabilities.


Wow, haven’t seen Bochs mentioned since I was doing hobby OS development 15 years ago. I guess there’s not a ton of emulators that don’t use JIT or hardware extensions these days.


Same here! One of my very first apps for android 1.1 was a port of bochs =)


Would recommend checking out the container examples, they are suprisingly fast.

https://ktock.github.io/container2wasm-demo/


This is quite cool...

But at the same time, please tell me this is not the future of software packaging.


Allow me to introduce you to https://www.destroyallsoftware.com/talks/the-birth-and-death...

Everything is on track.


I love all of Gary Bernhardt's talks.


Newt: My mommy always said there were no monsters, no real ones, but there are.

Ripley: Yes, there are, aren't there?

Newt: Why do they tell little kids that?

Ripley: Most of the time it's true.

---

But yes, I do believe this has a strong, serverless future.


Downloading a 50MB WASM blob to run an emulator to boot a Linux kernel and then start an HTTP server to handle a single request is utter madness, which is probably why this will become popular to do.


I can see my house from up here!


This will probably be a minor component of the Qeng Ho's timekeeping system: https://en.m.wikipedia.org/wiki/A_Deepness_in_the_Sky#Inters...



If this is a step on the road to wasm being the primary target for packaging applications (without a docker image + x86 emulator intermediary)...

Then I am all for it.


Maybe these containers should be build for wasm-wasi instead of x86 from the beginning? Then there would be no need to emulate x86 in wasm


Because "wasm-wasi" is not a CPU that Linux runs on.


But, if docker is running on WASM-WASI like it is here, maybe it's possible to do a full build toolchain as well?


Docker is not running on wasm. There's a wasm app, that is a x86_64 CPU emulator, used to run a Linux VM, on top of which anything can run. Including existing Docker images for x86_64.


Sure, fine, if an largely-compliant OCI runtime is running in a wasm-wasi context, then I see no reason you couldn't stub out syscalls to reduce dependence on linux-kernel syscalls, and gradually replace the kernel with a minimal set of stub syscalls that make sense, sort of like how gvisor has implemented 200+ linux syscalls in GO and presents an alternative OCI runtime for docker containers.

Gradually reduce dependence on an emulated linux-kernel in favour of an alternative lightweight POSIX implementation that runs in pure WASM. This is something that is already done with other OCI runtimes like sysbox and gvisor.


Why is that relevant? txdv was suggesting to ditch Linux, so what CPUs Linux supports is not relevant.


If you ditch Linux, you now have to write a kernel, not an application.


There is support in Docker to run wasm-wasi binaries directly (see: https://wasmlabs.dev/articles/docker-without-containers/). The downside compared to OP's approach is that whatever you're running has to have already been compiled to wasm-wasi. The upside would be much faster execution time (no emulation overhead for x86).


    FROM riscv64/alpine:20230208
    RUN apt-get update && apt-get install -y curl

The demo really is Debian, but it seems like the docs are confused about which images use Alpine instead.


So we're now at the point where installing Kubernetes is visiting a web page... nice.


container2wasm > Additional Resources: https://github.com/ktock/container2wasm#additional-resources :

vscode-container-wasm: https://github.com/ktock/vscode-container-wasm :

> VSCode extension for running containers on VSCode for the web (e.g. github.dev, [vscode.dev,]), leveraging container2wasm

Chromebooks can run vscode.dev and WASM.

Is this the best way to `git clone` and run `python -m this` in a Bash/ZSH shell on a Chromebook?

This could be useful with jupyter-repo2docker.


This is quite possible the coolest technical accomplishment i've seen in... since... well, further back then i can currently recall. On some level, even more impressive (to me) than the AI-related advances of the 2020s. Absolutely mind-blowing.

Edit: i don't mind saying that such accomplishments make me feel completely inadequate as a developer.


Any performance benchmarks or details of the practicality? Eg could this run on something like Cloudflare Workers?


If this performs, and it is a big if, it can make life a lot easier for people with stateful services. You just push the service back to the browers and you are done. It can be a lot cheaper and lot faster, and also reduce complexity of making a stateful service scalable and reliable.


And all the users have to download a 200MB web page every time they use your service...


Can the download be cached in the browser so that subsequent web page visits don't download the same initial 200MB blob? That's better at least.


I really liked Browser Shell [1]

It has interesting solution regarding fs.

[1] https://news.ycombinator.com/item?id=30199570



You've got to be kidding, typing `emacs` actually opens emacs (it seems to just download it and start it up in a few seconds)! Mindblowing.


Also: https://github.com/copy/v86 - more productized browser x86 runtime, used by eg https://github.com/snaplet/postgres-wasm


Is this a "why not" project, or are there real-world use cases for this?


Being able to run ANY Docker container directly in the browser is incredibly useful. The most obvious application is educational environments - this makes it trivial to provide all sorts of software for students to tinker with without needing to run any server-side code anywhere, just some static file hosting.


This is the use case I've been tackling with Runno (https://runno.dev), it's more performant than OP's approach but not as flexible.


Being able to do it client-side eliminates the biggest cost barrier (VM time) and risks (people using your VMs for cryptomining) that you encounter trying to offer real 'labs' for users.


I very much doubt it's "any" docker image. WASM isn't 1:1 feature equivalent with docker. e.g. filesystem access


It looks to me like they solve that by simulating the entire Linux operating system, filesystem included.

You won't get persistence when you restart the process, but you'll still be able to run code that needs to read and write files.

Try it for yourself: visit https://ktock.github.io/container2wasm-demo/amd64-debian-was... to start a shell against a Debian container, then use "echo 'hi' > hello.txt" to write a file and "cat hello.txt" to read it.


> You won't get persistence when you restart the process, but you'll still be able to run code that needs to read and write files.

Since it's Linux and you can give it "network access" (using workarounds such as redirecting via a server), you can just use one of the existing ways to mount a remote filesystem that could be stored on the server (such as NFS, sshfs, ...).

Or bridge/mount to the local browser and store it in indexeddb or whatever.

It already has directory mapping when running outside a browser - maybe there's even an easy way to do this more directly than funneling everything through the virtual network.


There are tons of real-world use cases.

WASM is more or more being used to extend applications with custom functions/plugins, as well as function-as-a-service services. But they usually require writing custom code, specifically for these environments.

The ability to build standard containers, use any languages and tools, run shell scripts, etc. makes WebAssembly far more accessible. Complex applications can be tested natively, and deployed effortlessly later to environments that require WebAssembly.

From a performance perspective, this is not optimal. But from a productivity perspective, this is awesome, and definitely something to have in your toolbox when all you need is get things done.


the most amazing, most wirth's law project


Whyyyyyyy.

bangs head into desk


The universe is just a simulation running inside a vm inside a web browser. It's web browsers all the way down.


Fret not friend, I see turtles ahead




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

Search: