nanovms / ops

ops - build and run nanos unikernels
https://ops.city
MIT License
1.27k stars 132 forks source link

Cannot run executables (e.g. `mix`) with eyberg/elixir:1.8.1 #1353

Closed paulreimer closed 1 year ago

paulreimer commented 2 years ago

Nanos is so promising and I'm very excited to start using it for my new project(s)!

I am hoping to use Elixir to run a typical mix app, but have so far been unable to execute the mix binary using the eyberg/elixir:1.8.1 image.

I am trying to run it in this way:

ops pkg load eyberg/elixir:1.8.1 --verbose -p 8000 -f --accel=false -e "PATH=/sysroot/usr/lib/elixir/bin" -a "-S" -a "mix" -a "run" -a "--no-halt"

But I get this output / error:

 100% |████████████████████████████████████████|  [0s:0s]
booting /Users/paulreimer/.ops/images/erlexec ...
en1: assigned 10.0.2.15
warning: the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale"
 in your shell)
-S : Could not find executable mix

It's not really clear where to go from here; the intended command (elixir -S mix run --no-halt) does work locally, and I have seen that /sysroot/usr/lib/elixir/bin/mix does exist in the image via ops pkg contents ....

eyberg commented 2 years ago

so we basically created a clone of elixir for this package - if you look at the manifest you can see what exactly is being executed:

eyberg@box:~/test/kv$ cat ~/.ops/packages/eyberg/elixir_1.8.1/package.manifest
{
  "Program": "/usr/local/lib/erlang/erts-11.0/bin/erlexec",
  "Version": "1.8.1",
  "Env": {
    "HOME": "/",
    "ROOTDIR": "/usr/local/lib/erlang",
    "BINDIR": "/usr/local/lib/erlang/erts-11.0/bin",
    "EMU": "beam",
    "PROGNAME": "hi"
  },
 "Args": ["/usr/local/lib/erlang/erts-11.0/bin/erlexec", "-pa",
"/usr/lib/elixir/bin/../lib/eex/ebin",
"/usr/lib/elixir/bin/../lib/elixir/ebin",
  "/usr/lib/elixir/bin/../lib/ex_unit/ebin",
"/usr/lib/elixir/bin/../lib/iex/ebin",
"/usr/lib/elixir/bin/../lib/logger/ebin",
  "/usr/lib/elixir/bin/../lib/mix/ebin", "-elixir", "ansi_enabled",
"true", "-noshell", "-s", "elixir", "start_cli", "-extra"]
}

all of this ends up calling 'mix' which itself is an elixir script which on my system looks like so:

eyberg@box:~/test/kv$ which mix
/usr/bin/mix
eyberg@box:~/test/kv$ cat /usr/bin/mix
#!/usr/bin/env elixir
Mix.start
Mix.CLI.main

following along via https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html

so we'll want to fake it if used here and load up anything else in our project using the 'files' and 'dirs' variables (there are other ways you can do this including 'mapdirs') ->

eyberg@box:~/test/kv$ cat config.json
{
  "BaseVolumeSz": "200m",
  "Files": ["fake.exs", "mix.exs"],
  "Dirs": ["_build", "config", "lib", "test"]
}
eyberg@box:~/test/kv$ cat fake.exs
Mix.start()
Mix.CLI.main()

then we can for example run the tests:

eyberg@box:~/test/kv$ ops pkg load eyberg/elixir:1.8.1 -c config.json -a "fake.exs" -a "test"
booting /home/eyberg/.ops/images/erlexec ...
en1: assigned 10.0.2.15
warning: the VM is running with native name encoding of latin1 which may cause Elixir to malfunction as it expects utf8. Please ensure your locale is set to UTF-8 (which can be verified by running "locale" in your shell)
..

Finished in 0.1 seconds
1 doctest, 1 test, 0 failures

Randomized with seed 109751

ymmv with mix, though cause it looks like there are a handful of situations where it might want to spawn a subshell which wouldn't be supported but for your basic daemonized commands (like an app server) you should be ok

paulreimer commented 1 year ago

This all works perfectly with eyberg/elixir:1.13.4. I wasn't able to get it working with elixir:1.8.1 when I tried previously, but I am much happier with elixir 1.13.x anyway!