Docker image not running, db error: django.db.utils.OperationalError could not translate host name "postgres" to address: Name or service not known

Docker image not running, db error: django.db.utils.OperationalError could not translate host name "postgres" to address: Name or service not known

所以我设法使用 docker-compose build 在本地构建了我的 Docker 图像,并将图像推送到我的 Docker Hub 存储库。

现在我正在尝试让它在 DigitalOcean 上运行,以便我可以托管它。我已经提取了正确版本的图像,我正在尝试使用以下命令 运行 它:

root@my-droplet:~# docker run --rm -it -p 8000:8000/tcp mycommand/myapp:1.1(是的,1.1)

然而我很快运行陷入这两个错误:

...
File "/usr/local/lib/python3.8/dist-packages/django/db/backends/postgresql/base.py",
line 185, in get_new_connection
    connection = Database.connect(**conn_params)   File "/usr/local/lib/python3.8/dist-packages/psycopg2/__init__.py", line
127, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync) 
psycopg2.OperationalError: could not translate host name "postgres" to address: Name or service not known ```
... 
File "/usr/local/lib/python3.8/dist-packages/django/db/backends/base/base.py",
line 197, in connect
    self.connection = self.get_new_connection(conn_params)   File "/usr/local/lib/python3.8/dist-packages/django/utils/asyncio.py", line
26, in inner
    return func(*args, **kwargs)   File "/usr/local/lib/python3.8/dist-packages/django/db/backends/postgresql/base.py",
line 185, in get_new_connection
    connection = Database.connect(**conn_params)   File "/usr/local/lib/python3.8/dist-packages/psycopg2/__init__.py", line
127, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync) 
django.db.utils.OperationalError: could not translate host name "postgres" to address: Name or service not known ```

这可能是由于我如何将我的应用程序(使用 docker-compose,yml)划分为两个服务,并且自 以来只推送应用程序的图像。这是我的 docker-compose.yml 文件:

这是我的 docker-compose.yml 文件:

version: '3'

services:
  db:
    image: postgres
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=(adminname)
      - POSTGRES_PASSWORD=(adminpassword)
      - CLOUDINARY_URL=(cloudinarykey)
  app:
    build: .
    ports:
      - "8000:8000"
    depends_on:
      - db

这是我的Docker文件:

FROM (MY FRIENDS ACCOUNT)/django-npm:latest

RUN mkdir usr/src/mprova

WORKDIR /usr/src/mprova

COPY frontend ./frontend
COPY backend ./backend

WORKDIR /usr/src/mprova/frontend

RUN npm install
RUN npm run build

WORKDIR /usr/src/mprova/backend

ENV DJANGO_PRODUCTION=True
RUN pip3 install -r requirements.txt

EXPOSE 8000

CMD python3 manage.py collectstatic && \
    python3 manage.py makemigrations && \
    python3 manage.py migrate && \
    gunicorn mellon.wsgi --bind 0.0.0.0:8000

这是我的 settings.py 文件的片段:

...
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'postgres',
        'USER': 'admin',
        'PASSWORD': '[THE PASSWORD]',
        'HOST': 'db',
        'PORT': 5432,
    }
}
...

我该如何解决这个问题?我环顾四周,但看不出我做错了什么。


根据我在网上看到的,我将以下内容添加到我的项目中,但它也不起作用:

这是我的base.py(新文件):

import psycopg2

conn = psycopg2.connect("dbname='postgres' user='admin' host='db' password='[THE PASSWORD]'")

Dockerfile 的补充:

FROM (MY FRIENDS ACCOUNT)/django-npm:latest

RUN pip3 install psycopg2-binary

COPY base.py base.py

RUN python3 base.py

...

但是构建由于以下错误而失败:

Traceback (most recent call last):   File "base.py", line 3, in
<module>
    conn = psycopg2.connect("dbname='postgres' user='admin' host='db' password='[THE PASSWORD]'")   
File "/usr/local/lib/python3.8/dist-packages/psycopg2/__init__.py", line
127, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync) psycopg2.OperationalError: could not connect to server: Connection refused
        Is the server running on host "db" ([SOME-IP-ADDRESS]) and accepting
        TCP/IP connections on port 5432?

ERROR: Service 'app' failed to build: The command '/bin/sh -c python3 base.py' returned a non-zero code: 1 
me@My-MacBook-Pro-5 mellon % 

我不确定接下来要尝试什么,但我觉得我犯了一个简单的错误。为什么此时连接被拒绝?

I am trying to run it with the following command: root@my-droplet:~#

docker run --rm -it -p 8000:8000/tcp mycommand/myapp:1.1 (yes, 1.1)

Docker-compose 允许创建多个容器的组合。
运行 带有 docker run 的 django 容器违背了它的目的。

你想要的是 运行 :

docker-compose build

docker-compose up

或在单个命令中:

docker-compose up --build                    

Why is the connection being refused at the moment?

可能是因为时机不对。

我不是 Django 专家,但您的第二次尝试看起来不错,而您的 Django 服务在 compose 声明中缺少 Dockerfile 属性(我认为是输入错误)。

第一次尝试,出现错误:

django.db.utils.OperationalError: could not translate host name "postgres" to address: Name or service not known ```

意味着 django 使用“postgres”作为数据库的主机。
但是根据您的撰写,可以使用名为“db”的主机访问数据库。这些不匹配。

关于您定义数据库属性的第二次尝试,它看起来不错并且也符合 the official doc states :

In this section, you set up the database connection for Django.

In your project directory, edit the composeexample/settings.py file.

Replace the DATABASES = ... with the following:

settings.py

DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.postgresql',
    'NAME': 'postgres',
    'USER': 'postgres',
    'PASSWORD': 'postgres',
    'HOST': 'db',
    'PORT': 5432,
} } These settings are determined by the postgres Docker image specified in docker-compose.yml.

第二次尝试,出现错误:

 conn = _connect(dsn, connection_factory=connection_factory, **kwasync) psycopg2.OperationalError: could not connect to server: Connection refused
        Is the server running on host "db" ([SOME-IP-ADDRESS]) and accepting
        TCP/IP connections on port 5432?

可能意味着当 Django 尝试初始化连接时,Postgres DB 侦听器尚未准备好。

您的撰写属性:depends_on: 定义了容器启动的顺序,但不等待容器后面的应用程序“准备就绪”。

这里有两种方法可以解决这种情况:

  • 在启动 django 服务之前添加几秒钟的睡眠
  • 或者将您的 django compose conf 设置为在失败时重新启动。

对于第一种方式,使用 CMD 配置您的 django 服务,例如(未尝试):

   app:
     build: .
     ports:
       - "8000:8000"
     depends_on:
       - db
     command: /bin/bash -c "sleep 30; python3 manage.py collectstatic && python3 manage.py makemigrations && python3 manage.py migrate && gunicorn mellon.wsgi --bind 0.0.0.0:8000 "

对于第二种方式,尝试类似的方法:

  app:
    build: .
    ports:
      - "8000:8000"
    depends_on:
      - db
    restart: on-failure

当您启动 docker-compose.yml 文件时,Compose 会自动为您创建一个 Docker 网络并将容器附加到它。如果文件中没有任何特定的 networks: 声明,Compose 会将网络命名为 default,然后 Compose 创建的大多数内容都以当前目录名称为前缀。此设置在 Networking in Compose.

中有更详细的描述

docker run 根本不查看 Compose 设置,因此您使用 docker run 手动执行的任何操作都需要复制 docker-compose.yml 已经或将自动生成的设置。要使 docker run 容器连接到 Compose 网络,您需要执行以下操作:

docker network ls              # looking for somename_default
docker run \
  --rm -it -p 8000:8000/tcp \
  --net somename_default \     # <-- add this option
  mycommand/myapp:1.1

(特定的错误消息 could not translate host name "postgres" to address 暗示 Docker 网络设置问题:数据库客户端容器与数据库服务器不在同一网络上,因此主机名解析失败。对比出现“连接被拒绝”类型错误,这表明一个容器正在寻找另一个容器,但数据库尚未 运行 或端口号错误。)

在您的 docker build 示例中,Docker 文件中的代码永远无法连接到数据库。在机械层面上,无法像我们对 docker run 所做的那样将其附加到 Docker 网络。在概念层面上,构建图像会产生可重用的工件;如果我 docker push 镜像到注册表并 docker run 它在不同的主机上,那将不会有数据库设置,或者类似地,如果我删除并在本地重新创建数据库容器。