Luis Batista
Luis Batista

Reputation: 69

Docker Network Host on Ubuntu

I have a Django REST service and another Flask service that work as a broker for the application. Both are different projects that run with their own Docker container. I'm able to POST a product on the Django service that is consumed by the Flask service, however, I cannot reach the Django service via Flask. These containers are running on the same network, and I already tried Thomasleveil's suggestions, including docker-host by qoomon. The error received by the request is the same as before I tried to forward the traffic. The difference is that now when I do the request it keeps hanging for a while until it fails.

The error is as follows: requests.exceptions.ConnectionError: HTTPConnectionPool(host='172.17.0.1', port=8000): Max retries exceeded with url: /api/user (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f0039388340>: Failed to establish a new connection: [Errno 110] Connection timed out'))

The request I'm trying to make is a POST at /api/products/1/like. At the moment, no body is required.

Here is how I'm doing the POST with Flask, where the IP is the Docker IP:

@app.route("/api/products/<int:id>/like", methods=["POST"])
def like(id):
    req = requests.get("http://172.17.0.1:8000/api/user")
    json = req.json()

    try:
        product_user = ProductUser(user_id=json["id"], product=id)
        db.session.add(product_user)
        db.session.commit()

        publish("product_liked", id)
    except:
        abort(400, "You already liked this product")

    return jsonify({
        "message": "success"
    })

Django's docker compose file (please ignore the service tcp_message_emitter):

version: '3.8'
services:
  backend:
    build:
      context: .
      dockerfile: Dockerfile
    command: "python manage.py runserver 0.0.0.0:8000"
    ports:
      - 8000:8000
    volumes:
      - .:/app
    depends_on:
      - db

  queue:
    build:
      context: .
      dockerfile: Dockerfile
    command: "python consumer.py"
    depends_on:
      - db

  db:
    image: mysql:5.7.22
    restart: always
    environment:
      MYSQL_DATABASE: admin
      MYSQL_USER: root
      MYSQL_PASSWORD: root
      MYSQL_ROOT_PASSWORD: root
    volumes:
      - .dbdata:/var/lib/mysql
    ports:
      - 33066:3306

  dockerhost:
    image: qoomon/docker-host
    cap_add:
      - NET_ADMIN
      - NET_RAW
    restart: on-failure
    networks:
      - backend

  tcp_message_emitter:
    image: alpine
    depends_on:
      - dockerhost
    command: [ "sh", "-c", "while :; do date; sleep 1; done | nc 'dockerhost' 2323 -v"]
    networks:
      - backend

networks:
  backend:
    driver: bridge

Flask's docker compose file:

version: '3.8'
services:
  backend:
    build:
      context: .
      dockerfile: Dockerfile
    command: "python main.py"
    ports:
      - 8001:5000
    volumes:
      - .:/app
    depends_on:
      - db

  queue:
    build:
      context: .
      dockerfile: Dockerfile
    command: "python consumer.py"
    depends_on:
      - db

  db:
    image: mysql:5.7.22
    restart: always
    environment:
      MYSQL_DATABASE: main
      MYSQL_USER: root
      MYSQL_PASSWORD: root
      MYSQL_ROOT_PASSWORD: root
    volumes:
      - .dbdata:/var/lib/mysql
    ports:
      - 33067:3306

At this point, I know that I am missing some detail or that I've a misconfiguration.

You can have a look at the repo here: https://github.com/lfbatista/ms-ecommerce

Any help would be appreciated.

Upvotes: 2

Views: 649

Answers (1)

anemyte
anemyte

Reputation: 20226

These containers are not actually on the same network. To put two containers from different docker-compose projects into one network you need to 'import' an existing network in one of the files. Here's how you can do it:

# first project
networks:
  internal:
  shared:
---
# second project
networks:
  internal:
  shared:
    # This is where all the magic happens:
    external: true  # Means do not create a network, import existing.
    name: admin_shared  # Name of the existing network. It's usually made of <folder_name>_<network_name> .

Do not forget to put all services into the same internal network or they will not be able to communicate with each other. If you forget to do that Docker will create a <folder_name>-default network and put any container with no explicitly assigned network there. You can assign networks like this:

services:
  backend:
    ...
    networks:
      internal:
      # Since this service needs access to the service in another project
      # you put here two networks.
      shared:
        # This part is relevant for this specific question because
        # both projects has services with identical names. To avoid
        # mess with DNS names you can add an additional name to the
        # service using 'alias'. This particular service will be
        # available in shared network as 'flask-backend'.
        aliases:
        - flask-backend

  db:
    ...
    # You can also assign networks as an array if you need no extra configuration:
    networks:
      - internal

And here are the files from your repository. Instead of IP-address one service can reach the other via flask-backend or django-backend respectively. Note that I cut out those strange 'host network containers'.

admin/docker-compose.yml:

version: '3.8'
services:
  backend:
    build:
      context: .
      dockerfile: Dockerfile
    command: "python manage.py runserver 0.0.0.0:8000"
    ports:
      - 8000:8000
    volumes:
      - .:/app
    depends_on:
      - db
    networks:
      internal:
      shared:
        aliases:
        - django-backend

  queue:
    build:
      context: .
      dockerfile: Dockerfile
    command: "python consumer.py"
    depends_on:
      - db
    networks:
      - internal

  db:
    image: mysql:5.7.22
    restart: always
    environment:
      MYSQL_DATABASE: admin
      MYSQL_USER: root
      MYSQL_PASSWORD: root
      MYSQL_ROOT_PASSWORD: root
    volumes:
      - .dbdata:/var/lib/mysql
    ports:
      - 33066:3306
    networks:
      - internal

networks:
  internal:
  shared:

main/docker-compose.yml:

version: '3.8'
services:
  backend:
    build:
      context: .
      dockerfile: Dockerfile
    command: "python main.py"
    networks:
      internal:
      shared:
        aliases:
        - flask-backend
    ports:
      - 8001:5000
    volumes:
      - .:/app
    depends_on:
      - db

  queue:
    networks:
      - internal
    build:
      context: .
      dockerfile: Dockerfile
    command: "python consumer.py"
    depends_on:
      - db

  db:
    image: mysql:5.7.22
    restart: always
    networks:
      - internal
    environment:
      MYSQL_DATABASE: main
      MYSQL_USER: root
      MYSQL_PASSWORD: root
      MYSQL_ROOT_PASSWORD: root
    volumes:
      - .dbdata:/var/lib/mysql
    ports:
      - 33067:3306

networks:
  internal:
  shared:
    external: true
    name: admin_shared

Upvotes: 2

Related Questions