【问题标题】:Docker image not running, db error: django.db.utils.OperationalError could not translate host name "postgres" to address: Name or service not knownDocker 映像未运行,数据库错误:django.db.utils.OperationalError 无法将主机名“postgres”转换为地址:名称或服务未知
【发布时间】:2020-08-02 13:51:28
【问题描述】:

所以我设法使用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)分成两个服务,并且自我的previous post 以来只推送应用程序的图像。这是我的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

这是我的 Dockerfile:

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 文件的 sn-p:

...
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 % 

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

【问题讨论】:

    标签: django postgresql docker dockerfile digital-ocean


    【解决方案1】:

    当您启动 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 示例中,Dockerfile 中的代码永远无法连接到数据库。在机械层面上,没有办法像我们使用docker run 那样将其连接到 Docker 网络。在概念层面上,构建图像会产生可重用的工件;如果我 docker push 将映像添加到注册表并 docker run 将其放在不同的主机上,则不会设置数据库,或者如果我在本地删除并重新创建数据库容器,则类似。

    【讨论】:

    • 我错过了跑步部分。很好的解释:)
    • 当我执行docker volume ls 时,没有可用的卷。为什么会这样?
    • 我的意思是docker network ls,对不起;我已经确定了答案。
    • @DavidMaze 谢谢。共有三个选项:桥接、主机和无。我怎么知道该选择哪一个?
    • 如果你运行过docker-compose up -d,应该有一个名为somename_default,其中somename是当前目录的名称。使用那个。
    【解决方案2】:

    我正在尝试使用以下命令运行它:root@my-droplet:~#

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

    Docker-compose 允许创建多个容器的组合。
    使用docker run 运行 django 容器会破坏其目的。

    你想要的是运行:

    docker-compose build
    
    docker-compose up
    

    或在单个命令中:

    docker-compose up --build                    
    

    为什么此时连接被拒绝?

    也许是因为那不是在正确的时刻完成的。

    我不是 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 匹配:

    在本节中,您将为 Django 设置数据库连接。

    在您的项目目录中,编辑 composeexample/settings.py 文件。

    将 DATABASES = ... 替换为以下内容:

    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 侦听器尚未准备好。

    您的 compose 属性: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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-16
      • 2021-08-25
      • 2016-03-07
      • 2020-10-03
      • 2017-05-25
      • 1970-01-01
      • 2019-07-31
      • 2012-08-23
      相关资源
      最近更新 更多