How to run seeds.exs for Elixir/Phoenix App?

Hi Fellow Frequent Flyers! :wave:

We are trying to deploy a Phoenix app to Fly.io that requires some data to be initialised in the PostgreSQL DB.

We followed the Elixir getting started guide: Deploy an Elixir Phoenix Application and have done a bunch of googling/debugging and come to the conclusion that the /priv/repo/seeds.exs file is not available during the mix release … :man_shrugging:

So my/our question is: has anyone else faced this issue and how can we seed data into a freshly deployed Phoenix App? (or is there a generic approach to seeding data in any programming language/framework that we can adapt…?) :question:

Thanks! :pray:

1 Like

Hello!

Yes, the seeds aren’t auto-run. That’s a general situation with Elixir releases. Typically, you only want them run once. I like to write my seeds so they can be run multiple times (ie idempotent). However, it’s unique to each project and that means the solution is as well.

What I do is put the seeds into a regular module like MyApp.GlobalSetup. Then define a function like seed/0 or populate_pick_list_options or whatever.

Then SSH into an instance and run it in an IEx shell. Ex: MyApp.GlobalSetup.seed.

I hope that helps!

10 Likes

@Mark that’s very helpful/insightful. thanks very much. Will try and implement this tonight. :+1:

2 Likes

@Mark just to clarify, write the seed logic into a module, so not using seeds.exs or similar at all, i.e. don’t run the existing seed script from the new module?

Indeed. What worked for us was following @Mark’s advice and shifting the database initialisation code out of seeds.exs to a new file lib/init.ex and then invoking it from priv/repo/seeds.exs on localhost.

We didn’t run the seeds.exs on Fly.io rather we created an /init endpoint+controller that would run the Init.main/0 function idempotently. It’s probably more steps than a typical app would require but it meant we could have a nice initialisation (“status”) page for our app:

Bottom line: @Mark’s advice worked and we managed to overcome our Fly.io deployment block.

(Thanks again Mark!)

5 Likes

Nice, thanks for the response.

Thanks for sharing your process! I like the dev status page too!

2 Likes

@Mark

I come from React and Front End land and am a Elixir, Phoenix, Fly noob here. How exactly would I go about doing this? My assumption is that in the MyApp.GlobalSetup I would need to execute some kind of Mix.Task and like everything else I am doing right now writing a custom mix task is a first :joy: I am also assuming that the seeds.exs is copied to the fly server instance since the entire priv directory is copied in the Dockerfile

What I have stubbed out at the moment (that is making iEX scream):

defmodule GlobalSetup do
  @moduledoc """
  Module for any global setup that needs to be executed
  on Fly.io that I cannot just have done in the Dockerfile.
  """

  use Mix.Task

  @impl Mix.Task
  def run(_args) do
    Mix.shell().info("Seeding the database via seeds.exs...")
    Mix.shell().run("priv/repo/seeds.exs")
  end
end

Any pointers would be greatly appreciated! Btw love reading your content for Fly, I come across it regularly on Twitter.

It’s actually more simple than that, just put the contents of the seeder inside the module.

defmodule GlobalSetup do
  def run do
    # Insert things on database here
  end
end

:slight_smile:

1 Like

Ahhh awesome thanks for the nudge in the right direction @lubien :tada:

1 Like

Hi @rockchalkwushock! Yes, @lubien is right, the last bit to specify is that you can run that code through fly ssh console. Once you start an IEx session on your project, then can execute the seeds. Ex: GlobalSetup.run.

It’s fine that it’s a manual process because you only do it once when setting up your project.

Have fun!

1 Like

hey buddy, I am having a similar issue. I have a mix task that i want to run on iex shell but it is not working it says

** (UndefinedFunctionError) function Mix.Task.run/1 is undefined (module Mix.Task is not available)
    Mix.Task.run("app.start")

can you help me out here?

Hi @amirhussain,

Yes, “Mix” is not available in an Elixir release. It is a “dev” tool only. When deploying an Elixir app to Fly, the Dockerfile (generated by Phoenix) builds a “release”. This does not support mix tasks.

Please refer to the conversation here as it describes a way to write the operations you need into your application. Then they can be run through an IEx shell.

yes, I read the conversation here and it helped me. I just wanted to make sure. Thanks for replying.

1 Like

An other approach I found, is simply running the seed file from the iEX ssh console (fly ssh console --pty -C "/app/bin/myapp remote") with this function:

Code.compile_file "/app/lib/myapp-0.1.0/priv/repo/seeds.exs"

Be careful to investigate first your file path by doing fly ssh console.

Also, if you want to handle “dev” and “prod” at the same time in a function, you can handle that with a if condition or pattern match according to System.get_env("MIX_ENV") == "prod".

Dev and prod paths will be different if you reference other files.

Hope it helps !

4 Likes