mix ecto.create 无法连接到 Postgres,即使 Postgres 是 运行 并且凭据正确

mix ecto.create can't connect to Postgres even though Postgres is running and the credentials are correct

我创建了一个新的 Phoenix 项目并检查了 config/dev.exs 中的凭据,它们是:

config :blog, Blog.Repo,
  adapter: Ecto.Adapters.Postgres,
  username: "postgres",
  password: "postgres",
  database: "blog_dev",
  hostname: "localhost",
  pool_size: 10

现在,数据库 blog_dev 不存在,但据我(初学者水平)的理解,如果 mix ecto.create 不存在,则应该创建它。所以我 运行:

mix ecto.create

哪个给了我错误

localhost:blog alex$ mix ecto.create
warning: found quoted keyword "test" but the quotes are not required. Note that keywords are always atoms, even when quoted. Similar to atoms, keywords made exclusively of Unicode letters, numbers, underscore, and @ do not require quotes
  mix.exs:57


18:04:24.675 [error] GenServer #PID<0.212.0> terminating
** (DBConnection.ConnectionError) tcp recv: closed
    (db_connection) lib/db_connection/connection.ex:163: DBConnection.Connection.connect/2
    (connection) lib/connection.ex:622: Connection.enter_connect/5
    (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: nil
State: Postgrex.Protocol
** (Mix) The database for Blog.Repo couldn't be created: an exception was raised:
    ** (DBConnection.ConnectionError) tcp recv: closed
        (db_connection) lib/db_connection/connection.ex:163: DBConnection.Connection.connect/2
        (connection) lib/connection.ex:622: Connection.enter_connect/5
        (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

This answer on Whosebug 提示这种错误一般出现在Postgres不是运行的时候。所以我这样检查:

localhost:blog alex$ brew services list
Name                       Status  User Plist
postgresql                 started

我还认为我的凭据不正确,所以我尝试使用 config/dev.exs 中的凭据手动登录 Postgres,如下所示:

localhost:blog alex$ psql postgres postgres -W
Password: 
psql (11.3)
Type "help" for help.

postgres=#

我输入的密码是'postgres'。有没有人对这里可能发生的事情有任何建议?谢谢!

Which gave me the error

localhost:blog alex$ mix ecto.create warning: found quoted keyword "test" but the quotes are not required. mix.exs:57

您应该做的第一件事是修复所有您能够修复的 warnings/errors。那么,您的 mix.exs 文件在第 57 行是什么样子的?

您需要做四件事来创建您的数据库:

1) 在mix.exs:

  defp deps do [
    ...
    ...
    {:ecto_sql, "3.0.3"},  # whatever versions you want here
    {:postgrex, "0.14.1"},
    {:phoenix_ecto, "~>4.0"}
  ]

2) 在config/config.exs:

config :blog,
  ecto_repos: [Blog.Repo]

3) 在config/dev.exs:

config :blog, Blog.Repo,
  database: "blog_dev",

  username: "postgres",
  password: "postgres",

  hostname: "localhost",
  port: "5432",

  show_sensitive_data_on_connection_error: true,
  pool_size: 10

您需要弄清楚您的 postgres 服务器 运行 在哪个端口上。我的 (Postgres.app) 默认在端口 5432 上运行。

3) 在lib/blog/repo.ex:

defmodule Blog.Repo do
  use Ecto.Repo,
    otp_app: :blog,
    adapter: Ecto.Adapters.Postgres
end

4) .../phoenix_apps/blog$ mix ecto.create

在 Elixir 1.8.2/OTP 21 上从 docker 和 Phoenix 1.4.9 运行 中提取的 Postgres 11.4 在应用程序连接到默认 5432 端口时工作正常。

docker pull postgres:11.4
docker run --rm --name pg-docker -e POSTGRES_PASSWORD=postgres -d -p 5434:5432 postgres:11.4
mix archive.install hex phx_new 1.4.9
mix phx.new blog
mix ecto.create

# Compiling 13 files (.ex)
# Generated blog app
# The database for Blog.Repo has been created

请注意,在上面的示例中,本地端口 5434 映射到 postgres 侦听的容器端口 5432。如果我们现在将映射更改为 5434:57885788 是 postgres 未使用的随机端口值,则设置会中断并出现类似于您所看到的错误。

docker container stop pg-docker
docker run --rm --name pg-docker -e POSTGRES_PASSWORD=postgres -d -p 5434:5788 postgres:11.4
mix ecto.create

# 11:25:32.876 [error] GenServer #PID<0.217.0> terminating
# ** (DBConnection.ConnectionError) tcp recv: closed
#     (db_connection) lib/db_connection/connection.ex:87: DBConnection.Connection.connect/2
#     (connection) lib/connection.ex:622: Connection.enter_connect/5
#     (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
# Last message: nil
# State: Postgrex.Protocol
# ** (Mix) The database for Blog.Repo couldn't be created: killed

这意味着您的应用会尝试与关闭的端口建立 TCP 连接。

换句话说,检查您的 postgres 配置并确保您连接的端口是 postgres 侦听的端口。