I have this weird problem that can be reproduced with the simple tutorial from Docker.
If I follow the tutorial exactly, everything would work fine, i.e. after docker-compose up command, the web container would run and connect nicely to the db container.
However, if I choose to create the same Django project on the host, change its settings for the postgres db, and copy it over to the web image in its Dockerfile, instead of mounting the host directory to the container and doing those things there as shown in the tutorial (using the command docker-compose run web django-admin.py startproject composeexample . and then change the settings file generated and located in the mounted directory on the host), the first time I run docker-compose up, the web container would have problems connecting to the db, with the error as below
web_1 | psycopg2.OperationalError: could not connect to server: Connection refused web_1 | Is the server running on host "db" (172.18.0.2) and accepting web_1 | TCP/IP connections on port 5432?
However, if I stop the compose with docker-compose down and then run it again with docker-compose up, the web container would connect to the db successfully with no problems.
'Connection refused' seems to be not an uncommon problem here but I have checked and verified that all the settings are correct and the usual causes like wrong port number, port not exposed or setting host as 'local' instead of 'db', etc. are not the problems in this case.
Note: FWIW, I use CNTLM as the system proxy in the host and have to set the environment variables for the web image, and it works fine for other scenarios.
EDIT: Please find additional info as below.
In the host directory I have the following files and directories
- composeexample (generated by another container following the same tutorial and copied over to here)
- manage.py (generated by another container and copied over to here)
- requirements.txt (exactly as the one in the tutorial)
- Dockerfile (slightly modified from the one in the tutorial)
- docker-compose.yml (slightly modified from the one in the tutorial)
composeexample/settings.py:
.........
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': 'postgres',
'HOST': 'db',
'PORT': 5432,
}
}
.........
Dockerfile (mostly the same, with the added 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 (I removed the mounted volume .:/code as the project files have already been copied to the web image when it's built. I tested with leaving it as in the original file and it made no difference):
version: '3'
services:
db:
image: postgres
web:
build: .
command: python3 manage.py runserver 0.0.0.0:8000
ports:
- "8000:8000"
depends_on:
- db
command: /bin/bash -c "sleep 7; python3 manage.py runserver -h 0.0.0.0 -p 9000 -r -d"sleep 5to the command of the web container has fixed the problem for me. I've read about this but it never comes to my mind that this is actually the problem. It's still a bit strange to me though, as I would expect that once you have set thedepends_on, the web container would wait for the db to be fully ready before attempting to connect to it?