Create a phoenix rest api with a dockerized postgresql databse

I’m trying to create a REST API following this guide: https://www.youtube.com/watch?v=LGY_eILc8Ks&list=PL2Rv8vpZJz4zM3Go3X-dda478p-6xrmEl&index=1.

I’m currently using:
Ubuntu 22.04 LTS
docker 24.0.7
elixir 1.17.2

Following the guide, i create and run a postgres container and try to create a project through the mix command.
I then configure the env.exs file as done in the second video.
At that point i run the mix ecto.create command, which fails with the following message:

`23:53:30.489 [error] Postgrex.Protocol (#PID<0.6242.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused - :econnrefused

23:53:30.491 [error] :gen_statem #PID<0.6242.0> terminating
** (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused - :econnrefused
(db_connection 2.7.0) lib/db_connection/connection.ex:104: DBConnection.Connection.handle_event/4
(stdlib 6.0.1) gen_statem.erl:3115: :gen_statem.loop_state_callback/11
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Queue: [internal: {:connect, :init}]
Postponed:
State: Postgrex.Protocol
Callback mode: &DBConnection.Connection.handle_event/4, state_enter: false

23:53:30.494 [error] Postgrex.Protocol (#PID<0.6248.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused - :econnrefused

23:53:30.494 [error] :gen_statem #PID<0.6248.0> terminating
** (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused - :econnrefused
(db_connection 2.7.0) lib/db_connection/connection.ex:104: DBConnection.Connection.handle_event/4
(stdlib 6.0.1) gen_statem.erl:3115: :gen_statem.loop_state_callback/11
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Queue: [internal: {:connect, :init}]
Postponed:
State: Postgrex.Protocol
Callback mode: &DBConnection.Connection.handle_event/4, state_enter: false
** (Mix) The database for Backend24h.Repo couldn’t be created: killed`

As far as i can tell by looking at other posts here this means there are no databases listening on the given port. But i can see and connect to the database by running psql in bash terminal opened in the container through a docker exec bash command, so the container is working properly

The videos i’ve linked don’t seem to imply there needs to be anything done besides creating and running the postgres container.

Am i doing something wrong or this linked to the fact that i use linux and not mac, some poor handling of docker, etc. ?

In a Docker setup you don’t use localhost, you always have some made-up name like docker.dev or whatever. So find out the host and put it in your config.

Let’s see your Docker command. Are you exposing the ports correctly, e.g. -p 5432:5432?.

Even if postgres exposed, the localhost reference used is the container localhost not the host where postgres exposed the port. You need to use a different hostname if you want to access the database via the host: https://medium.com/@TimvanBaarsen/how-to-connect-to-the-docker-host-from-inside-a-docker-container-112b4c71bc66

My 2 cents is to not follow that guide and just find a docker-compose example script and use that, for example like this one: Docker Compose setup for Elixir, Phoenix, and Postgres · GitHub . It will make your life easier as to connect the database you can just use db as hostname, no further setup required.

1 Like

So managed to make it work by following arcanemachine’s advice and re-running a container exposing the right port.

I wanna point out that the ecto.create command works with hostname: "localhost", despite the fact that is seemingly not the listed hostname of the container’s json you get when running docker inspect. I’m not quite sure i understand why that is but it does work.

My problem was also caused by renaming the databse in the dev.exs file, i thought it needed to match the container’s name but it does not.

So passing -p 5432:5432 to docker run and only modifying the username and password in the dev.exs file, while leaving other values as default, did the trick for me !

1 Like

Glad to see that it helped… I know that I’m outclassed by @D4no0 and @dimitarvp but I just expose the ports as I described, and can reach them via localhost from outside the container.

I think it would probably be better (from a security and isolation standpoint) to expose the ports over an internal Docker network via -p 5432, then you could use the custom hostnames as described by the others, and avoid exposing the port on the host machine (I think?!). But I only use Docker for dev work personally, so I don’t mind exposing ports to the host machine.

1 Like