在CircleCI部署Elixir/Phoenix应用时遇Postgres :username未找到错误
我在把Elixir/Phoenix应用部署到CircleCI时踩了个坑——添加配置文件后反复调试都跑不起来,每次都会抛出**(KeyError)**错误,说关键字列表里找不到:username键,完整的错误栈信息是这样的:
** (KeyError) 错误,提示在关键字列表[types: Postgrex.DefaultTypes, backoff_type: :stop, pool: DBConnection.Connection, database: "postgres", otp_app: :todo_with_auth, repo: TodoWithAuth.Repo, timeout: 15000, pool_timeout: 5000, adapter: Ecto.Adapters.Postgres, hostname: "localhost", pool_size: 10]中未找到:username键
(elixir) lib/keyword.ex:343: Keyword.fetch!/2
(postgrex) lib/postgrex/protocol.ex:548: Postgrex.Protocol.startup/2
(postgrex) lib/postgrex/protocol.ex:475: Postgrex.Protocol.handshake/2
(db_connection) lib/db_connection/connection.ex:134: DBConnection.Connection.connect/2
(connection) lib/connection.ex:622: Connection.enter_connect/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
下面是我的配置文件信息:
CircleCI配置文件(.circleci/config.yml)
# Elixir CircleCI 2.0 configuration file # # Check https://circleci.com/docs/2.0/language-elixir/ for more details version: 2 jobs: build: docker: # specify the version here - image: circleci/elixir:1.4 # Specify service dependencies here if necessary # CircleCI maintains a library of pre-built images # documented at https://circleci.com/docs/2.0/circleci-images/ - image: circleci/postgres:9.4 working_directory: ~/repo steps: - checkout # specify any bash command here prefixed with `run: ` - run: mix local.hex --force - run: mix local.rebar - run: mix deps.get - run: mix ecto.create - run: mix test
测试环境配置(test.exs)
config :todo_with_auth, TodoWithAuth.Repo, adapter: Ecto.Adapters.Postgres, username: "postgres", password: "postgres", database: "todo_with_auth_test", hostname: "localhost", pool: Ecto.Adapters.SQL.Sandbox
dev.exs的配置和test环境差不多,但里面的username和password行被我注释掉了。
问题排查与解决思路
1. 核心原因:环境加载错误
从错误信息里的数据库名是postgres而不是你test.exs里配置的todo_with_auth_test就能看出来——CircleCI默认跑的是dev环境!而你的dev.exs里注释掉了用户名和密码,自然会报找不到:username的错误。
2. 快速修复:强制指定测试环境
修改CircleCI配置里的mix命令,明确加上MIX_ENV=test,让它加载测试环境的配置:
- run: MIX_ENV=test mix ecto.create - run: MIX_ENV=test mix test
3. 额外保障:配置Postgres服务的环境变量
虽然CircleCI的Postgres镜像默认用户名密码就是postgres,但显式声明环境变量能避免一些奇怪的连接问题,修改Docker服务部分:
- image: circleci/postgres:9.4 environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: todo_with_auth_test
4. 调试技巧:打印当前Repo配置
如果还是有问题,可以加个调试步骤,看看当前加载的Repo配置到底是什么样的:
- run: MIX_ENV=test mix run -e "IO.inspect(TodoWithAuth.Repo.config())"
这行命令会输出当前的Repo配置参数,你可以直接看到有没有:username和:password,方便定位问题。
5. 检查通用配置(config.exs)
确保config.exs里的Repo默认配置没有覆盖测试环境的参数,比如config.exs里应该只保留通用配置:
config :todo_with_auth, TodoWithAuth.Repo, adapter: Ecto.Adapters.Postgres, otp_app: :todo_with_auth
具体的用户名、密码、数据库名这些,交给test.exs和dev.exs各自去配置。
一般来说,只要强制指定测试环境就能解决这个问题,你可以先试试这个方案,如果还有其他问题再进一步排查。
内容的提问来源于stack exchange,提问作者Felipe Skinner

