我正在尝试使用Docker Compose创建两个容器:一个包含PostgreSQL(实际上是PostGIS),另一个包含一个查询PostgreSQL的Web应用程序。
我的docker-compose.yaml是:
version: '3.1'
services:
db:
build:
context: .
dockerfile: Dockerfile-db
restart: always
ports:
- 5432:5432
web:
build:
context: .
dockerfile: Dockerfile-web
args:
PGHOSTADDR: db
restart: always
ports:
- 80:80
depends_on:
- db
应用程序Dockerfile是:
FROM php:apache
ARG PGHOSTADDR
ENV PGHOSTADDR=$PGHOSTADDR
COPY . /var/www/html/
RUN apt-get update && mkdir -p /usr/share/man/man1 /usr/share/man/man7 && apt-get install -y postgresql-client strace ltrace iputils-ping bind9-host dnsutils
CMD until psql -c '\q' ; do sleep 1 ; done ; /usr/sbin/apache2
PostgreSQL Dockerfile只是:
FROM mdillon/postgis
PostgreSQL容器启动并且似乎完美运行 - 我可以从主机查询它,只要我使用PostgreSQL容器的IP地址,我就可以从应用程序容器中查询它。
但是,在app容器中运行的“psql”无法访问PostgreSQL:
$ docker-compose up -d && echo MARK && docker-compose logs --follow web
WARNING: The Docker Engine you're using is running in swarm mode.
Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.
To deploy your application across the swarm, use `docker stack deploy`.
Starting myapp_db_1 ...
Starting myapp_db_1 ... done
Starting myapp_web_1 ...
Starting myapp_web_1 ... done
MARK
Attaching to myapp_web_1
web_1 | psql: could not translate host name "db" to address: Name or service not known
web_1 | psql: could not translate host name "db" to address: Name or service not known
web_1 | psql: could not translate host name "db" to address: Name or service not known
web_1 | psql: could not translate host name "db" to address: Name or service not known
通常,'psql'在无法解析给定的主机名时输出此诊断信息。但是,主机名解析似乎在应用程序容器中正常工作:
$ docker exec -it myapp_web_1 bash
root@3a11fb7a22a1:/var/www/html# dig db
; <<>> DiG 9.10.3-P4-Debian <<>> db
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21082
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;db. IN A
;; ANSWER SECTION:
db. 600 IN A 172.22.0.2
;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Fri Dec 29 04:18:32 UTC 2017
;; MSG SIZE rcvd: 38
root@3a11fb7a22a1:/var/www/html# ping -c 2 db
PING db (172.22.0.2) 56(84) bytes of data.
64 bytes from myapp_db_1.myapp_default (172.22.0.2): icmp_seq=1 ttl=64 time=0.036 ms
64 bytes from myapp_db_1.myapp_default (172.22.0.2): icmp_seq=2 ttl=64 time=0.045 ms
--- db ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1020ms
rtt min/avg/max/mdev = 0.036/0.040/0.045/0.007 ms
root@3a11fb7a22a1:/var/www/html#
此外,PostgreSQL客户端和服务器似乎与此主机名相关的问题完全不同:
root@3a11fb7a22a1:/var/www/html# unset PGHOSTADDR
root@3a11fb7a22a1:/var/www/html# psql -h 172.22.0.2 -U postgres -c 'SELECT 1;'
?column?
----------
1
(1 row)
root@3a11fb7a22a1:/var/www/html#
为什么'psql'不能将'db'解析为172.22.0.2,因为'dig'能够做到,因此有效吗?
我正在设置PGHOSTADDR,它需要是一个点分十进制IP地址,而我应该设置PGHOST,它可以是一个主机名,正如the PostgreSQL documentation中清楚解释的那样。
取消设置PGHOSTADDR而不是设置PGHOST使'psql'按预期工作:
root@3a11fb7a22a1:/var/www/html# psql -U postgres -c 'SELECT 1;'
psql: could not translate host name "db" to address: Name or service not known
root@3a11fb7a22a1:/var/www/html# unset PGHOSTADDR
root@3a11fb7a22a1:/var/www/html# PGHOST=db
root@3a11fb7a22a1:/var/www/html# export PGHOST
root@3a11fb7a22a1:/var/www/html# psql -U postgres -c 'SELECT 1;'
?column?
----------
1
(1 row)
root@3a11fb7a22a1:/var/www/html#
RTFM的另一个失败。