'Ocelot API Gateway error: No connection could be made because the target machine actively refused it
I am trying to build a microservice architecture system using Ocelot as my API Gateway. I have had the current problem for about 2 weeks and have not been able to figure out why it is happening, so I am turing to the experts and hopefully you can help :).
The structure at the moment is as follows: I have an AccountAPI and an Ocelot API Gateway. I have added the route from the API Gateway to the AccountAPI according to the docs. When I run the project, I can call the AccountAPI directly, and it works fine. But when I call through the API Gateway, I get this error.
Error Code: ConnectionToDownstreamServiceError Message: Error connecting to downstream service, exception:
System.Net.Http.HttpRequestException: No connection could be made because the target machine actively refused it.
(localhost:5101)
Quite obviously, it is not even reaching the controller of the AccountAPI, so I can't even debug >.>
The fact that I can access the object without going through the gateway tells me it is not a network / firewall issue (I turned off all my firewalls just to test, and got the same result).
This is what is in my ocelot.json file (which should connect Ocelot to the AccountAPI)
{
"GlobalConfiguration": {
"BaseUrl": "http://localhost:5111/"
},
"Routes": [
{
"DownstreamPathTemplate": "/Account/{url}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5101
}
],
"UpstreamPathTemplate": "/MeHealth/Account/{url}",
"UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE" ],
"Priority": 1
}
]
}
So if I call https:// localhost:5101/Account/1
I get my correct object returned. But with calling https:// localhost:5111/MeHalth/Account/1
I get the error. (I did also try http://
(for those who caught the scheme) and I get the same result as https)).
Other things to note: Both of these are deployed through the docker-compose with the following config:
services:
ocelotapigateway:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:443;http://+:80
ports:
- "5111:443"
volumes:
- ${APPDATA}/Microsoft/UserSecrets:C:\Users\ContainerUser\AppData\Roaming\Microsoft\UserSecrets:ro
- ${APPDATA}/ASP.NET/Https:C:\Users\ContainerUser\AppData\Roaming\ASP.NET\Https:ro
accountapi:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:443;http://+:80
ports:
- "5101:443"
volumes:
- ${APPDATA}/Microsoft/UserSecrets:C:\Users\ContainerUser\AppData\Roaming\Microsoft\UserSecrets:ro
- ${APPDATA}/ASP.NET/Https:C:\Users\ContainerUser\AppData\Roaming\ASP.NET\Https:ro
Any advice or help that you can give will be greatly appreciated. Please also let me know if you need extra information on something.
Solution 1:[1]
The problem is localhost
on your host machine is not same as localhost
when running in docker container. Think about docker as isolated "virtual machine" with its own localhost
. When your api gateway tries to reach localhost:5101
it fails because it not exists in this "virtual machine", it's running on your host machine. You have 2 solutions here:
- Use
host.docker.internal
and external port instead oflocalhost
:https://host.docker.internal:5101
. - When running 2 containers under same non-default docker network (that's what happens when you run docker-compose) they can reach each other by service name and internal port:
https://accountapi:443
Solution 2:[2]
I also trapped in the same problem just only need to commented out in API's startup file
app.UseHttpsRedirection();
and in ocelot file
"Host": "host.docker.internal",
"Port": 5101
OR
"Host": "service-name",
"Port": 80
Solution 3:[3]
Do not use https (and remove app.UseHttpsRedirection())
Use docker internal host name: "Host": "host.docker.internal"
Below is working example;
Ocelot.json
{
"Routes": [
{
"DownstreamPathTemplate": "/api/v1/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "host.docker.internal",
"Port": 7001
}
],
"UpstreamPathTemplate": "/article-service/{everything}",
"UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE" ]
},
{
"DownstreamPathTemplate": "/api/v1/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "host.docker.internal",
"Port": 7002
}
],
"UpstreamPathTemplate": "/review-service/{everything}",
"UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE" ]
}
],
"GlobalConfiguration": {
"BaseUrl": "http://localhost:7000"
}
}
docker-compose.yml
version: '3.4'
services:
data:
container_name: sqlserver
image: mcr.microsoft.com/mssql/server:2019-latest
environment:
- SA_PASSWORD=@P****
- ACCEPT_EULA=Y
ports:
- "1433:1433"
volumes:
- ./APPDATA:/var/opt/mssql/data
myapp.apigateway:
image: ${DOCKER_REGISTRY-}myappapigateway
build:
context: .
dockerfile: MyApp.ApiGateway/Dockerfile
ports:
- "7000:80"
myapp.articleservice:
image: ${DOCKER_REGISTRY-}myapparticleservice
build:
context: .
dockerfile: MyApp.ArticleService/Dockerfile
ports:
- "7001:80"
myapp.reviewservice:
image: ${DOCKER_REGISTRY-}myappreviewservice
build:
context: .
dockerfile: MyApp.ReviewService/Dockerfile
ports:
- "7002:80"
docker-compose.override.yml
version: '3.4'
services:
myapp.apigateway:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:443;http://+:80
ports:
- "80"
- "443"
volumes:
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
myapp.reviewservice:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:443;http://+:80
ports:
- "80"
- "443"
volumes:
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
myapp.articleservice:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:443;http://+:80
ports:
- "80"
- "443"
volumes:
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Saad Awan |
Solution 3 |