Nerves Weather Station Book Issue with mix ecto.setup: (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused

I am working through the book by Koutmos, Tate and Hunleth. I have the sensors collecting data and am trying to set up Postgresql and ecto. I have created the yml file and have Posgresql running with “docker compose up” but I had to use “sudo docker compose up”. I then created the migration with “mix ecto.gen.migration set_up_weather_data_table” and edited the resulting file as per the book (page 49). When I perform the next step which is to run “mix ecto.setup” in the weather_tracker directory I get the following error:

**22:21:17.144 \[error\] Postgrex.Protocol (#PID<0.196.0>) failed to connect: \*\* (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused - :econnrefused**

**22:21:17.153 \[error\] :gen_statem #PID<0.196.0> terminating**
**\*\* (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused - :econnrefused**
**(db_connection 2.8.1) lib/db_connection/connection.ex:109: DBConnection.Connection.handle_event/4**
**(stdlib 7.2) gen_statem.erl:3743: :gen_statem.loop_state_callback/11**
**(stdlib 7.2) proc_lib.erl:333: :proc_lib.init_p_do_apply/3**
**Process Label: “db_conn_1”**
**Queue: \[internal: {:connect, :init}\]**
**Postponed: [ ]**
**State: Postgrex.Protocol**
**Callback mode: :handle_event_function, state_enter: false**

**22:21:17.162 \[error\] Postgrex.Protocol (#PID<0.202.0>) failed to connect: \*\* (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused - :econnrefused**

**22:21:17.162 \[error\] :gen_statem #PID<0.202.0> terminating**
**\*\* (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused - :econnrefused**
**(db_connection 2.8.1) lib/db_connection/connection.ex:109: DBConnection.Connection.handle_event/4**
**(stdlib 7.2) gen_statem.erl:3743: :gen_statem.loop_state_callback/11**
**(stdlib 7.2) proc_lib.erl:333: :proc_lib.init_p_do_apply/3**
**Process Label: “db_conn_1”**
**Queue: \[internal: {:connect, :init}\]**
**Postponed: [ ]**
**State: Postgrex.Protocol**
**Callback mode: :handle_event_function, state_enter: false**
**\*\* (Mix) The database for WeatherTracker.Repo couldn’t be created: killed**

I tried running “sudo mix ecto.setup” from the same directory (just in case I need the extra permissions) and it tells me sudo: mix: command not found.

Not sure where to go from here. Any suggestions anyone?

Thanks.

Just want to mention couple things:

  • You probably have to call sudo when you run docker compose up because you didn’t add your user to the docker group. If you’re on Linux, run sudo usermod -aG docker $USER, then log out and log back in. If not, check the Docker install guide and make sure you follow the correct post-install instructions for your OS.

The previous point won’t address your actual issue though, it will just prevent you from needing to add sudo when calling docker.

The actual issue is probably that the port isn’t being correctly exposed from the container.

To check if the port is exposed, you can install nmap (sudo apt install nmap if you’re on Ubuntu/Debian) and scan the port to make sure it’s actually visible from outside the container:

$ nmap -p 5432 0.0.0.0

Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-01-11 22:54 MST
Nmap scan report for 0.0.0.0
Host is up (0.000083s latency).

PORT     STATE SERVICE
5432/tcp open  postgresql

Nmap done: 1 IP address (1 host up) scanned in 0.10 seconds

If the port for Postgres (or Timescale or whatever) is exposed, you should

If it says the port is “open” and you’re still getting the “connection refused” error, then I’m stumped (maybe bad credentials? But I don’t think you’re even getting that far). But I’m assuming it will say the port is “closed”.

Make sure the port is exposed correctly in your Docker Compose file:

docker-compose.yml (or compose.yaml, whichever one the book uses)

services:
  your-postgres-service:
    image: postgres:blah-version
    ports:
      - 5432:5432

When you run docker compose up, port 5432 should be open.

If that doesn’t work, you can bypass Docker container networking stack by adding network_mode: host.

docker-compose.yml (or compose.yaml, whichever one the book uses)

services:
  your-postgres-service:
    image: postgres:blah-version
    # ports:
    #   - 5432:5432
    network_mode: host

Now, when you run docker compose up, it should DEFINITELY work. If so, then double check the previous port config, and make sure it’s set correctly. (Were you maybe using 5432 instead of 5432:5432? That won’t work.)

If not, then some random ideas:

  • Try running docker compose down to reset the compose service.
  • Try logging out and back in, or restarting the computer.

Other than that, I have no idea. Maybe post your Docker Compose YAML file in that case.

Hope this helps!

2 Likes

Thanks for the great reply.
I fixed the issue of requiring sudo to run the docker compose command according to your instructions.
When I run the netstat command it tells me that the port is closed.
PORT STATE SERVICE
5432/tcp closed postgresql

This is my yaml file:
services:
postgres:
image: timescale/timescaledb:2.18.0-pg14
ports:
- ‘5432:5432’
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres

volumes:
postgres-data: {}

And this is the output when I run docker compose up:
WARN[0000] No services to build
Attaching to postgres-1
postgres-1 |
postgres-1 | PostgreSQL Database directory appears to contain a database; Skipping initialization
postgres-1 |
postgres-1 | 2026-01-12 19:19:09.326 UTC [1] LOG: starting PostgreSQL 14.15 on x86_64-pc-linux-musl, compiled by gcc (Alpine 13.2.1_git20240309) 13.2.1 20240309, 64-bit
postgres-1 | 2026-01-12 19:19:09.326 UTC [1] LOG: listening on IPv4 address “0.0.0.0”, port 5432
postgres-1 | 2026-01-12 19:19:09.326 UTC [1] LOG: listening on IPv6 address “::”, port 5432
postgres-1 | 2026-01-12 19:19:09.332 UTC [1] LOG: listening on Unix socket “/var/run/postgresql/.s.PGSQL.5432”
postgres-1 | 2026-01-12 19:19:09.339 UTC [27] LOG: database system was shut down at 2026-01-12 19:19:06 UTC
postgres-1 | 2026-01-12 19:19:09.347 UTC [1] LOG: database system is ready to accept connections
postgres-1 | 2026-01-12 19:19:09.349 UTC [33] LOG: TimescaleDB background worker launcher connected to shared catalogs

It seems to me it is the fact that the TCP port is closed. Is that an internal firewall issue?

Yeah, no clue here. It should work, based on what I’m seeing. You tried network_mode: host?

I had not tried that but I just attempted it now and it seems to have worked.

Thanks for your help!!!

No problem. Hopefully you can get it working the old-fashioned way. Maybe try reinstalling Docker at some point?

Host networking is a nice workaround, but using Docker’s network layer is nice since you can have multiple instances of the same application running, even appearing on the same port (e.g. multiple instances of Postgres which appear, to the other Docker containers, to be on port 5432.).