42

He everyone. I'm working with docker and trying to dockerize a simple django application that does an external http connect to a web page (real website) so when I set in the Docker file the address of my django server that should work in the container - 127.0.0.1:8000. my app wasn't working because of the impossibility to do an external connection to the website.

but when I set the port for my server: 0.0.0.0:8000 it started to work.

So my question is: Why it behaves like that? What is the difference in this particular case? I just want to understand it.

I read some articles about 0.0.0.0 and it's like a 'generic' or 'placeholder' port that allows to use the OC default port.

127.0.0.1 is like a host that redirects the request to the current machine. I knew it. But when I run the app at my localmachine (host: 127.0.0.0:8000) everything was working and the app could do the connection to the real website but in case of docker it stopped to work.

Thanks for any help!

Here are my sources: Docker file

FROM python:3.6

RUN mkdir /code
WORKDIR /code

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY . ./

EXPOSE 8000

ENTRYPOINT [ "python", "manage.py" ]
CMD [ "runserver", "127.0.0.1:8000" ] # doesn't work
# CMD [ "runserver", "0.0.0.0:8000" ] - works

docker-compose.yml

version: "3"
services:
  url_rest:
    container_name: url_keys_rest
    build:
      context: .
      dockerfile: Dockerfile
    image: url_keys_rest_image
    stdin_open: true
    tty: true
    volumes:
      - .:/var/www/url_keys
    ports:
      - "8000:8000"

here is the http error that I received in case of 127.0.0.1. Maybe it will be useful.

http: error: ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8000): Max retries exceeded with url: /api/urls (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x10cd51e80>: Failed to establish a new connection: [Errno 61] Connection refused')) while doing GET request to URL: http://127.0.0.1:8000/api/urls
Velidan
  • 5,526
  • 10
  • 48
  • 86

2 Answers2

54

You must set a container’s main process to bind to the special 0.0.0.0 “all interfaces” address, or it will be unreachable from outside the container.

In Docker 127.0.0.1 almost always means “this container”, not “this machine”. If you make an outbound connection to 127.0.0.1 from a container it will return to the same container; if you bind a server to 127.0.0.1 it will not accept connections from outside.


One of the core things Docker does is to give each container its own separate network space. In particular, each container has its own lo interface and its own notion of localhost.

At a very low level, network services call the bind(2) system call to start accepting connections. That takes an address parameter. It can be one of two things: either it can be the IP address of some system interface, or it can be the special 0.0.0.0 “all interfaces” address. If you pick an interface, it will only accept connections from that interface; if you have two network cards on a physical system, for example, you can use this to only accept connections from one network but not the other.

So, if you set a service to bind to 127.0.0.1, that’s the address of the lo interface, and the service will only accept connections from that interface. But each container has its own lo interface and its own localhost, so this setting causes the service to refuse connections unless they’re initiated from within the container itself. It you set it to bind to 0.0.0.0, it will also accept connections from the per-container eth0 interface, where all connections from outside the container arrive.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • 6
    Thanks for your answer. To be honest I read it a few times just to understand it as this explanation is too `technical`. So my current knowledge level isn't enough to understand in 100% but I understand something, at least a little. Thank you. – Velidan Dec 06 '19 at 22:38
6

My understanding is that docker is randomly assigning IP address to each container instead of localhost(127.*.*.*). So using 0.0.0.0 to listen inside the docker application will work. I tried to connect local database inside a docker file before with localhost. It doesn't work as well. I guess it is due to this reason. Correct me if I am wrong plz!

Update: I attach an intuitive image to show how docker interact with those ip addresses. Hope this will help to understand.

enter image description here

zhen404
  • 111
  • 1
  • 7