Контейнеры с docker-compose ведут себя по-разному в зависимости от машины, на которой они выполняются.

Добрый день,

Я пытаюсь заставить нижеприведенную композицию docker работать на моей машине, но у меня возникают проблемы с некоторыми ошибками 404 при попытке доступа к URL-адресу контейнера A из контейнера B.

Априори единственное, чего не было в исходном контроле, это модификация в хост-файле, где мне пришлось добавить следующие строки.

127.0.0.1 idsrv4admin.traefik.me
127.0.0.1 idsrv4adminApi.traefik.me
127.0.0.1 login.traefik.me

Я получил все ресурсы из системы управления версиями, и на машине моего друга все работает нормально. Возможно, у меня другая конфигурация на моей машине, но я не могу узнать, что это такое.

Если я попытаюсь получить доступ к http://login.traefik.me/.well-known/openid-configuration непосредственно из своего браузера, я смогу получить к нему доступ:

{"issuer":"http://login.traefik.me","authorization_endpoint":"http://login.traefik.me/connect/authorize","token_endpoint":"http://login.traefik.me/connect/token","userinfo_endpoint":"http://login.traefik.me/connect/userinfo","end_session_endpoint":"http://login.traefik.me/connect/endsession","check_session_iframe":"http://login.traefik.me/connect/checksession","revocation_endpoint":"http://login.traefik.me/connect/revocation","introspection_endpoint":"http://login.traefik.me/connect/introspect","device_authorization_endpoint":"http://login.traefik.me/connect/deviceauthorization","frontchannel_logout_supported":true,"frontchannel_logout_session_supported":true,"backchannel_logout_supported":true,"backchannel_logout_session_supported":true,"scopes_supported":["roles","openid","profile","email","address","identity_admin_api","offline_access"],"claims_supported":["role","sub","updated_at","locale","zoneinfo","birthdate","gender","website","picture","preferred_username","nickname","middle_name","given_name","family_name","name","profile","email","email_verified","address"],"grant_types_supported":["authorization_code","client_credentials","refresh_token","implicit","password","urn:ietf:params:oauth:grant-type:device_code"],"response_types_supported":["code","token","id_token","id_token token","code id_token","code token","code id_token token"],"response_modes_supported":["form_post","query","fragment"],"token_endpoint_auth_methods_supported":["client_secret_basic","client_secret_post"],"subject_types_supported":["public"],"code_challenge_methods_supported":["plain","S256"],"request_parameter_supported":true}

Если я подключаюсь из администратора контейнера и пробую завиток по тому же URL-адресу, у меня появляется ошибка 404 со следующим сообщением об ошибке:

* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x560c38473f50)
* Connected to login.traefik.me (127.0.0.1) port 80 (#0)
> GET /.well-known/openid-configuration HTTP/1.1
> Host: login.traefik.me
> User-Agent: curl/7.64.0
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Mon, 23 Nov 2020 08:34:58 GMT
< Content-Length: 0
< X-XSS-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< X-Frame-Options: SameOrigin
< Referrer-Policy: no-referrer
< Content-Security-Policy: script-src 'self' 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline' https://fonts.googleapis.com/ https://fonts.gstatic.com/;font-src 'self' https://fonts.googleapis.com/ https://fonts.gstatic.com/
<
* Connection #0 to host login.traefik.me left intact

Ниже приведен docker-compose:

version: "3.4"

services:
  traefik:
    image: "traefik:latest"
    container_name: "traefik"
    command:
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.traefik.address=:9090"
    ports:
      - "80:80"
      - "443:443"
      - "9090:9090"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - proxy

  admin:
    image: ${DOCKER_REGISTRY-}admin:latest
    build:
      context: .
      dockerfile: src/IdentityServer/Admin/Dockerfile
    container_name: is4-admin
    hostname: idsrv4admin.traefik.me
    expose:      
      - '80'
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.identityserver4Admin.rule=Host(`idsrv4admin.traefik.me`)"
      - "traefik.http.routers.identityserver4Admin.entrypoints=web"
    environment:
      - VIRTUAL_HOST=idsrv4admin.traefik.me
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://+:80
      - DOTNET_USE_POLLING_FILE_WATCHER=1
      - "AdminConfiguration__IdentityAdminRedirectUri=http://idsrv4admin.traefik.me/signin-oidc"
      - "AdminConfiguration__IdentityServerBaseUrl=http://login.traefik.me"
      - "AdminConfiguration__RequireHttpsMetadata=false"
    depends_on:
      - sts.identity
      - admin.api
    networks:
      - proxy

  admin.api:
    image: ${DOCKER_REGISTRY-}admin-api:latest
    build:
      context: .
      dockerfile: src/IdentityServer/Admin.Api/Dockerfile
    container_name: is4-admin-api
    hostname: idsrv4adminApi.traefik.me
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.identityserver4AdminApi.rule=Host(`idsrv4adminApi.traefik.me`)"
      - "traefik.http.routers.identityserver4AdminApi.entrypoints=web"
    environment:
      - VIRTUAL_HOST=idsrv4adminApi.traefik.me
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://+:80
      - DOTNET_USE_POLLING_FILE_WATCHER=1
      - "AdminApiConfiguration__RequireHttpsMetadata=false"
      - "AdminApiConfiguration__ApiBaseUrl=http://idsrv4adminApi.traefik.me"
      - "AdminApiConfiguration__IdentityServerBaseUrl=http://login.traefik.me"
    depends_on:
      - sts.identity
    networks:
      - proxy

  sts.identity:
    image: ${DOCKER_REGISTRY-}sts-identity:latest
    build:
      context: .
      dockerfile: src/IdentityServer/STS.Identity/Dockerfile
    container_name: is4-sts-identity
    hostname: login.traefik.me
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.identityserver4STS.rule=Host(`login.traefik.me`)"
      - "traefik.http.routers.identityserver4STS.entrypoints=web"
    environment:
      - VIRTUAL_HOST=login.traefik.me
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://+:80
      - DOTNET_USE_POLLING_FILE_WATCHER=1
      - "AdminConfiguration__IdentityAdminBaseUrl=http://idsrv4admin.traefik.me"
    networks:
      - proxy

networks:
  proxy:
    driver: bridge

У кого-нибудь есть идея?

Заранее спасибо


person Gobelet    schedule 23.11.2020    source источник


Ответы (2)


Вы пытаетесь подключиться к 127.0.0.1 Connected to login.traefik.me (127.0.0.1) port 80 (#0), который отправит вас на 127.0.0.1 внутри вашего контейнера администратора, а не на вашем компьютере.

Чтобы это работало, вам нужно сопоставить login.traefik.me с вашим локальным адресом (192.168.xx)

Кроме того, было бы лучше, если бы вы вызывали эту конечную точку с именем службы, поскольку все контейнеры находятся в одной сети, вы можете заменить эту переменную среды

- "AdminApiConfiguration__IdentityServerBaseUrl=http://login.traefik.me"

С

- "AdminApiConfiguration__IdentityServerBaseUrl=http://sts.identity:80"
person Andrei Stoicescu    schedule 23.11.2020
comment
Спасибо, если я изменю 127.0.0.1 на свой IP-адрес, это сработает, но как это может работать на его машине с такими настройками? Единственная разница между ним и мной заключается в том, что он работает на Linux-машине, а я на Windows. - person Gobelet; 23.11.2020
comment
Я предполагаю, что в зависимости от версий докеров, используемых на обеих машинах, 127.0.0.1 на вашем (Windows) разрешается во внутренний контейнер, а на другом (linux) — на адрес хоста машины. - person Andrei Stoicescu; 23.11.2020
comment
dev.to/natterstefan/ On Docker for Linux, the IP address of the gateway between the Docker host and the bridge network is 172.17.0.1 if you are using default networking. Также проверьте ответ Андреаса Ягле. - person Andrei Stoicescu; 23.11.2020

Вы используете имена хостов, предоставленные службой traefik.me, которая (аналогично xip.io) предоставляет службу DNS с подстановочными знаками, разрешая домены в IP-адреса в соответствии с шаблоном поддомена.

Например, DNS-запрос к myapp.1.2.3.4.traefik.me будет разрешаться в IP-адрес, закодированный в субдомене 1.2.3.4. Если вы не укажете IP-адрес в поддомене (и не используете шестнадцатеричную нотацию), эта служба автоматически преобразуется в 127.0.0.1, что работает в большинстве случаев для настроек хост-контейнер.

Запуск на вашем хост-компьютере с использованием этого IP-адреса (localhost) указывает на ваш хост-компьютер. Поскольку вы открыли traefik с помощью docker compose, это работает, поскольку запрос с вашего локального компьютера на ваш локальный компьютер сопоставляется с контейнером (из-за сопоставления ports, которое вы определили для traefik).

Это не тот случай, когда вы работаете внутри самого контейнера. Посмотрите вывод журнала вашей команды curl:

* Connected to login.traefik.me (127.0.0.1) port 80 (#0)

Запуск точно такого же запроса внутри одного из контейнеров также будет разрешаться в IP-адрес 127.0.0.1, но внутри контейнера этот IP-адрес больше не является адресом вашего хост-компьютера, а петлевым адаптером сетевого интерфейса контейнера. Итак, в основном вы сталкиваетесь с довольно распространенной проблемой о значении 127.0.0.1 при использовании контейнеров, на что уже несколько раз отвечали здесь:

Поэтому, если вам нужно иметь одно единственное DNS-имя, которое работает с хоста и из контейнера, вам нужно переключиться на что-то вроде login.192.168.1.123.traefik.me, предполагая, что 192.168.1.123 — это IP-адрес вашего хоста. Но, как вы заметили, это требует адаптации для каждого отдельного разработчика и даже когда вы меняете сеть / Wi-Fi, к которой вы подключены.

Итак, я полагаю, что для этого не существует подходящего решения с использованием такой службы DNS с подстановочными знаками, если вы хотите использовать одно и то же доменное имя для общего доступа и вызовов между контейнерами. В производственном сценарии имя хоста будет преобразовано в общедоступный общедоступный IP-адрес, который также работает при доступе из контейнера, поскольку он будет проходить через traefik в оба конца, но это не очень хороший вариант для такой настройки разработки.

В этом сценарии вам действительно нужно указать разные домены в зависимости от того, выполняете ли вы перенаправление (используя глобально действительный домен) или используете прямой вызов из одного контейнера в другой. Они доступны с использованием внутренних имен служб docker-compose, например. например http://sts.identity или, что менее предпочтительно, имя контейнера (http://is4-sts-identity). Можете ли вы указать, что эти URL-адреса используются вместо общедоступных, соответствующим образом настроив переменную среды AdminApiConfiguration__IdentityServerBaseUrl?

person Andreas Jägle    schedule 23.11.2020