FATAL: no pg_hba.conf entry for host "172.17.0.2", user "app", database "lab", no encryption means the server reached your connection but found no line in pg_hba.conf that matches that client address, user, database and connection type. Add a matching host line and reload the configuration; no restart is needed.

Read the four values in the message, write a rule that covers them (for example host lab app 172.17.0.0/16 scram-sha-256), run SELECT pg_reload_conf() and connect again.

The error

+ psql -h 172.17.0.2 -U app -d lab -c SELECT current_user
psql: error: connection to server at "172.17.0.2", port 5432 failed: FATAL:  no pg_hba.conf entry for host "172.17.0.2", user "app", database "lab", no encryption

Why it happens

pg_hba.conf is a list of rules read top to bottom; each says which connection type (local for the Unix socket, host for TCP), which databases, which users and which client addresses may connect, and how they must authenticate. PostgreSQL uses the first rule that matches. If none matches, it rejects the connection with this message, and a correct password does not help: in the reproduction the client had the right one.

The message lists exactly what was compared: the client address as the server sees it, the user, the database, and whether the connection was encrypted ("no encryption" here, because the server has no SSL configured). In the reproduction the only remote rule allowed 10.0.0.0/8, while the client came from the Docker bridge address 172.17.0.2. The same thing happens when an app moves to a new network, when a rule names one database and the app connects to another, or when a client connects over TCP where only local rules exist.

The fix

+ echo host    lab             app             172.17.0.0/16           scram-sha-256
+ tail -n 3 /var/lib/postgresql/18/docker/pg_hba.conf

host    all             all             10.0.0.0/8              scram-sha-256
host    lab             app             172.17.0.0/16           scram-sha-256
+ psql -U postgres -d lab -c SELECT pg_reload_conf()
 pg_reload_conf
----------------
 t
(1 row)

+ psql -U postgres -d lab -c SELECT line_number, type, database, user_name, address, netmask, auth_method, error FROM pg_hba_file_rules WHERE type = 'host' ORDER BY line_number
 line_number | type |   database    | user_name |  address   |                 netmask                 |  auth_method  | error
-------------+------+---------------+-----------+------------+-----------------------------------------+---------------+-------
         119 | host | {all}         | {all}     | 127.0.0.1  | 255.255.255.255                         | trust         |
         121 | host | {all}         | {all}     | ::1        | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | trust         |
         125 | host | {replication} | {all}     | 127.0.0.1  | 255.255.255.255                         | trust         |
         126 | host | {replication} | {all}     | ::1        | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | trust         |
         128 | host | {all}         | {all}     | 10.0.0.0   | 255.0.0.0                               | scram-sha-256 |
         129 | host | {lab}         | {app}     | 172.17.0.0 | 255.255.0.0                             | scram-sha-256 |
(6 rows)

+ psql -h 172.17.0.2 -U app -d lab -c SELECT current_user, inet_client_addr()
 current_user | inet_client_addr
--------------+------------------
 app          | 172.17.0.2
(1 row)

The line was appended to the file with >> (shown as the echo trace above). Find your file with SHOW hba_file; in the official Docker image it is /var/lib/postgresql/18/docker/pg_hba.conf. After the reload, the query on pg_hba_file_rules above listed the host rules as the server read them, with the new rule on line 129 and an empty error column.

Keep the rule as narrow as the need: the new line admits only user app to database lab. The same user connecting to postgres was still refused with the identical message, naming database "postgres". Avoid trust on any host line that is reachable from another machine.

How it was reproduced

A postgres:18 container (PostgreSQL 18.4, Debian build 18.4-1.pgdg13+1) on Docker 29.9.2. Its pg_hba.conf ends with host all all all scram-sha-256; a shell script inside the container created a test role app, narrowed that line to 10.0.0.0/8 with sed, reloaded, and connected with psql -h 172.17.0.2, the container's own bridge address, so the connection went over TCP. The script ran under sh -x, which is why the commands appear with a + prefix.

Frequently asked

How do I fix 'no pg_hba.conf entry for host'?
Add a host line to pg_hba.conf that matches the client address, user and database named in the message, then run SELECT pg_reload_conf(). A reload is enough; the server does not need a restart.
Where is pg_hba.conf in the PostgreSQL Docker image?
Run SHOW hba_file. In the postgres:18 image it is /var/lib/postgresql/18/docker/pg_hba.conf, inside the data directory, so it lives in the data volume.
What does 'no encryption' mean at the end of the message?
The connection was made without SSL. PostgreSQL reports the encryption state because pg_hba.conf rules can require it (hostssl) or forbid it (hostnossl), and it is one of the values the rules were matched against.

More decoded errors in the Fixes category. If the rule matches and the password is then refused, see password authentication failed (28P01).