Почему я не могу получить доступ к сервису, созданному docker-compose? - PullRequest
0 голосов
/ 19 октября 2018

Я создаю веб-приложение на основе микросервисов с Flask и Docker.В настоящее время у меня есть 2 службы, запущенные docker-compose в той же сети по умолчанию.

  • mysql
  • product_api

docker-compose.yml Файл -

version: '3'

services:
  mysql:
    image: mysql
    environment:
      MYSQL_USER: "mysqluser"
      MYSQL_PASSWORD: "mysqlpassword"
      MYSQL_ROOT_PASSWORD: "root"
      MYSQL_DATABASE: "gadgetfreeiot"
    container_name: mysql
    ports:
      - 3306:3306
    restart: always
    entrypoint: ['docker-entrypoint.sh', '--default-authentication-plugin=mysql_native_password']

  product_api:
    build: ./${SERVICE_ROOT:-src/services/product/api}
    image: product_api:v1
    container_name: product_api
    volumes: 
      - ./${SERVICE_ROOT:-src/services/product/api}:${PROJECT_ROOT:-/usr/projects/gadgetfreeiot}/${SERVICE_ROOT:-src/services/product/api}
    ports: 
      - 5000:5000
    depends_on:
      - mysql
    environment:
      username: "mysqluser"
      password: "mysqlpassword"
      host: "mysql"
      port: "3306"
      database: "gadgetfreeiot"
    command: ["./wait-for-mysql.sh", "--", "python", "./run.py"]

docker ps вывод дает мне -

johir@ubuntu:gadgetfreeiot$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
e10329e26e5c        product_api:v1      "./wait-for-mysql.sh…"   18 minutes ago      Up 18 minutes       0.0.0.0:5000->5000/tcp              product_api
7fed5a136123        mysql               "docker-entrypoint.s…"   18 minutes ago      Up 18 minutes       0.0.0.0:3306->3306/tcp, 33060/tcp   mysql

Обе службы работают в сети gadgetfreeiot_default.docker inspect gadgetfreeiot_default показывает, что оба находятся в одной сети -

johir@ubuntu:gadgetfreeiot$ docker inspect gadgetfreeiot_default 
[
    {
        "Name": "gadgetfreeiot_default",
        "Id": "67e09ae3a33c0ff4203eefe4fee6ba421d3f68564c6e32c7d1cd04e866ac6850",
        "Created": "2018-10-18T14:56:05.86215576+03:00",


       "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "192.168.0.0/20",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "14ffb8eaa0c17de0122de142dbcf7aa5455b41b47eadb197e8be200c2375fbb3": {
                "Name": "mysql",
                "EndpointID": "38ed4140ed728271194ee82f12b3d937c53166f6159ab4e6fcf2d8087039ed06",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/20",
                "IPv6Address": ""
            },
            "e013059b510e42933d33f7c3fb7e141a19a6c78a0e34d031e5fce5e104aa8697": {
                "Name": "product_api",
                "EndpointID": "fdbe0ed92d0e53d6fc1040a50b1898e2bb87b34384f80b98e638a3a89a57c4e1",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/20",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "default",
            "com.docker.compose.project": "gadgetfreeiot",
            "com.docker.compose.version": "1.22.0"
        }
    }
]

Теперь я пытаюсь получить доступ к службам product_api, а также mysql из моей операционной системы.Тем временем я также пытаюсь получить доступ из одного контейнера в другой (от product_api до mysql и от mysql до product_api).mysql доступно из всех 3-х, которые являются моей операционной системой хоста, сам product_api и mysql с помощью -

mysql -h172.19.0.2 -P3306 -umysqluser -p

product_api также может получить доступ с помощью -

mysql -hmysql -P3306 -umysqluser -p

К счастью, я могу получить доступ к curl http://localhost:5000 шоу из product_api -

johir@ubuntu:gadgetfreeiot$ docker exec -it product_api bash
root@e013059b510e:/usr/projects/gadgetfreeiot/src/services/product/api# curl http://localhost:5000
{
  "message": "Endpoint not found", 
  "status": "failed"
}

Где curl http://172.19.0.3:5000 шоу -

curl: (7) Failed to connect to 172.19.0.3 port 5000: Connection refused

Это означает, что product_api запущен и работает и доступен только localhost или 127.0.0.1 изнутри контейнера product_api, а не по IP-адресу или по имени службы из внешнего контейнера product_api, который не принадлежит ни моей операционной системе хостани из mysql контейнера.

Наконец, я проверил - активные сети среди 3 netstat -tln -

# product_api container 
root@e10329e26e5c:/usr/projects/gadgetfreeiot/src/services/product/api# netstat -tln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 127.0.0.11:40071        0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:5000          0.0.0.0:*               LISTEN

# mysql container
root@7fed5a136123:/# netstat -tln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 127.0.0.11:35507        0.0.0.0:*               LISTEN     
tcp6       0      0 :::33060                :::*                    LISTEN     
tcp6       0      0 :::3306                 :::*                    LISTEN

# host OS
johir@ubuntu:gadgetfreeiot$ netstat -tln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN     
tcp6       0      0 ::1:631                 :::*                    LISTEN     
tcp6       0      0 :::5000                 :::*                    LISTEN     
tcp6       0      0 :::3306                 :::*                    LISTEN

Примечание: порт 5000 неоткрыть по tcp6 в product_api контейнере.С другой стороны, порт 3306 открыт TCP6 на контейнере mysql.

Вопрос: Почему я не могу получить доступ к сервису product_api из моей хост-ОС или даже из mysql (в ограничении, почему tcp6 не предоставляет порт 5000 для сервиса product_api)?

1 Ответ

0 голосов
/ 19 октября 2018

Краткий ответ: вы не можете получить доступ, как вы показали с помощью curl http://localhost:5000.Просто кажется немного запутанным, кто (хост против контейнеров) может получить доступ к каким IP-адресам и решить, какие имена хостов.

В вашем docker-compose.yml вы сопоставили порты 3306 и 5000 с вашими соответствующими контейнерами.Поэтому docker добавил порт вперед от любого интерфейса на вашем хосте (без интерфейсов сетей Docker) к вашим контейнерам (посмотрите на вывод sudo iptables-save | grep 5000, если вы заинтересованы в том, как это делается под капотом,будет выглядеть примерно так:

-A DOCKER -d 192.168.0.2/20 ! -i br-e013059b510e -o br-e013059b510e -p tcp -m tcp --dport 5000 -j ACCEPT

Доступ

Таким образом, с вашего хоста вы можете получить доступ к своему сервису через

curl http://localhost:5000

С другого компьютера (при условии, что настройки брандмауэра позволяют) через

curl http://your.hostname:5000

Из контейнера в одной докерной сети

curl http://product_api:5000                            # or
curl http://product_api.gadgetfreeiot_default:5000      # or
curl http://192.168.0.3:5000

Чтобы оба контейнера были в одной докерной сети, настройте docker-compose.yml следующим образом:

services:
  mysql:
  [...]
  ports:
    - 3306:3306
  networks:
    - gadgetfreeiot
  [...]

  product_api:
    ports:
      - 5000:5000
    networks:
      - gadgetfreeiot
  [...]
networks:
  gadgetfreeiot:

DNS

Имена хостов контейнеров, такие как product_api, не могут быть разрешены на хосте. Однако они находятся внутри ваших контейнеров. Внутри контейнера у вас есть дополнительный док-сервер DNS на 127.0.0.11, который можетВаш хост может быть восстановлен, плюс имена хостов докера, такие как product_api.gadgetfreeiot_default. Попробуйте

nslookup product_api.gadgetfreeiot_default

на вашем хосте и внутри контейнера

docker exec -it mysql bash

Проверьте https://docs.docker.com/network/ для получения дополнительной информациина этом.

Что касается вашей заметки: netstat не показывает, какой порт «открыт», т.е. разрешен брандмауэром, но с каким портом связана программа.Будет ли программа связана с портом на интерфейсе IPv4, v6 или обоими, зависит от программы.Это не связано с сетью докеров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...