具有 docker-compose 的容器具有不同的行为,具体取决于执行它们的机器
Containers with docker-compose have different behavior depending on machine where they are executed
美好的一天,
我试图让下面的 docker-compose 在我的机器上工作,但是当我试图从容器 B 访问容器 A 的 url 时,我遇到了一些 404 错误的问题。
先验唯一不在源代码管理中的是主机文件中的修改,我必须在其中添加以下行。
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 上尝试 curl,我会收到 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
有人有想法吗?
提前致谢
您正在尝试连接到 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.x.x)
此外,如果您使用服务名称调用该端点会更好,因为所有容器都在同一网络中,您可以替换此环境变量
- "AdminApiConfiguration__IdentityServerBaseUrl=http://login.traefik.me"
有
- "AdminApiConfiguration__IdentityServerBaseUrl=http://sts.identity:80"
您正在使用 traefik.me 服务提供的主机名,该服务(类似于 xip.io)通过根据子域模式将域解析为 IP 来提供通配符 DNS 服务。
例如,对 myapp.1.2.3.4.traefik.me
的 DNS 查询将解析为在子域 1.2.3.4
中编码的 IP 地址。如果您没有在子域中指定 IP 地址(也不使用十六进制表示法),则此服务会自动解析为 127.0.0.1
,这在大多数情况下适用于主机到容器设置。
运行 在您的主机上,使用此 IP 地址(本地主机)指向您的主机。当您使用 docker compose 公开 traefik 时,这可以作为从本地计算机到本地计算机的请求映射到容器(由于您为 traefik 定义的 ports
映射)。
当 运行 在容器本身内部时,情况并非如此。查看 curl 命令的日志输出:
* Connected to login.traefik.me (127.0.0.1) port 80 (#0)
运行 来自其中一个容器内部的完全相同的请求也将解析为 127.0.0.1 IP,但在容器内部此 IP 地址不再是您的主机地址,而是环回适配器容器网络接口。所以基本上你 运行 在使用容器时遇到了一个关于 127.0.0.1
含义的非常普遍的问题,因为这里已经回答了好几次:
因此,如果您需要从主机和容器中使用一个单一的 dns 名称,则需要切换到类似 login.192.168.1.123.traefik.me
的名称,假设 192.168.1.123
是您的主机 IP 地址。但是正如您所注意到的,这需要针对每个开发人员进行调整,甚至当您更改所连接的 network/wifi 时也是如此。
因此,如果您想使用完全相同的域名进行 public 访问和容器间调用,我想没有使用这种通配符 dns 服务的首选解决方案。在生产场景中,主机名将解析为全局有效的 public IP 地址,该地址在从容器内部访问时也有效,因为它将通过 traefik 进行完整的往返,但这并不是一个好的选择开发设置。
在这种情况下,您确实需要指定不同的域,具体取决于您是发出重定向(使用全局有效域)还是使用从一个容器到另一个容器的直接调用。这些可以使用 docker-compose 内部服务名称访问,例如像 http://sts.identity
或 - 不太喜欢 - 容器名称 (http://is4-sts-identity
)。您可以通过相应地配置环境变量 AdminApiConfiguration__IdentityServerBaseUrl
来指定使用这些 url 而不是 public 吗?
美好的一天,
我试图让下面的 docker-compose 在我的机器上工作,但是当我试图从容器 B 访问容器 A 的 url 时,我遇到了一些 404 错误的问题。
先验唯一不在源代码管理中的是主机文件中的修改,我必须在其中添加以下行。
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 上尝试 curl,我会收到 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
有人有想法吗?
提前致谢
您正在尝试连接到 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.x.x)
此外,如果您使用服务名称调用该端点会更好,因为所有容器都在同一网络中,您可以替换此环境变量
- "AdminApiConfiguration__IdentityServerBaseUrl=http://login.traefik.me"
有
- "AdminApiConfiguration__IdentityServerBaseUrl=http://sts.identity:80"
您正在使用 traefik.me 服务提供的主机名,该服务(类似于 xip.io)通过根据子域模式将域解析为 IP 来提供通配符 DNS 服务。
例如,对 myapp.1.2.3.4.traefik.me
的 DNS 查询将解析为在子域 1.2.3.4
中编码的 IP 地址。如果您没有在子域中指定 IP 地址(也不使用十六进制表示法),则此服务会自动解析为 127.0.0.1
,这在大多数情况下适用于主机到容器设置。
运行 在您的主机上,使用此 IP 地址(本地主机)指向您的主机。当您使用 docker compose 公开 traefik 时,这可以作为从本地计算机到本地计算机的请求映射到容器(由于您为 traefik 定义的 ports
映射)。
当 运行 在容器本身内部时,情况并非如此。查看 curl 命令的日志输出:
* Connected to login.traefik.me (127.0.0.1) port 80 (#0)
运行 来自其中一个容器内部的完全相同的请求也将解析为 127.0.0.1 IP,但在容器内部此 IP 地址不再是您的主机地址,而是环回适配器容器网络接口。所以基本上你 运行 在使用容器时遇到了一个关于 127.0.0.1
含义的非常普遍的问题,因为这里已经回答了好几次:
因此,如果您需要从主机和容器中使用一个单一的 dns 名称,则需要切换到类似 login.192.168.1.123.traefik.me
的名称,假设 192.168.1.123
是您的主机 IP 地址。但是正如您所注意到的,这需要针对每个开发人员进行调整,甚至当您更改所连接的 network/wifi 时也是如此。
因此,如果您想使用完全相同的域名进行 public 访问和容器间调用,我想没有使用这种通配符 dns 服务的首选解决方案。在生产场景中,主机名将解析为全局有效的 public IP 地址,该地址在从容器内部访问时也有效,因为它将通过 traefik 进行完整的往返,但这并不是一个好的选择开发设置。
在这种情况下,您确实需要指定不同的域,具体取决于您是发出重定向(使用全局有效域)还是使用从一个容器到另一个容器的直接调用。这些可以使用 docker-compose 内部服务名称访问,例如像 http://sts.identity
或 - 不太喜欢 - 容器名称 (http://is4-sts-identity
)。您可以通过相应地配置环境变量 AdminApiConfiguration__IdentityServerBaseUrl
来指定使用这些 url 而不是 public 吗?