🦒 Compile OCaml programs to WebAssembly (.wasm) online using a secure, containerized API.
![]() |
![]() |
docker build --load -t ocapi-sandbox -f Containerfile.sandbox .docker build --load -t ocapi -f Containerfile .
docker run -p 8080:8080 -v /var/run/docker.sock:/var/run/docker.sock ocapiCreate a docker-compose.yml file:
version: "3.9"
services:
ocapi:
image: ghcr.io/anmaped/ocapi:latest
container_name: ocapi
ports:
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
security_opt:
- no-new-privileges:true
restart: unless-stoppedThen deploy:
docker compose up -d
docker compose logs -f ocapiTo stop and destroy containers:
docker compose downsystemctl --user start podman.socket
ls $XDG_RUNTIME_DIR/podman/podman.sock
# Example output: /run/user/1000/podman/podman.sockNow, run the prebuilt image from the GitHub Container Registry (ghcr.io/anmaped/ocapi):
podman run --rm -d --security-opt label=disable --name ocapi-container -p 8080:8080 --net host -v /run/user/1000/podman/podman.sock:/var/run/docker.sock ghcr.io/anmaped/ocapi:latest
Alternatively, you can build the OCAPI server locally using Podman with the following command:
podman build -t ocapi -f Containerfile .curl -X POST http://localhost:8080/compile \
-H "Content-Type: application/json" \
-d '{"code": "print_endline \"Hello WebAssembly!\""}' \
--output output.wasm.js.zip
output.wasm.js.zipnow contains your compiled WebAssembly module and the glue JS code.
Workflow Overview:
flowchart TD
A[1. Client Request] -->|POST /compile with OCaml code| B[2. Sandboxed Execution]
B -->|Spawn ocapi-sandbox container| C[3. Compilation]
C -->|wasm_of_ocaml + dune| D[4. Output Packaging]
D -->|Package .wasm + JS glue| E[5. Response & Cleanup]
E -->|Return .zip & destroy container| A
Workflow Steps:
- Client Request — The client sends OCaml source code via a POST request to
/compile. - Sandboxed Execution — The REST API spawns a temporary, isolated container using the
ocapi-sandboximage. - Compilation — Inside the container,
wasm_of_ocamlanddunecompile the OCaml code to WebAssembly. - Output Packaging — The resulting
.wasmmodule and JavaScript glue code are packaged into a.ziparchive. - Response & Cleanup — The compiled assets (or compilation errors) are returned to the client, and the container is destroyed.
- Requires a running Docker or Podman daemon (socket must be mountable).
- Each request compiles in an ephemeral, isolated container; it is removed after completion.
- Only OCaml projects using
dune(andopamfor deps) are supported. - Produced artifacts (.wasm + JS glue) are zipped and streamed back; nothing is persisted.
- Enforce reasonable CPU / memory / time limits to mitigate abuse (adjust in server config).
- Avoid embedding secrets in submitted code; the sandbox is intended for untrusted snippets.
We welcome contributions! Follow this workflow:
git clone https://github.com/anmaped/ocapi.git
cd ocapieval $(opam env)
dune builddune exec ./server.exedune runtest- Create a branch:
git checkout -b feature/my-new-feature- Make your changes and commit:
git add .
git commit -m "Add my feature"- Push and create a pull request:
git push origin feature/my-new-feature- Ensure your code passes
dune runtestbefore submitting. - Use descriptive commit messages.
- Update the README if your change affects usage or deployment.

