Docker PostgreSQL服务:无法绑定IPv6套接字:无法分配请求的地址

时间:2017-10-09 21:32:02

标签: postgresql docker

我正在使用Docker运行PostgreSQL服务。出于某种原因,PostgreSQL希望绑定到IPV6 - 虽然我没有在任何地方指定(至少就我所知)。

因此,我无法连接到PG。相关细节如下:

Dockerfile

FROM postgres:9.6

RUN apt-get update \
 && apt-get -y install apt-utils \
 && apt-get -y install python3 \
 && apt-get -y install postgresql-plpython3-9.6

COPY sql /docker-entrypoint-initdb.d/ 

EXPOSE 5432

# Add VOLUMEs to allow backup of config, logs and databases
VOLUME  ["/etc/postgresql", "/var/log/postgresql", "/var/lib/postgresql"]

PostgreSQL日志文件内容

LOG:  received fast shutdown request
LOG:  aborting any active transactions
waiting for server to shut down....LOG:  autovacuum launcher shutting down
LOG:  shutting down
LOG:  database system is shut down
 done
server stopped

PostgreSQL init process complete; ready for start up.

LOG:  could not bind IPv6 socket: Cannot assign requested address
HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
LOG:  database system was shut down at 2017-10-09 21:22:22 UTC
LOG:  MultiXact member wraparound protections are now enabled
LOG:  database system is ready to accept connections
LOG:  autovacuum launcher started

我使用以下命令运行容器:docker run --name my_db_service_cntnr image_tag

当我运行以下命令时:docker container port my_db_service_cntnr,我什么都没有回复:

me@yourbox:~/path/to/pgdb$ docker container port my_db_service_cntnr 
me@yourbox:~/path/to/pgdb$ 

我知道PostgreSQL正在容器中运行:

me@yourbox:~/path/to/pgdb$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
824ffe17c5b9        df:pg               "docker-entrypoint..."   16 hours ago        Up 5 minutes        5432/tcp            my_db_service_cntnr


me@yourbox:/path/to/pgdb$ docker container inspect my_db_service_cntnr | grep Address
            "LinkLocalIPv6Address": "",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "GlobalIPv6Address": "",
            "IPAddress": "172.17.0.2",
            "MacAddress": "02:42:ac:11:00:02",
                    "IPAddress": "172.17.0.2",
                    "GlobalIPv6Address": "",
                    "MacAddress": "02:42:ac:11:00:02"

然而,当我尝试连接到PostgreSQL(使用默认端口5432)时,它无法连接到数据库:

尝试通过psql连接

me@yourbox:~/path/to/pgdb$ psql -h 172.17.0.2 -U postgres -p 5432
psql: could not connect to server: Connection refused
        Is the server running on host "172.17.0.2" and accepting
        TCP/IP connections on port 5432?
me@yourbox:~/path/to/pgdb$ 

虽然我指定了PG图像EXPOSE端口5432:

me@yourbox:~/path/to/pgdb$ sudo lsof -i -P | grep -i "listen"
lighttpd  1477  www-data    4u  IPv4  22342      0t0  TCP *:80 (LISTEN)
dnsmasq   1645    nobody    5u  IPv4  26954      0t0  TCP CEBERUS:53 (LISTEN)
master    2182      root   12u  IPv4  28720      0t0  TCP localhost:25 (LISTEN)
master    2182      root   13u  IPv6  28721      0t0  TCP ip6-localhost:25 (LISTEN)
rhythmbox 3149        me   17u  IPv4  33925      0t0  TCP *:3689 (LISTEN)
rhythmbox 3149        me   18u  IPv6  33926      0t0  TCP *:3689 (LISTEN)
cupsd     8432      root   10u  IPv6  87004      0t0  TCP ip6-localhost:631 (LISTEN)
cupsd     8432      root   11u  IPv4  87005      0t0  TCP localhost:631 (LISTEN)

导致此错误的原因是什么,我该如何解决?

1 个答案:

答案 0 :(得分:8)

这不是一个完整的答案,但应该让你更接近答案。它涵盖了问题中调试步骤所需的dockerism。

运行postgres容器

$ CID=$(docker run -d postgres)
$ echo $CID
48024dc71aa446...

获取容器的PID

$ PID=$(docker inspect -f {{.State.Pid}} $CID)
$ echo $PID
7994

从容器中获取日志,检查错误。

$ docker logs $CID

容器中的处理列表

$ docker exec -ti $CID ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
postgres     1     0  0 23:19 ?        00:00:00 postgres
postgres    49     1  0 23:19 ?        00:00:00 postgres: checkpointer process  
postgres    50     1  0 23:19 ?        00:00:00 postgres: writer process  
postgres    51     1  0 23:19 ?        00:00:00 postgres: wal writer process  
postgres    52     1  0 23:19 ?        00:00:00 postgres: autovacuum launcher pr
postgres    53     1  0 23:19 ?        00:00:00 postgres: stats collector proces
postgres    54     1  0 23:19 ?        00:00:00 postgres: bgworker: logical repl
root        66     0  0 23:26 ?        00:00:00 ps -ef

在容器中运行ss寻找侦听tcp进程(如lsof

$ docker exec -ti $CID ss -lntp
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128          *:5432                     *:*                  
LISTEN     0      128         :::5432                    :::*

容器外部不会报告容器命名空间中的端口

$ ss -lntp
State      Recv-Q Send-Q                         Local Address:Port                                        Peer Address:Port              
LISTEN     0      128                                        *:22                                                     *:*                   users:(("sshd",pid=592,fd=3))
LISTEN     0      128                                       :::22                                                    :::*                   users:(("sshd",pid=592,fd=4))

从主机,您可以使用nsenter输入容器命名空间并运行命令。

$ nsenter -t $PID -n ss -lntp
State      Recv-Q Send-Q                         Local Address:Port                                        Peer Address:Port              
LISTEN     0      128                                        *:5432                                                   *:*                   users:(("postgres",pid=7994,fd=3))
LISTEN     0      128                                       :::5432                                                  :::*                   users:(("postgres",pid=7994,fd=4))

$ nsenter -t $PID -n ip address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
52: eth0@if53: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 scope global eth0
       valid_lft forever preferred_lft forever

从Docker获取容器的IP

$ IP=$(docker inspect -f '{{.NetworkSettings.Networks.bridge.IPAddress}}' $CID)
$ echo $IP
172.17.0.3

测试连接

$ psql -h $IP -U postgres -p 5432

映射端口

使用映射端口,主机上的端口稍微改变

$ CID=$(docker run -d -p 5432:5432 postgres)
$ echo $CID
020f72394fcd...

现在容器已配置端口

$ docker container port $CID
5432/tcp -> 0.0.0.0:5432

$ docker inspect -f {{.NetworkSettings.Ports}} $CID
map[5432/tcp:[{0.0.0.0 5432}]]

该端口也将在主机上监听

$ ss -lntp
State      Recv-Q Send-Q                         Local Address:Port                                        Peer Address:Port              
LISTEN     0      128                                        *:22                                                     *:*                   users:(("sshd",pid=592,fd=3))
LISTEN     0      128                                       :::22                                                    :::*                   users:(("sshd",pid=592,fd=4))
LISTEN     0      128                                       :::5432                                                  :::*                   users:(("docker-proxy",pid=8571,fd=4))

您现在可以连接到localhost或主机IP

$ psql -h 127.0.0.1 -U postgres -p 5432