如何使用 DATABASE_URL 将 Docker 容器连接到本地主机上的 PostgreSQL 运行?

How to connect a Docker container to PostgreSQL running on the localhost using a DATABASE_URL?

我正在关注描述如何创建和部署应用程序 Aptible 的 PaaS 的 Aptible Django Quickstart Tutorial。我还希望能够 运行 Docker 容器与本地 Django 应用程序连接到本地 PostgreSQL 数据库,但是,我不清楚如何执行此操作。

Django 应用的 Dockerfile 是:

FROM python:3.6

# System prerequisites
RUN apt-get update \
 && apt-get -y install build-essential libpq-dev \
 && rm -rf /var/lib/apt/lists/*

# If you require additional OS dependencies, install them here:
# RUN apt-get update \
#  && apt-get -y install imagemagick nodejs \
#  && rm -rf /var/lib/apt/lists/*

# Install Gunicorn. If Gunicorn is already present in your requirements.txt,
# you don't need that (but if won't hurt).
RUN pip install gunicorn

ADD requirements.txt /app/
WORKDIR /app
RUN pip install -r requirements.txt

ADD . /app

EXPOSE 8000

CMD ["gunicorn", "--access-logfile=-", "--error-logfile=-", "--bind=0.0.0.0:8000", "--workers=3", "mysite.wsgi"]

其中 mysite 是 Django 应用程序的名称。它的 settings.py 使用 dj-database-url 如下:

import dj_database_url
DATABASES = {'default': dj_database_url.config()}

为了连接到 PostgreSQL 的本地实例,我似乎应该遵循 Docker for Mac Solution on :

docker run -e DB_PORT=5432 -e DB_HOST=docker.for.mac.host.internal

但是,如果我尝试这样做,我仍然会收到以

结尾的错误
  File "/usr/local/lib/python3.6/site-packages/psycopg2/__init__.py", line 130, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
django.db.utils.OperationalError: could not connect to server: Connection refused
    Is the server running on host "localhost" (127.0.0.1) and accepting
    TCP/IP connections on port 5432?
could not connect to server: Cannot assign requested address
    Is the server running on host "localhost" (::1) and accepting
    TCP/IP connections on port 5432?

在我看来,当前配置的应用程序不是 'doing anything' 和 DB_PORTDB_HOST 环境变量,因为它是从 DATABASE_URL。这是问题吗?如果是这样,我如何在仍然使用 DATABASE_URL 的同时解决这个问题,因为这似乎是 Aptible 的 'interface'?

据我了解,postgres 不是 运行ning 在容器上,而是作为 host os 上的服务,对吗?

请看下面:

1。检查你的 postgres 接受所有 IP 地址上的连接

通常 postgres 只监听 localhost,这意味着,与 localhost 以外的连接将被拒绝。每个 docker 容器都附加到一个虚拟网络,并且从容器到 host 的通信通过该虚拟网络进行。

更新您的 postgresql.conf 文件并添加:

listen_addresses = '*'          # what IP address(es) to listen on;
                                    # comma-separated list of addresses;
                                    # defaults to 'localhost'; use '*' for all
                                    # (change requires restart)

2。使用正确的 ip address/hostname

如前所述,容器通过此虚拟网络与 host 通信。确保您使用的是正确的 hostname 或 ip 地址。

  • localhost

localhost 不会起作用,因为在容器上下文中,localhost 指的是容器

  • docker.for.mac.host.internal

至少对我来说它不起作用(docker-ce on a mac),看到 host 分辨率不起作用

docker run --rm -it postgres:10 ping docker.for.mac.host.internal
ping: unknown host
  • 使用您的 IP 地址

我正在使用我的 dhcp 服务器提供的 ip 地址,ping 正常

docker run --rm -it postgres:10 ping 192.168.0.* -c 1
PING 192.168.0.* (192.168.0.*): 56 data bytes
64 bytes from 192.168.0.*: icmp_seq=0 ttl=37 time=0.455 ms

因此请尝试使用有效的 IP 地址,docker 设备的 IP 或物理网络接口的 IP。

3。使用 docker compose 文件

将 docker compose 文件与 compose 或 swarm 一起使用到 运行,请参阅此处的示例应用程序:https://docs.docker.com/engine/swarm/stack-deploy/#create-the-example-application

我设法通过将 .env 文件中的 DATABASE_URL 更改为

来解决问题
DATABASE_URL=postgres://my_app:my_password@localhost/my_database

DATABASE_URL=postgres://my_app:my_password@docker.for.mac.host.internal/my_database

和 运行 容器,我标记了 lucy_web,像这样:

docker run -p 8000:8000 --env-file .env lucy_web

没有必要在我的postgresql.conf中将listen_addresses更改为'*';这仍然是默认值,localhost。 (我相信这是因为 -p 8000:8000 参数将 localhost 上的端口 8000 映射到容器)。

Windows 用户配置他们的环境使用:

DATABASE_URL=postgres://my_app:my_password@docker.host.internal/my_database