Elixir/Phoenix部署AWS ECS问题:prod.exs无法读取环境变量
Elixir/Phoenix部署AWS ECS环境变量问题解决
问题根源
Elixir的配置文件执行阶段有明确区分:
prod.exs在应用编译阶段执行,此时你的AWS ECS容器还未启动,任务定义里的环境变量还未注入,所以System.get_env()返回nil。runtime.exs在应用启动(运行时)阶段执行,此时容器已加载环境变量,所以能正常读取DATABASE_URL。
另外,Application.compile_env/2是在编译阶段读取配置,如果你拿的是运行时才会存在的变量,自然只能拿到nil;而Application.get_env/2是在运行时读取,只要配置在runtime.exs里正确设置,就能拿到值。
解决方案
将动态配置移至runtime.exs
把需要从环境变量读取的配置放到runtime.exs中:# runtime.exs config :my_app, :my_variable, System.get_env("MY_VARIABLE")这样应用启动时会读取ECS注入的环境变量,配置就能正常生效。
修改模块中的配置读取方式
模块里不要用Application.compile_env/2读取运行时动态配置,改用运行时读取的方式:defmodule MyApp.MyModule do # 移除编译时赋值的@my_variable,因为编译时还没有环境变量值 def get_variable, do: Application.get_env(:my_app, :my_variable) # 如果需要在模块内频繁使用,封装成函数(运行时调用才会获取值) defp my_variable, do: Application.get_env(:my_app, :my_variable) end
配置放置原则
- 留在prod.exs的配置:编译时就确定的静态配置,比如应用名称、固定的功能开关、不需要动态变化的参数。
- 移至runtime.exs的配置:所有需要从环境变量读取、运行时可能变化的配置,比如数据库地址、API密钥、第三方服务地址等。
编译时注入环境变量的场景
只有当配置是编译阶段必须确定的(比如某些依赖的编译选项、静态资源的编译路径),才需要在编译阶段注入环境变量。比如在构建Docker镜像的过程中(比如用Dockerfile的ARG或者ENV,或者在CodeBuild构建环节设置环境变量),让编译prod.exs时能拿到对应的值。但这种场景在普通Web应用部署中很少见,大部分动态配置都应该用runtime.exs处理。
是否需要全移至runtime.exs并停止使用Application.compile_env/2?
不需要全部迁移,也不需要完全停用Application.compile_env/2:
- 对于静态配置,继续放在prod.exs,用
Application.compile_env/2读取完全没问题,能提升运行时性能。 - 对于动态配置,必须放在runtime.exs,并且用
Application.get_env/2(或者Application.fetch_env!/2)在运行时读取。
内容的提问来源于stack exchange,提问作者Dyey517
相关产品推荐
相关产品推荐

