I am running a dotnet core app using Kubernetes with Docker.
The setup is as follows:
APP
In the dotnet core app, I have Kestrel server listening on port 8080 by setting the following in Program.cs:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseKestrel(options =>
{
options.Listen(IPAddress.Loopback, 8080);
})
.Build();
I have tested the app build locally and the endpoint works as expected on localhost:8080/api/test
.
DOCKER IMAGE
In the Dockerfile I have the following:
EXPOSE 8080
I understand this to mean that the container gets built with an exposed 8080 port.
Question 1: ...does this necessarily mean that the container's 8080 is mapped to the app's 8080? If not, how do I map this?
KUBERNETES (MINIKUBE)
Within Kubernetes (running locally on Minikube), I then use a Replication Controller to create 3 pods that each contain 1 docker container with the app. My RC file looks like this:
{
"apiVersion": "v1",
"kind": "ReplicationController",
"spec": {
"replicas": 3,
"selector": {
"app": "myApp"
},
"template": {
"metadata": {
"labels": {
"app": "myApp"
}
},
"spec": {
"containers": [
{
"name": "my-app",
"image": "myname/myapp:1.0",
"ports": [
{
"containerPort": 8080
}
]
}
]
}
}
}
}
Notice "ports": [{ "containerPort": 8080 }]
. The way I understand it, this means that the container port I want to expose is 8080.
I then have a Kubernetes Service that exposes my 3 pods' 8080 ports through the endpoint [minikubeIPAddress]:30001
:
{
"apiVersion": "v1",
"kind": "Service",
"spec": {
"type": "NodePort",
"ports": [
{
"port": 8080,
"nodePort": 30001,
"protocol": "TCP"
}
],
"selector": {
"app": "myApp"
}
}
}
When I try to hit the endpoint [minikubeIPAddress]:30001/api/test
I am getting a 'site can't be reached' error.
I had it working this morning when I was using the default HTTP port 80. The only changes that have been made are to the port numbers.
Question 2: ...have I missed something here? Is there a connection along the line here that is still mapped to the default port of 80?
Any help would be much appreciated.
After much trial and error I found the solution.
In line with what @johnharris85 and @Yuankun said about the IP Address needing to be set to 'any' rather than on the localhost, I found this article: http://blog.scottlogic.com/2016/09/05/hosting-netcore-on-linux-with-docker.html
The dotnet core app defaults to using the localhost network, and while running locally on a test machine, this works fine. However, running a dotnet app inside a Docker container means that the localhost network is restricted to within the container.
To solve this, I initially changed
options.Listen(IPAddress.Loopback, 8080);
to
options.Listen(IPAddress.Any, 8080);
However, I tested this locally and could not get the app to respond. I took this to mean that this was not a valid solution. This may have been a valid solution if I had tested it with a containerized app.
I then came across the aforementioned article and decided to try the following:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseUrls("http://*:8080")
.Build();
This solved my problem and now my app is accessible through the Kubernetes endpoint.
Thanks to everyone who gave advice.