Starting Elixir/Phoenix in production - confused by the messaging

This might be a basic question, but I couldn’t find any answers anywhere. I’ve spent a lot of time writing elixir code, not so much time deploying it.

FYI. I’m building on the server, because you know MacOS is great and all until you need to build for a server.

When I run MIX_ENV=prod mix phx.gen.release, I get the message with the following:

    # To build a release
    mix release

    # To start your system with the Phoenix server running
    _build/dev/rel/myapp/bin/server

I’m assuming that server command is just for testing that things work if someone is building locally, then planning to do a release locally that they push to a server. If I’m doing all this on the server, do I just start my server with that command, and skip the release stuff all together?

Regardless for now i’ve done the release, which gives me the following messaging:

Release created at _build/prod/rel/myapp

    # To start your system
    _build/prod/rel/myapp/bin/myapp start

Once the release is running:

    # To connect to it remotely
    _build/prod/rel/myapp/bin/myapp remote

    # To stop it gracefully (you may also send SIGINT/SIGTERM)
    _build/prod/rel/myapp/bin/myapp stop

I run the start command, and then I’m confused because it binds my shell, so I can’t really run remote or stop(unless from a separate shell), because i’d have to kill the server to get a shell back to run the stop command, which would no longer be needed because the server would be stopped.

Years ago when I deployed something else, I remember having a start command that didn’t bind the shell. This was pre-elixir releases though. I forget if it was exrm or distillery. I think distillery. But that would start the server, and not bind your shell. I’m assuming that’s more similar to:

daemon         Starts the system as a daemon

But considering I have to ignore the line telling me to start my server with _build/.../myapp start, input _build/.../myapp to see more commands, to see the daemon command, is why I’m asking this question. Is start a red-herring/intended for testing? Is daemon the way most people are actually starting apps in production? In my case(i.e. building on the server), should I just run _build/.../server and skip releases?

Sorry if this is common knowledge. I did search quite a bit for answers, but didn’t find anything.

1 Like

Seems like you want to run in a daemon mode. See mix release # Daemon mode (Unix-like)

Though, my dev workflow been: develop on mac, build a docker image in CI and run that image in a container in prod.
There we have bin/myapp start running in a container, just fine. Dockerfile is pretty much the one that default phx.gen.release generates.

It’s just a workflow with docker is slightly different.
We have a container running, and when needed, we start a new shell session in the container where we could do bin/myapp remote to attach iex shell to running app.

1 Like

That’s not what it is. Phoenix generates a additional …/bin/server binary besides …/bin/myapp, which automatically sets the PHX_SERVER env variable to true, which is picked up by config/runtime.exs to start up phoenix. It just delegates to …/bin/myapp start fron there.

So if you manually manage ENV variables there’s no need to use that additional server binary. You could remove it from rel/overlay/bin if you don’t need that. There’s also a migrate binary which is just a wrapper for a more complex command on …/bin/myapp.

You still need to build a release to use those commands. You could compare building a release with building a docker image. To be able to start a docker image you need to build that image first. You cannot start the source files directly.

You could use mix to start your application directly from source files, but I’d still suggest going the release route. That way if you eventually more to building releases not on the same machine things will continue to work. I’d generally suggest investing a few hours into building releases in CI, which in my experience is hardly more work than figuring out how to ship source files to your server to build a release there. I’d rather have the complexity somewhere in CI than on the prod server.

The expectation is that you’re not starting releases manually/by hand, but that you start the release using the service/init system of your server. This might be systemd, supervisord, initd, … depending on the OS. Those not only manage a single start of your application, but also restarts when the app goes down or the server restarts.

daemon can still put your app in the background, but that’ll neither restart the application if it crashes nor when the server restarts. It’s generally discouraged, but can be useful in testing and probably also exists to not break existing systems using that functionality.

3 Likes

Thank you. This is hugely helpful. I’ll look into systemd, as that might be exactly what I’m looking for!