Running micro-services, implemented in Ocaml

I don’t run my OCaml services in docker, but I do run them in a very constrained bubblewrap container.

First, it’s relatively easy to statically compile OCaml binaries in a docker container to reduce their dependencies on the guest:

Create a Dockerfile:

FROM ocaml/opam2:alpine-3.8-ocaml-4.07

RUN git pull && opam update && opam switch create 4.07.1+flambda && \
    eval $(opam env) && \
    opam depext --install cmdliner cohttp-lwt-unix conf-libev containers

The build commands will then be:

docker build -t my-ocaml-container .
docker run --volume=$PWD:/build/ -it my-ocaml-container make -C /build/ static

Add -ccopt -static to your build commands, for example using dune:

(env (release-static (flags (:standard -ccopt -static))))

And invoke it like this: dune build --profile release-static main.exe

You can drop the statically compiled binary on basically any Linux host, even without access to /usr, /bin etc. In my case:

bwrap
    --tmpfs / \
    --ro-bind /app/ /app/ \
    --bind /app/log/ /app/log/ \
    --dev /dev \
    --tmpfs /tmp/ \
    --ro-bind /etc/resolv.conf /etc/resolv.conf \
    --ro-bind /etc/localtime /etc/localtime \
    --remount-ro / \
    --new-session \
    --unshare-all --share-net \
    {cmd}

More infos:

11 Likes