在docker-compose中运行Django应用程序:连接到postgres数据库拒绝了第一次,但后来工作

我有这个奇怪的问题,可以从Docker的简单教程中复制。

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

但是,如果我select在主机上创build相同的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而不会出现问题。

'拒绝连接'似乎不是一个不常见的问题,但我已经检查和validation了所有的设置是正确的,像通常的原因,例如错误的端口号,端口没有暴露或设置主机为'本地'而不是'数据库'等在这种情况下不是问题。

注意:FWIW,我使用CNTLM作为主机的系统代理,必须设置网页图片的环境variables,并且对于其他场景也能正常工作。

编辑:请find更多的信息如下。

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

  • 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(大部分是相同的,添加了envvariables):

 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(我删除了已安装的卷。:/代码,因为项目文件在构build时已经被复制到了Web映像中,我将它作为原始文件进行了testing,结果没有区别):

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

正如文档所述, depends_on depends_onexpression了容器之间的依赖关系,但这并不意味着容器将等待其他人准备好,一个可能的解决scheme就是在docker-compose添加一些东西,比如:

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

使用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 

它会等待正义的时间,不会浪费任何时间。