{"id":25057416,"url":"https://github.com/container2wasm/container2wasm","last_synced_at":"2025-05-14T07:11:06.922Z","repository":{"id":91931101,"uuid":"601918925","full_name":"container2wasm/container2wasm","owner":"container2wasm","description":"Container to WASM converter","archived":false,"fork":false,"pushed_at":"2025-05-05T02:45:36.000Z","size":8143,"stargazers_count":2279,"open_issues_count":46,"forks_count":101,"subscribers_count":23,"default_branch":"main","last_synced_at":"2025-05-05T07:07:22.014Z","etag":null,"topics":["containers","docker","wasm","webassembly"],"latest_commit_sha":null,"homepage":"https://ktock.github.io/container2wasm-demo/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/container2wasm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":"GOVERNANCE.md","roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-02-15T05:22:10.000Z","updated_at":"2025-05-04T13:52:06.000Z","dependencies_parsed_at":"2023-11-17T08:47:06.258Z","dependency_job_id":"25ffc4c6-1c89-41a5-9c69-9f2056aa5372","html_url":"https://github.com/container2wasm/container2wasm","commit_stats":{"total_commits":302,"total_committers":5,"mean_commits":60.4,"dds":0.2880794701986755,"last_synced_commit":"5cd7dedb8017b00d0b504de681f1fd94ceb11fb8"},"previous_names":["container2wasm/container2wasm","ktock/container2wasm"],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/container2wasm%2Fcontainer2wasm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/container2wasm%2Fcontainer2wasm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/container2wasm%2Fcontainer2wasm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/container2wasm%2Fcontainer2wasm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/container2wasm","download_url":"https://codeload.github.com/container2wasm/container2wasm/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254092798,"owners_count":22013292,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["containers","docker","wasm","webassembly"],"created_at":"2025-02-06T14:01:17.434Z","updated_at":"2025-05-14T07:11:01.908Z","avatar_url":"https://github.com/container2wasm.png","language":"Go","funding_links":[],"categories":["Go","docker"],"sub_categories":[],"readme":"[[⬇️**Download**]](https://github.com/ktock/container2wasm/releases)\n[[📖 **Command reference**]](#command-reference)\n[[📚 **Additional Documents**]](#additional-resources)\n[[▶️**Demo**]](https://ktock.github.io/container2wasm-demo/)\n\n# container2wasm: Container to WASM converter\n\ncontainer2wasm is a container-to-wasm image converter that enables to run the container on WASM.\n\n- Converts a container to WASM with emulation by Bochs (for x86_64 containers), TinyEMU (for riscv64 containers) and QEMU.\n- Runs on WASI runtimes (e.g. wasmtime, wamr, wasmer, wasmedge, wazero)\n- Runs on browser\n- x86_64, riscv64 or AArch64 containers are recommended.\n\nThis is an experimental software.\n\nDemo page of containers on browser (debian,python,node,vim): https://ktock.github.io/container2wasm-demo/\n\n## Examples\n\n### Container Image to WASM (WASI)\n\n```console\n$ c2w ubuntu:22.04 out.wasm\n```\n\nThe above command converts `ubuntu:22.04` container image to WASI image (`out.wasm`).\n\n\u003e 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`).\n\n\u003e NOTE2: x86_64 or riscv64 container is recommended. Other platform's containers should work but slow because of additional emulation.\n\nThe generated image runs on WASI runtimes:\n\n```console\n$ wasmtime out.wasm uname -a\nLinux localhost 6.1.0 #1 PREEMPT_DYNAMIC Mon Jun  5 11:57:09 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux\n$ wasmtime out.wasm ls /\nbin   dev  home  lib32\tlibx32\tmnt  proc  run\t srv  tmp  var\nboot  etc  lib\t lib64\tmedia\topt  root  sbin  sys  usr\n```\n\nDirectory mapped from the host is accessible on the container.\n\n```\n$ mkdir -p /tmp/share/ \u0026\u0026 echo hi \u003e /tmp/share/from-host\n$ wasmtime --mapdir /mnt/share::/tmp/share out.wasm cat /mnt/share/from-host\nhi\n```\n\n\u003e Please refer to [`./examples/networking/wasi/`](./examples/networking/wasi/) for enabling networking\n\n### Container on Browser\n\n![Container on browser](./docs/images/ubuntu-wasi-on-browser.png)\n\nYou can run the container on browser as well.\nThere are two methods for running the container on browser.\n\n#### WASI on browser\n\nThis example converts the container to WASI and runs it on browser.\n\n\u003e Please also refer to [`./examples/wasi-browser`](./examples/wasi-browser/) for details.\n\nThe following command generates a WASI image.\n\n```\n$ c2w ubuntu:22.04 /tmp/out-js2/htdocs/out.wasm\n```\n\nThe following is an example of running the image on browser relying on [xterm-pty](https://github.com/mame/xterm-pty) and [browser_wasi_shim](https://github.com/bjorn3/browser_wasi_shim).\nThis example serves the image on `localhost:8080` using apache http server.\n\n```\n$ cp -R ./examples/wasi-browser/* /tmp/out-js2/ \u0026\u0026 chmod 755 /tmp/out-js2/htdocs\n$ docker run --rm -p 8080:80 \\\n         -v \"/tmp/out-js2/htdocs:/usr/local/apache2/htdocs/:ro\" \\\n         -v \"/tmp/out-js2/xterm-pty.conf:/usr/local/apache2/conf/extra/xterm-pty.conf:ro\" \\\n         --entrypoint=/bin/sh httpd -c 'echo \"Include conf/extra/xterm-pty.conf\" \u003e\u003e /usr/local/apache2/conf/httpd.conf \u0026\u0026 httpd-foreground'\n```\n\nYou can run the container on browser via `localhost:8080`.\n\n##### WASI on browser with networking\n\n![Debian container on browser with browser networking](./docs/images/debian-curl-wasi-on-browser-frontend-networking.png)\n\nContainer can also perform networking.\nThis section is the demo of using curl command in the container.\n\n\u003e Tested only on Chrome. The example might not work on other browsers.\n\n```\n$ cat \u003c\u003cEOF | docker build -t debian-curl -\nFROM debian:sid-slim\nRUN apt-get update \u0026\u0026 apt-get install -y curl\nEOF\n$ c2w debian-curl /tmp/out-js2/htdocs/out.wasm\n```\n\nThis example serves the image on `localhost:8080` using apache http server.\nThe following also puts the [network stack runnable on browser](./extras/c2w-net-proxy/) to the document root.\n\n```\n$ cp -R ./examples/wasi-browser/* /tmp/out-js2/ \u0026\u0026 chmod 755 /tmp/out-js2/htdocs\n$ wget -O /tmp/out-js2/htdocs/c2w-net-proxy.wasm https://github.com/ktock/container2wasm/releases/download/v0.5.0/c2w-net-proxy.wasm\n$ docker run --rm -p 8080:80 \\\n         -v \"/tmp/out-js2/htdocs:/usr/local/apache2/htdocs/:ro\" \\\n         -v \"/tmp/out-js2/xterm-pty.conf:/usr/local/apache2/conf/extra/xterm-pty.conf:ro\" \\\n         --entrypoint=/bin/sh httpd -c 'echo \"Include conf/extra/xterm-pty.conf\" \u003e\u003e /usr/local/apache2/conf/httpd.conf \u0026\u0026 httpd-foreground'\n```\n\nYou can run the container on browser with several types of configurations:\n\n- `localhost:8080/?net=browser`: Container with networking. [Network stack `c2w-net-proxy`](./extras/c2w-net-proxy/) implemented based on [`gvisor-tap-vsock`](https://github.com/containers/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`](./examples/networking/fetch/) for detalis.\n- `localhost:8080/?net=delegate=ws://localhost:8888`: Container with networking. You need to run [user-space network stack `c2w-net`](./cmd/c2w-net/) implemented based on [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) on the host (outside of browser). It forwards all packets received from the browser over WebSocket. See also [`./examples/networking/websocket`](./examples/networking/websocket/) for detalis and configuration. (tested only on Linux)\n- `localhost:8080`: Container without networking.\n\n\u003e Please also refer to [`./examples/networking/`](./examples/networking/) for details about networking.\n\n#### emscripten on browser\n\nThis example uses emscripten for converting the container to WASM.\nThis leverages [QEMU Wasm](https://github.com/ktock/qemu-wasm) which is QEMU ported to browser with JIT compilation (TCG) enabled.\nAlso refer to [`./examples/emscripten/`](./examples/emscripten/) for detalis.\n\nThe following command generates a WASM image and a JS file runnable on browser.\n\n```console\n$ c2w --to-js alpine:3.20 /tmp/out-js/htdocs/\n```\n\nThe following is an example of running the image on browser relying on [xterm-pty](https://github.com/mame/xterm-pty).\nThis example serves the image on `localhost:8080` using apache http server.\n\n```console\n$ ( cd ./examples/emscripten/htdocs/ \u0026\u0026 npx webpack \u0026\u0026 cp -R index.html dist vendor/xterm.css /tmp/out-js4/htdocs/ )\n$ wget -O /tmp/c2w-net-proxy.wasm https://github.com/ktock/container2wasm/releases/download/v0.5.0/c2w-net-proxy.wasm\n$ cat /tmp/c2w-net-proxy.wasm | gzip \u003e /tmp/out-js4/htdocs/c2w-net-proxy.wasm.gzip\n$ cp ./examples/emscripten/xterm-pty.conf /tmp/out-js4/\n$ docker run --rm -p 8080:80 \\\n         -v \"/tmp/out-js4/htdocs:/usr/local/apache2/htdocs/:ro\" \\\n         -v \"/tmp/out-js4/xterm-pty.conf:/usr/local/apache2/conf/extra/xterm-pty.conf:ro\" \\\n         --entrypoint=/bin/sh httpd -c 'echo \"Include conf/extra/xterm-pty.conf\" \u003e\u003e /usr/local/apache2/conf/httpd.conf \u0026\u0026 httpd-foreground'\n```\n\nYou can run the container on browser with several types of configurations:\n\n- `localhost:8080/?net=browser`: Container with networking. [Network stack `c2w-net-proxy`](./extras/c2w-net-proxy/) implemented based on [`gvisor-tap-vsock`](https://github.com/containers/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/emscripten/`](./examples/emscripten/) for detalis.\n- `localhost:8080/?net=delegate=ws://localhost:8888`: Container with networking. You need to run [user-space network stack `c2w-net`](./cmd/c2w-net/) implemented based on [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) on the host (outside of browser). It forwards all packets received from the browser over WebSocket. See also [`./examples/emscripten/`](./examples/emscripten/) for detalis and configuration. (tested only on Linux)\n- `localhost:8080`: Container without networking.\n\n![Container on browser](./docs/images/emscripten-qemu-alpine-net-browser.png)\n\n\u003e Please also refer to [`./examples/networking/`](./examples/networking/) for details about networking.\n\n## Getting Started\n\n- requirements\n  - Docker 18.09+ (w/ `DOCKER_BUILDKIT=1`)\n  - [Docker Buildx](https://docs.docker.com/build/install-buildx/) v0.8+ (recommended) or `docker build` (w/ `DOCKER_BUILDKIT=1`)\n\nYou can install the converter command `c2w` using one of the following methods.\n\n\u003e NOTE: The output binary also contains [`c2w-net`](./cmd/c2w-net/) which a command usable for controlling networking feature (please see also [./examples/networking](./examples/networking/) for details).\n\n### Release binaries\n\nBinaries are available from https://github.com/ktock/container2wasm/releases\nExtract the tarball and put the binary somewhere under `$PATH`.\n\n### Building binaries using make\n\nGo 1.19+ is needed.\n\n```\nmake\nsudo make install\n```\n\n## Command reference\n\n### c2w\n\nConverts a container image into a WASM image and writes it to the specified path (default: `out.wasm` at the current directory).\n\nUsage: `c2w [options] image-name [output file]`\n\n- `image-name`: container image name (will be pulled from the registry if it doesn't exist in Docker)\n- `[output file]`: path to the result WASM file.\n\nSub commands\n\n- `help, h`: Shows a list of commands or help for one command\n\nOptions\n\n- `--assets value`: Custom location of build assets.\n- `--dockerfile value`: Custom location of Dockerfile (default: embedded to this command)\n- `--builder value`: Bulider command to use (default: \"docker\")\n- `--target-arch value`: target architecture of the source image to use (default: \"amd64\")\n- `--build-arg value`: Additional build arguments (please see Dockerfile for available build args)\n- `--to-js`: convert the container to WASM using emscripten\n- `--debug-image`: Enable debug print in the output image\n- `--show-dockerfile`: Show default Dockerfile\n- `--legacy`: Use \"docker build\" instead of buildx (no support for assets flag) (default:false)\n- `--external-bundle`: Do not embed container image to the Wasm image but mount it during runtime\n- `--help, -h`: show help\n- `--version, -v: `print the version\n\n### Run-time flags for WASM image\n\nYou can specify run-time flags to the generated wasm image for configuring the execution (e.g. for changing command to run in the container).\n\nUsage: `out.wasm [options] [COMMAND] [ARG...]`\n\n- `[COMMAND] [ARG...]`: command to run in the container. (default: commands specified in the image config)\n\nOptions\n\n- `-entrypoint \u003ccommand\u003e` : entrypoint command. (default: entrypoint specified in the image config)\n- `-no-stdin` : disable stdin. (default: false)\n\nExample:\n\nThe following changes the container's entrypoint to `echo` and pass `hello` to the arguments.\n\n```\nwasmtime -- /app/out.wasm --entrypoint=echo hello\n```\n\n### Directory mapping\n\nDirectory mapped from the host is accessible on the container.\n\n```\n$ mkdir -p /tmp/share/ \u0026\u0026 echo hi \u003e /tmp/share/hi\n$ wasmtime --mapdir /test/dir/share::/tmp/share /app/out.wasm ls /test/dir/share/\nhi\n```\n\n## Motivation\n\nThough more and more programming languages start to support WASM, it's not easy to run the existing programs on WASM.\nThis sometimes requires re-implementing and re-compiling them and costs extra time for development.\nThis is a PoC converter tries to solve it by enabling running unmodified containers on WASM.\n\n## How does it work\n\ncontaienr2wasm creates a WASM image that runs the container and the Linux kernel on the emulated CPU.\n\nThe following shows the techniqual details:\n\n- Builder: [BuildKit](https://github.com/moby/buildkit) runs the conversion steps written in Dockerfile.\n- Emulator: [Bochs](https://bochs.sourceforge.io/) emulates x86_64 CPU on WASM. [TinyEMU](https://bellard.org/tinyemu/) emulates RISC-V CPU on WASM. For `--to-js` flag, QEMU ([QEMU Wasm](https://github.com/ktock/qemu-wasm)) is used. They're compiled to WASM using [wasi-sdk](https://github.com/WebAssembly/wasi-sdk) (for WASI and on-browser) and [emscripten](https://github.com/emscripten-core/emscripten) (for on-browser).\n- Guest OS: Linux runs on the emulated CPU. [runc](https://github.com/opencontainers/runc) starts the container. Non-x86 and non-RISC-V containers runs with additional emulation by QEMU installed via [`tonistiigi/binfmt`](https://github.com/tonistiigi/binfmt).\n- Directory Mapping: WASI filesystem API makes host directories visible to the emulator. Emulators mount them to the guest linux via virtio-9p.\n- Packaging: [wasi-vfs](https://github.com/kateinoigakukun/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](https://github.com/bytecodealliance/wizer/) to minimize the startup latency (for WASI only as of now).\n- Networking: Browser's Fetch API or WebSocket is used for on-browser image. `sock_*` API is used for WASI. [`gvisor-tap-vsock`](https://github.com/containers/gvisor-tap-vsock) can be used as the networking stack. (docs: [`./examples/networking/`](./examples/networking/))\n- Security: The converted container runs in the sandboxed WASM (WASI) VM with the limited access to the host system.\n\n## WASI Runtimes Integration Status\n\n- :heavy_check_mark: : supported\n- :construction: : WIP\n\n- **NOTE**: WASI features not listed here are untested (future version will support more features)\n\n### x86_64 containers\n\n|runtime|stdio|mapdir|networking|note|\n|---|---|---|---|---|\n|wasmtime|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: (w/ [host-side network stack](./examples/networking/wasi/))||\n|wamr(wasm-micro-runtime)|:heavy_check_mark:|:heavy_check_mark:|:construction:||\n|wazero|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: (w/ [host-side network stack](./examples/networking/wasi/)||\n|wasmer|:construction: (stdin unsupported)|:heavy_check_mark:|:construction:|non-blocking stdin doesn't seem to work|\n|wasmedge|:construction: (stdin unsupported)|:heavy_check_mark:|:construction:|non-blocking stdin doesn't seem to work|\n\n### risc-v and other architecutre's containers\n\n|runtime |stdio|mapdir|networking|note|\n|---|---|---|---|---|\n|wasmtime|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: (w/ [host-side network stack](./examples/networking/wasi/))||\n|wamr(wasm-micro-runtime)|:heavy_check_mark:|:heavy_check_mark:|:construction:||\n|wazero|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: (w/ [host-side network stack](./examples/networking/wasi/))||\n|wasmer|:construction: (stdin unsupported)|:heavy_check_mark:|:construction:|non-blocking stdin doesn't seem to work|\n|wasmedge|:construction: (stdin unsupported)|:heavy_check_mark:|:construction:|non-blocking stdin doesn't seem to work|\n\n## Similar projects\n\nThere are several container runtimes support running WASM applications, but they don't run containers on WASM.\n\n- WASM on container runtimes\n  - Docker+Wasm integration: https://docs.docker.com/desktop/wasm/\n  - runwasi: https://github.com/containerd/runwasi\n  - youki: https://github.com/containers/youki\n  - crun: https://github.com/containers/crun\n  - krustlet: https://github.com/krustlet/krustlet\n\nThere are emulators that support running linux on WASM, but they don't support WASI.\n\n- x86 on WASM\n  - v86: https://github.com/copy/v86\n\n- RISCV on WASM\n  - TinyEMU: https://bellard.org/tinyemu/\n\nSome WASM API specs provides applications access to the host system.\nRe-compilation (and possibe re-implementation) of the application is needed.\n\n- WASI: https://github.com/WebAssembly/WASI\n- WASIX(WASI + additional syscall extensions): https://github.com/wasix-org\n\n## Additional Resources\n\n- [`./examples/`](./examples): Examples (python, php, on-browser, networking, etc.)\n- `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\n- [`./extras/imagemounter`](./extras/imagemounter/): A helper tool for enabling to distributing and running container images on browser without pre-conversion of the images.\n\n## Acknowledgement\n\n- container2wasm itself is licensed under Apache 2.0 but the generated WASM image will include third-pirty softwares:\n  - Bochs ([GNU Lesser General Public License v2.1](https://github.com/bochs-emu/Bochs/blob/master/LICENSE)) https://bochs.sourceforge.io/\n    - needs patches to make it work with containers: https://github.com/ktock/Bochs\n  - TinyEMU ([MIT License](https://opensource.org/license/mit/)) https://bellard.org/tinyemu/\n    - needs patches to make it work with containers: https://github.com/ktock/tinyemu-c2w\n  - GRUB ([GNU General Public License Version 3](https://www.gnu.org/licenses/gpl.html)): https://www.gnu.org/software/grub/\n  - BBL(riscv-pk) ([license](https://github.com/riscv-software-src/riscv-pk/blob/master/LICENSE)): https://github.com/riscv-software-src/riscv-pk\n  - Linux ([GNU General Public License version 2](https://github.com/torvalds/linux/blob/master/COPYING)): https://github.com/torvalds/linux/\n  - tini ([MIT License](https://github.com/krallin/tini/blob/master/LICENSE)): https://github.com/krallin/tini\n  - runc ([Apache License 2.0](https://github.com/opencontainers/runc/blob/main/LICENSE)): https://github.com/opencontainers/runc\n  - Binfmt ([MIT License](https://github.com/tonistiigi/binfmt/blob/master/LICENSE)): https://github.com/tonistiigi/binfmt\n  - QEMU ([license](https://github.com/qemu/qemu/blob/master/LICENSE)): https://github.com/qemu/qemu\n  - vmtouch ([license](https://github.com/hoytech/vmtouch/blob/master/LICENSE)): https://github.com/hoytech/vmtouch\n  - BusyBox ([GNU General Public License version 2](https://www.busybox.net/license.html)): https://git.busybox.net/busybox\n\n- On-browser example relies on the following softwares.\n  - xterm-pty ([MIT License](https://github.com/mame/xterm-pty/blob/main/LICENSE.txt)): https://github.com/mame/xterm-pty\n  - `browser_wasi_shim` (either of [MIT License](https://github.com/bjorn3/browser_wasi_shim/blob/main/LICENSE-MIT) and [Apache License 2.0](https://github.com/bjorn3/browser_wasi_shim/blob/main/LICENSE-APACHE)): https://github.com/bjorn3/browser_wasi_shim\n  - `gvisor-tap-vsock` ([Apache License 2.0](https://github.com/containers/gvisor-tap-vsock/blob/main/LICENSE)): https://github.com/containers/gvisor-tap-vsock\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcontainer2wasm%2Fcontainer2wasm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcontainer2wasm%2Fcontainer2wasm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcontainer2wasm%2Fcontainer2wasm/lists"}