Docker Ubuntu 上的网络主机

Docker Network Host on Ubuntu

我有一个 Django REST 服务和另一个作为应用程序代理的 Flask 服务。两者都是不同的项目,运行 有自己的 Docker 容器。 我可以 POST Flask 服务使用的 Django 服务上的产品,但是,我无法通过 Flask 访问 Django 服务。 这些容器 运行 在同一个网络上,我已经尝试过 Thomasleveil's suggestions, including docker-host by qoomon。 请求收到的错误与我尝试转发流量之前相同。不同之处在于,现在当我执行请求时,它会一直挂起一段时间,直到失败。

错误如下: 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'))

我要提出的请求是 POST /api/products/1/like。目前不需要正文。

这是我用 Flask 做 POST 的方法,其中 IP 是 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 的docker compose 文件(请忽略服务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 的 docker 组合文件:

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

此时,我知道我遗漏了一些细节或者配置错误。

您可以在此处查看存储库:https://github.com/lfbatista/ms-ecommerce

如有任何帮助,我们将不胜感激。

这些容器实际上不在同一个网络上。要将来自不同 docker-compose 项目的两个容器放入一个网络中,您需要 'import' 一个文件中的现有网络。方法如下:

# 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> .

不要忘记将所有服务置于同一个 internal 网络中,否则它们将无法相互通信。如果您忘记这样做,Docker 将创建一个 <folder_name>-default 网络并将任何没有明确分配网络的容器放在那里。您可以这样分配网络:

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

这是您存储库中的文件。一项服务可以通过 flask-backenddjango-backend 访问另一项服务,而不是 IP 地址。注意我删掉了那些奇怪的'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