🔥

dockerのpostgresにlocalhost指定で接続できない

に公開

環境

os: macOS 26.0.1
dockerDesktop: 4.39.0

事象

以下のcompose.yamlを記述した上で docker-compose up -dを実行し、無事postgresが立ち上がった。

services:
  postgres:
    container_name: postgres
    image: postgres:16.1
    environment:
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=admin
      - POSTGRES_DB=${POSTGRES_DB} 
    ports:
      - "5432:5432"
    restart: always


portも通ってる。
ところが、PgAdminから入ろうとすると以下のエラーとなった

Unable to connect to server: connection failed: connection to server at "127.0.0.1", port 5432 failed: FATAL: role "admin" does not exist Multiple connection attempts failed. All failures were: - host: 'localhost', port: '5432', hostaddr: '::1': connection failed: connection to server at "::1", port 5432 failed: FATAL: role "admin" does not exist - host: 'localhost', port: '5432', hostaddr: '127.0.0.1': connection failed: connection to server at "127.0.0.1", port 5432 failed: FATAL: role "admin" does not exist

adminロールがない??

原因の概要

結論だけ話すと、brew経由でpostgresが立ち上がっており、そちらに接続されてしまったが為にadminロールはないよ~~と怒られていました。

解決策

主に2つあると思います。

1.brew で動いてる postgresを止める

brew services stop postgresql

もしくは、バージョンを指定して

brew services stop postgresql@14

等で素直にbrew側を止めてあげる。
筆者はこちらで対応しました。

2.portを変える

被ってたらbrew側が優先されてしまうので大人しくportを変えれば競合せず使えそう。(未実施)

以上です!!もしも治らない場合は別の原因が考えられるのでよければコメントで共有してください!

(余談)原因の詳細

ここからは余談になります。

別のpostgresのDBに繋がったのはわかりましたが、ではなぜ docker psで見た際に 0.0.0.0:5432->5432/tcp となっているのにbrew側のdbにつながってしまうのか??

これはmacOSで dockerDesktopを利用してることが原因の通信問題です。
まず、dockerDesktopは、macOS上で仮想VMを稼働させ、その中で動きます。
つまり、実際に通信を行う際は macOS→NAT→Docker VM→ 各dockerコンテナ となります。
そして、docker ps で出てくる 0.0.0.0:5432->5432/tcpはまさにNATの行ってる内容で、

「MacOSのport 5432に通信されたら、dockerの0.0.0.0:5432に繋ぐで~~」
という約束の内容になります。つまり、実際のmacOSのport5432をバインドして、確保してるわけではないんですね。あくまで、ここに通信されたらdockerへ経由するでという約束に過ぎないわけです。

なので、brewのpostgresが5432portで起動されてる状況も、docker側が0.0.0.0:5432->5432/tcpとなってる状況も成立してしまいます。
したがって、localhostや127.0.0.1へ通信を行うと、まず先にmacOSのport5432へ接続を行なってしまうためdockerの方へは通信が届かないというわけです。

おもしろ~~~~

更なる余談ですが、この時hostのIPアドレスを自身のローカルIPアドレスにするとなんとdocker側へ繋がります。
理由は有志の方々に指摘いただきながら調査中です。

  • brew側のpostgresはデフォルトでlocalhostしかlistenしないため、dockerの方に通信が流れる?
  • ローカルIPアドレスへのアクセスは一度NICを経由することになるので、なんやかんやでdockerが優先されてる?
    誠意調査中です。

Discussion