https://github.com/ktock/container2wasm Skip to content Toggle navigation Sign in * Product + Actions Automate any workflow + Packages Host and manage packages + Security Find and fix vulnerabilities + Codespaces Instant dev environments + Copilot Write better code with AI + Code review Manage code changes + Issues Plan and track work + Discussions Collaborate outside of code Explore + All features + Documentation + GitHub Skills + Blog * Solutions For + Enterprise + Teams + Startups + Education By Solution + CI/CD & Automation + DevOps + DevSecOps Resources + Learning Pathways + White papers, Ebooks, Webinars + Customer Stories + Partners * Open Source + GitHub Sponsors Fund open source developers + The ReadME Project GitHub community articles Repositories + Topics + Trending + Collections * Pricing Search or jump to... Search code, repositories, users, issues, pull requests... Search [ ] Clear Search syntax tips Provide feedback We read every piece of feedback, and take your input very seriously. [ ] [ ] Include my email address so I can be contacted Cancel Submit feedback Saved searches Use saved searches to filter your results more quickly Name [ ] Query [ ] To see all available qualifiers, see our documentation. Cancel Create saved search Sign in Sign up You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session. Dismiss alert {{ message }} ktock / container2wasm Public * Notifications * Fork 24 * Star 697 Container to WASM converter ktock.github.io/container2wasm-demo/ License Apache-2.0 license 697 stars 24 forks Activity Star Notifications * Code * Issues 10 * Pull requests 2 * Actions * Projects 0 * Security * Insights Additional navigation options * Code * Issues * Pull requests * Actions * Projects * Security * Insights ktock/container2wasm This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository. main Switch branches/tags [ ] Branches Tags Could not load branches Nothing to show {{ refName }} default View all branches Could not load tags Nothing to show {{ refName }} default View all tags Name already in use A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch? Cancel Create 4 branches 10 tags Code * Local * Codespaces * Clone HTTPS GitHub CLI [https://github.com/k] Use Git or checkout with SVN using the web URL. [gh repo clone ktock/] Work fast with our official CLI. Learn more about the CLI. * Open with GitHub Desktop * Download ZIP Sign In Required Please sign in to use Codespaces. Launching GitHub Desktop If nothing happens, download GitHub Desktop and try again. Launching GitHub Desktop If nothing happens, download GitHub Desktop and try again. Launching Xcode If nothing happens, download Xcode and try again. Launching Visual Studio Code Your codespace will open once ready. There was a problem preparing your codespace, please try again. Latest commit @ktock ktock Merge pull request #182 from ktock/dependabot/go_modules/ github.com/o... ... 31f6db8 Jan 3, 2024 Merge pull request #182 from ktock/dependabot/go_modules/github.com/ o... ...pencontainers/runc-1.1.11 build(deps): bump github.com/opencontainers/runc from 1.1.10 to 1.1.11 31f6db8 Git stats * 338 commits Files Permalink Failed to load latest commit information. Type Name Latest commit message Commit time .github build(deps): bump actions/setup-go from 4 to 5 December 7, 2023 02:09 cmd more retry November 1, 2023 23:54 docs/images Initial support for networking September 12, 2023 09:52 examples example: allow browser using its user-agent September 14, 2023 12:41 extras/c2w-net-proxy c2w-net-proxy: gvisor-tap-vsock v0.7.1 December 16, 2023 22:33 patches Rename flag -net=qemu to -net=socket September 14, 2023 12:35 tests test: wazero v1.6.0 December 25, 2023 23:32 version first commit February 28, 2023 14:29 .gitignore first commit February 28, 2023 14:29 Dockerfile Dockerfile: lock rust version to 1.74.1-buster January 3, 2024 19:18 Dockerfile.test test: go 1.21.5 December 14, 2023 19:48 LICENSE first commit February 28, 2023 14:29 Makefile Initial support for networking September 12, 2023 09:52 README.md fix header November 4, 2023 16:54 embed.go first commit February 28, 2023 14:29 go.mod build(deps): bump github.com/opencontainers/runc from 1.1.10 to 1.1.11 January 3, 2024 10:44 go.sum build(deps): bump github.com/opencontainers/runc from 1.1.10 to 1.1.11 January 3, 2024 10:44 View code [ ] container2wasm: Container to WASM converter Examples Container Image to WASM (WASI) Container on Browser WASI on browser WASI on browser with networking emscripten on browser Getting Started Release binaries Building binaries using make Command reference c2w Run-time flags for WASM image Directory mapping Motivation How does it work WASI Runtimes Integration Status x86_64 containers risc-v and other architecutre's containers Similar projects Additional Resources Acknowledgement README.md [:arrow_down: Download] [:book: Command reference] [:books: Additional Documents] [:arrow_forward: Demo] container2wasm: Container to WASM converter container2wasm is a container-to-wasm image converter that enables to run the container on WASM. * Converts a container to WASM with emulation by Bochs (for x86_64 containers) and TinyEMU (for riscv64 containers). * Runs on WASI runtimes (e.g. wasmtime, wamr, wasmer, wasmedge, wazero) * Runs on browser * x86_64 or riscv64 containers are recommended. Other platforms (e.g. arm64) also work (but slow). This is an experimental software. Demo page of containers on browser (debian,python,node,vim): https:// ktock.github.io/container2wasm-demo/ Examples Container Image to WASM (WASI) $ c2w ubuntu:22.04 out.wasm The above command converts ubuntu:22.04 container image to WASI image (out.wasm). NOTE1: For selecting the container image's architecture other than amd64, use --target-arch flag of c2w (e.g. c2w --target-arch =riscv64 riscv64/ubuntu:22.04 out.wasm). NOTE2: x86_64 or riscv64 container is recommended. Other platform's containers should work but slow because of additional emulation. The generated image runs on WASI runtimes: $ wasmtime out.wasm uname -a Linux localhost 6.1.0 #1 PREEMPT_DYNAMIC Mon Jun 5 11:57:09 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux $ wasmtime out.wasm ls / bin dev home lib32 libx32 mnt proc run srv tmp var boot etc lib lib64 media opt root sbin sys usr Directory mapped from the host is accessible on the container. $ mkdir -p /tmp/share/ && echo hi > /tmp/share/from-host $ wasmtime --mapdir /mnt/share::/tmp/share out.wasm cat /mnt/share/from-host hi Please refer to ./examples/networking/wasi/ for enabling networking Container on Browser Container on browser You can run the container on browser as well. There are two methods for running the container on browser. Please also refer to ./examples/wasi-browser (WASI-on-browser example) and ./examples/emscripten (emscripten example). Please refer to ./examples/networking/ for details about enabling networking. WASI on browser This example converts the container to WASI and runs it on browser. The following command generates a WASI image. $ c2w ubuntu:22.04 /tmp/out-js2/htdocs/out.wasm The following is an example of running the image on browser relying on xterm-pty and browser_wasi_shim. This example serves the image on localhost:8080 using apache http server. $ cp -R ./examples/wasi-browser/* /tmp/out-js2/ && chmod 755 /tmp/out-js2/htdocs $ docker run --rm -p 8080:80 \ -v "/tmp/out-js2/htdocs:/usr/local/apache2/htdocs/:ro" \ -v "/tmp/out-js2/xterm-pty.conf:/usr/local/apache2/conf/extra/xterm-pty.conf:ro" \ --entrypoint=/bin/sh httpd -c 'echo "Include conf/extra/xterm-pty.conf" >> /usr/local/apache2/conf/httpd.conf && httpd-foreground' You can run the container on browser via localhost:8080. WASI on browser with networking Debian container on browser with browser networking Container can also perform networking. This section is the demo of using curl command in the container. Tested only on Chrome. The example might not work on other browsers. $ cat <> /usr/local/apache2/conf/httpd.conf && httpd-foreground' You can run the container on browser with several types of configurations: * localhost:8080/?net=browser: Container with networking. Network stack c2w-net-proxy implemented based on gvisor-tap-vsock runs on browser and forwards HTTP/HTTPS packets using the browser's Fetch API. The set of accesible sites is restricted by the browser configuration (e.g. CORS restriction). See also ./examples/ networking/fetch for detalis. * localhost:8080/?net=delegate=ws://localhost:8888: Container with networking. You need to run user-space network stack c2w-net implemented based on gvisor-tap-vsock on the host (outside of browser). It forwards all packets received from the browser over WebSocket. See also ./examples/networking/websocket for detalis and configuration. (tested only on Linux) * localhost:8080: Container without networking. emscripten on browser This example uses emscripten for converting the container to WASM. * pros: WASM image size can be smaller than WASI. * cons: WASI-specific optimization like Wizer pre-initialization isn't available for this mode. So the startup of the container can be slow (For x86_64 containers it might take >= 30s. For riscv64 containers it might take >= 10s). The following command generates a WASM image and a JS file runnable on browser. $ c2w --to-js ubuntu:22.04 /tmp/out-js/htdocs/ The following is an example of running the image on browser relying on xterm-pty. This example serves the image on localhost:8080 using apache http server. $ cp -R ./examples/emscripten/* /tmp/out-js/ && chmod 755 /tmp/out-js/htdocs $ docker run --rm -p 8080:80 \ -v "/tmp/out-js/htdocs:/usr/local/apache2/htdocs/:ro" \ -v "/tmp/out-js/xterm-pty.conf:/usr/local/apache2/conf/extra/xterm-pty.conf:ro" \ --entrypoint=/bin/sh httpd -c 'echo "Include conf/extra/xterm-pty.conf" >> /usr/local/apache2/conf/httpd.conf && httpd-foreground' You can run the container on browser via localhost:8080. NOTE: It can take some time to load and start the container. Networking can also be enabled using the user-space network stack c2w-net implemented based on gvisor-tap-vsock serving over WebSocket on the host (outside of browser). See also ./examples/networking/ websocket for detalis. Getting Started * requirements + Docker 18.09+ (w/ DOCKER_BUILDKIT=1) + Docker Buildx v0.8+ (recommended) or docker build (w/ DOCKER_BUILDKIT=1) You can install the converter command c2w using one of the following methods. NOTE: The output binary also contains c2w-net which a command usable for controlling networking feature (please see also ./ examples/networking for details). Release binaries Binaries are available from https://github.com/ktock/container2wasm/ releases Extract the tarball and put the binary somewhere under $PATH. Building binaries using make Go 1.19+ is needed. make sudo make install Command reference c2w Converts a container image into a WASM image and writes it to the specified path (default: out.wasm at the current directory). Usage: c2w [options] image-name [output file] * image-name: container image name (will be pulled from the registry if it doesn't exist in Docker) * [output file]: path to the result WASM file. Sub commands * help, h: Shows a list of commands or help for one command Options * --assets value: Custom location of build assets. * --dockerfile value: Custom location of Dockerfile (default: embedded to this command) * --builder value: Bulider command to use (default: "docker") * --target-arch value: target architecture of the source image to use (default: "amd64") * --build-arg value: Additional build arguments (please see Dockerfile for available build args) * --to-js: convert the container to WASM using emscripten * --debug-image: Enable debug print in the output image * --show-dockerfile: Show default Dockerfile * --legacy: Use "docker build" instead of buildx (no support for assets flag) (default:false) * --help, -h: show help * --version, -v: print the version Run-time flags for WASM image You can specify run-time flags to the generated wasm image for configuring the execution (e.g. for changing command to run in the container). Usage: out.wasm [options] [COMMAND] [ARG...] * [COMMAND] [ARG...]: command to run in the container. (default: commands specified in the image config) Options * -entrypoint : entrypoint command. (default: entrypoint specified in the image config) * -no-stdin : disable stdin. (default: false) Example: The following changes the container's entrypoint to echo and pass hello to the arguments. wasmtime -- /app/out.wasm --entrypoint=echo hello Directory mapping Directory mapped from the host is accessible on the container. $ mkdir -p /tmp/share/ && echo hi > /tmp/share/hi $ wasmtime --mapdir /test/dir/share::/tmp/share /app/out.wasm ls /test/dir/share/ hi Motivation Though more and more programming languages start to support WASM, it's not easy to run the existing programs on WASM. This sometimes requires re-implementing and re-compiling them and costs extra time for development. This is a PoC converter tries to solve it by enabling running unmodified containers on WASM. How does it work contaienr2wasm creates a WASM image that runs the container and the Linux kernel on the emulated CPU. The following shows the techniqual details: * Builder: BuildKit runs the conversion steps written in Dockerfile. * Emulator: Bochs emulates x86_64 CPU on WASM. TinyEMU emulates RISC-V CPU on WASM. They're compiled to WASM using wasi-sdk (for WASI and on-browser) and emscripten (for on-browser). * Guest OS: Linux runs on the emulated CPU. runc starts the container. Non-x86 and non-RISC-V containers runs with additional emulation by QEMU installed via tonistiigi/binfmt. * Directory Mapping: WASI filesystem API makes host directories visible to the emulator. Emulators mount them to the guest linux via virtio-9p. * Packaging: wasi-vfs (for WASI and on-browser) and emscripten (for on-browser) are used for packaging the dependencies. The kernel is pre-booted during the build using wizer to minimize the startup latency (for WASI only as of now). * Networking: Browser's Fetch API or WebSocket is used for on-browser image. sock_* API is used for WASI. gvisor-tap-vsock can be used as the networking stack. (docs: ./examples/networking /) * Security: The converted container runs in the sandboxed WASM (WASI) VM with the limited access to the host system. WASI Runtimes Integration Status * [?] : supported * : WIP * NOTE: WASI features not listed here are untested (future version will support more features) x86_64 containers runtime stdio mapdir networking note [?] (w/ wasmtime [?] [?] host-side network stack) wamr [?] [?] (wasm-micro-runtime) [?] (w/ wazero [?] [?] host-side network stack (stdin non-blocking wasmer unsupported) [?] stdin doesn't seem to work (stdin non-blocking wasmedge unsupported) [?] stdin doesn't seem to work risc-v and other architecutre's containers runtime stdio mapdir networking note [?] (w/ wasmtime [?] [?] host-side network stack) wamr [?] [?] (wasm-micro-runtime) [?] (w/ wazero [?] [?] host-side network stack) (stdin non-blocking wasmer unsupported) [?] stdin doesn't seem to work (stdin non-blocking wasmedge unsupported) [?] stdin doesn't seem to work Similar projects There are several container runtimes support running WASM applications, but they don't run containers on WASM. * WASM on container runtimes + Docker+Wasm integration: https://docs.docker.com/desktop/wasm / + runwasi: https://github.com/containerd/runwasi + youki: https://github.com/containers/youki + crun: https://github.com/containers/crun + krustlet: https://github.com/krustlet/krustlet There are emulators that support running linux on WASM, but they don't support WASI. * x86 on WASM + v86: https://github.com/copy/v86 * RISCV on WASM + TinyEMU: https://bellard.org/tinyemu/ Some WASM API specs provides applications access to the host system. Re-compilation (and possibe re-implementation) of the application is needed. * WASI: https://github.com/WebAssembly/WASI * WASIX(WASI + additional syscall extensions): https://github.com/ wasix-org Additional Resources * ./examples/: Examples (python, php, on-browser, networking, etc.) * vscode-container-wasm: VSCode extension for running containers on VSCode on browser (e.g. github.dev), leveraging container2wasm: https://github.com/ktock/vscode-container-wasm Acknowledgement * container2wasi itself is licensed under Apache 2.0 but the generated WASM image will include third-pirty softwares: + Bochs (GNU Lesser General Public License v2.1) https:// bochs.sourceforge.io/ o Source code is contained in (./patches/bochs). Bochs is modified by our project for making it work with containers + TinyEMU (MIT License) https://bellard.org/tinyemu/ o Source code is contained in (./patches/tinyemu). TinyEMU is modified by our project for making it work with containers + GRUB (GNU General Public License Version 3): https:// www.gnu.org/software/grub/ + BBL(riscv-pk) (license): https://github.com/ riscv-software-src/riscv-pk + Linux (GNU General Public License version 2): https:// github.com/torvalds/linux/ + tini (MIT License): https://github.com/krallin/tini + runc (Apache License 2.0): https://github.com/opencontainers/ runc + Binfmt (MIT License): https://github.com/tonistiigi/binfmt + QEMU (license): https://github.com/qemu/qemu + vmtouch (license): https://github.com/hoytech/vmtouch + BusyBox (GNU General Public License version 2): https:// git.busybox.net/busybox * On-browser example relies on the following softwares. + xterm-pty (MIT License): https://github.com/mame/xterm-pty + browser_wasi_shim (either of MIT License and Apache License 2.0): https://github.com/bjorn3/browser_wasi_shim + gvisor-tap-vsock (Apache License 2.0): https://github.com/ containers/gvisor-tap-vsock About Container to WASM converter ktock.github.io/container2wasm-demo/ Topics docker containers webassembly wasm Resources Readme License Apache-2.0 license Activity Stars 697 stars Watchers 13 watching Forks 24 forks Report repository Releases 10 v0.5.2 Latest Nov 4, 2023 + 9 releases Packages 0 No packages published Contributors 4 * @ktock ktock Kohei Tokunaga * @dependabot[bot] dependabot[bot] * @codefromthecrypt codefromthecrypt Crypt Keeper * @kateinoigakukun kateinoigakukun Yuta Saito Languages * C++ 68.7% * C 21.6% * Shell 3.1% * Makefile 2.0% * Rez 1.9% * Go 0.7% * Other 2.0% Footer (c) 2024 GitHub, Inc. Footer navigation * Terms * Privacy * Security * Status * Docs * Contact * Manage cookies * Do not share my personal information You can't perform that action at this time.