Dyey517
Dyey517

Reputation: 586

Elixir/Phoenix Issue with deployment to AWS ECS: System.get_env/1 in prod.exs not retrieving environment variable defined in Task definition

I'm new to AWS deployment and facing an issue with my Elixir/Phoenix application.

I've deployed my app to AWS ECS, but I'm encountering a problem with environment variables.

All the configurations in prod.exs that fetch values from environment variables using System.get_env() are returning nil.

In my prod.exs file:

config :my_app, :my_variable, System.get_env("MY_VARIABLE")
...

And in my module:

defmodule MyApp.MyModule do
  @my_variable Application.compile_env(:my_app, :my_variable)

  def get_variable, do: Application.get_env(:my_app, :my_variable)
  ...
end

Both of these methods return nil.

However, strangely, System.get_env("DATABASE_URL") in runtime.exs works fine (the app won't function without a database connection). This indicates that the app can read the environment variables defined in the Task Definition.

Now, I'm confused about how runtime and compile time handle environment variables. How can I resolve this issue in my case? Where should I place my configurations? When should I inject environment variables for compile time?

Should I move all the configurations to runtime.exs and stop using Application.compile_env/2 ?

Help me please.

Upvotes: 0

Views: 101

Answers (1)

Everett
Everett

Reputation: 9628

Remember that prod.exs and the environment-specific config files are executed at build-time (i.e. when the app is compiled). Often in a deployment pipeline, this happens on a separate build machine (e.g. as part of a Github workflow). The environment variables set on that machine may have nothing to do with environment variables set on the machine where the app eventually runs.

My advice is to use System.fetch_env!/1 and other bang functions to read environment variables -- they will alert you immediately if there's a problem and they will help you further troubleshoot this issue.

I am the author of the dotenvy; that package seeks to help reduce the confusion created when reading from environment variables. The package may or may not be useful to you, but understanding the impetus behind it is helpful to think about when deploying your app. I wrote a couple articles to further ponder the subtleties that seem relevant to your problem: https://fireproofsocks.medium.com/configuration-in-elixir-with-dotenvy-8b20f227fc0e

The takeaways are to dig into how your app reads the environment variables, esp. compile-time vs. runtime. Leveraging runtime.exs over other compile-time config files has several advantages, but it is just one of many valid approaches to configuration. I favor it because it makes the app's contract with its environment more explicit and it avoids the opaqueness of using things like configuration providers, but any app has many factors which may suggest which configuration strategy might best fit.

Upvotes: 3

Related Questions