在docker-compose中运行Django应用程序:连接到postgres db第一次拒绝但后续工作

时间:2017-07-12 00:53:05

标签: django postgresql docker docker-compose

我有这个奇怪的问题,可以使用Docker中的simple tutorial重现。

如果我完全遵循教程,一切都会正常工作,即在docker-compose up命令之后,Web容器将运行并很好地连接到db容器。

但是,如果我选择在主机上创建相同的Django项目,请更改其postgres数据库的设置,并将其复制到其Dockerfile中的Web映像,而不是将主机目录挂载到容器并执行这些操作教程中显示的内容(使用命令docker-compose run web django-admin.py startproject composeexample .然后更改生成并位于主机上已安装目录中的设置文件),第一次运行docker-compose up时,Web容器将具有连接到数据库的问题,错误如下

  

web_1 | psycopg2.OperationalError:无法连接到服务器:连接被拒绝   web_1 |服务器是否在主机“db”(172.18.0.2)上运行并且正在接受   web_1 |端口5432上的TCP / IP连接?

但是,如果我停止使用docker-compose进行撰写,然后使用docker-compose再次运行它,则Web容器将成功连接到db,没有任何问题。

'拒绝连接'似乎不是一个不常见的问题,但我检查并验证所有设置都是正确的,通常的原因是错误的端口号,端口没有暴露或将主机设置为'本地'而不是'db '等等不是这种情况下的问题。

注意:FWIW,我使用CNTLM作为主机中的系统代理,并且必须为Web图像设置环境变量,并且它适用于其他场景。

编辑: 请在下面找到其他信息。

在主机目录中,我有以下文件和目录

  • composeexample(由另一个容器生成,遵循相同的教程并复制到此处)
  • manage.py(由另一个容器生成并复制到此处)
  • requirements.txt(与教程中的完全相同)
  • Dockerfile(稍微修改过教程中的那个)
  • docker-compose.yml(稍微修改过教程中的那个)

composeexample / settings.py:

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

Dockerfile(大致相同,添加了env vars):

FROM python:3.5
ENV PYTHONUNBUFFERED 1
ENV http_proxy "http://172.17.0.1:3128"
ENV https_proxy "http://172.17.0.1:3128"
ENV HTTP_PROXY "http://172.17.0.1:3128"
ENV HTTPS_PROXY "http://172.17.0.1:3128"

RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/

docker-compose(我删除了已安装的卷。:/ code,因为项目文件在构建时已经被复制到Web图像。我测试时将其保留为原始文件并且它没有区别):< / p>

version: '3'

services:
  db:
    image: postgres
  web:
    build: .
    command: python3 manage.py runserver 0.0.0.0:8000
    ports:
      - "8000:8000"
    depends_on:
      - db

3 个答案:

答案 0 :(得分:5)

使用wait-for-it.sh等待Postgres准备就绪:

下载这个众所周知的脚本:https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh

version: '3'

services:
  db:
    image: postgres
  web:
    build: .
    command: /wait-for-it.sh db:5432 -- python3 manage.py runserver 0.0.0.0:8000
    volumes:
      - ./wait-for-it.sh:/wait-for-it.sh
    ports:
      - "8000:8000"
    depends_on:
      - db

它将等待正义的时间,不再浪费时间。

答案 1 :(得分:3)

正如文档所说 depends_on depends_on它表示容器之间的依赖关系,但这并不意味着容器会等待其他容器准备就绪,可能的解决方案是在docker-compose 内添加有点睡觉,这样的事情:

command: /bin/bash -c "sleep 7; python3 manage.py runserver -h 0.0.0.0 -p 9000 -r -d"

答案 2 :(得分:0)

您可以使用healthcheck

示例来自:peter-evans/docker-compose-healthcheck: How to wait for container X before starting Y using docker-compose healthcheck

var items = [ [1, 2], [3, 4], [5, 6] ];

function listiteration(list, start, end, col) {
  var result = [];
  for ( i = start; i <= end; i++ ) {
    result.push( [ list[ i ][ col ] ] )
  }
  return result;
}

console.log(listiteration(items, 1, 2, 1));