Docker Container Listening on http://[::]:80 - docker

I am working on setting up two Docker containers using Docker for Windows. A simple node based web app, and a dotnet core API application. I am starting both these containers using "docker-compose up". The node app starts up perfectly and I can hit the exposed URL, however the dotnet app isn't seeming to work.
The output of the docker-compose up command is below:
application.client_1 | INFO: Accepting connections at http://localhost:8080
application.api_1 | warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
application.api_1 | No XML encryptor configured. Key {cc83a8ac-e1de-4eb3-95ab-8c69a5961bf9} may be persisted to storage in unencrypted form.
application.api_1 | Hosting environment: Development
application.api_1 | Content root path: /app/application.Api
application.api_1 | Now listening on: http://[::]:80
application.api_1 | Application started. Press Ctrl+C to shut down.
The Docker file looks like the following:
FROM microsoft/dotnet AS build
WORKDIR /app
ENV PORT=8081
COPY application.Api/application.Api.csproj application.Api/
COPY application.Business/application.Business.csproj application.Business/
COPY application.DataAccess/application.DataAccess.csproj application.DataAccess/
COPY application.DataModel/application.DataModel.csproj application.DataModel/
WORKDIR /app/application.Api
RUN dotnet restore
WORKDIR /app/
COPY application.Api/. ./application.Api/
COPY application.Business/. ./application.Business/
COPY application.DataAccess/. ./application.DataAccess/
COPY application.DataModel/. ./application.DataModel/
WORKDIR /app/application.Api
RUN dotnet publish -c Release -o out
FROM microsoft/dotnet AS runtime
WORKDIR /app/application.Api
COPY --from=build /app/application.Api/out .
ENTRYPOINT ["dotnet", "application.Api.dll" ]
EXPOSE $PORT
I am unable to get an IP and thus hit the API url. Any thoughts would be much appreciated as I am pretty new to Docker.
UPDATE 1: Compose YML
version: '3.4'
services:
tonquin.api:
image: application.api
ports:
- 8081:5000
build:
context: .
dockerfile: Dockerfile
tonquin.client:
image: application.client
ports:
- 8080:8080
build:
context: .
dockerfile: ../application.Client/Dockerfile

As they've mentioned it seems your container is running on port 80. So for whatever reason that's the port being exposed.
Maybe the EXPOSE $PORT is not returning 8081 as you expect?
When you run the container, unless you specify where to map it, it will only be available at the container's IP at the exposed port (80 in your case). Find out this container Ip easily by running docker inspect <container_id>
Test your image by doing something like docker run -p 8080:80 yourimage. You'll see that in addition to the port 80 that the image exposes, it is being mapped to your local port 8080 so that http://localhost:8080 should be reachable.
See this in case it helps you

See this answer.
The base dotnet image overrides the default kestrel port. Why, I don't know. Adding the environment declaration to my docker file fixed the problem for me.

It's trying to use the IPv6 protocol on the network interface. Disable IPv6 and restart docker. It also looks like you might have both apps trying to use port 80. You can only serve one item on a given port with a given interface/IP. Try setting the API to use a different port number, like 8080.

Related

docker-compose error connection ECONNREFUSED

I have a web service that is packed inside Docker image. I use compose to build this image and run it. I use docker desktop to run docker containers.
So, to run service I just need to type:
docker-compose run app
compose file:
version: "3.6"
services:
app:
build:
context: .
target: app
ports
- 5001:5001
docker file:
FROM python:3.10-slim as app
RUN mkdir -p /app
WORKDIR /app
COPY entrypoint.sh .
CMD ["sh", "/app/entrypoint.sh"]
However, I face following issue: when I try to get this service GET http://localhost:5001/up I get Error: connect ECONNREFUSED
I can't figure out why I can't access service. Any help/comment/explanation will be mush appreciated.
Did you check if the docker is running using the command docker ps ?
If it's running, please check if the port is listening using netstat -tnulp | grep 5001
Also check if firewall is blocking the connection

ASP.NET Core Webapi startup url - Docker-Compose vs. Docker build

I am encountering an interesting difference in startup behaviour when running a simple net6.0 web api built with docker-compose in comparison to being built with docker. The application itself runs in a kubernetes cluster.
Environment
Minikube v1.26.1
Docker Desktop v4.12
Docker Compose v2.10.2
Building with docker-compose
docker-compose.yml
version: "3.8"
services:
web.api:
build:
context: ./../
dockerfile: ./web.API/Dockerfile
The context is set to the parent directory due to some files needed there.
Dockerfile
FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build
WORKDIR /src
ENV ASPNETCORE_URLS=http://+:80
COPY Directory.Build.props ./Directory.Build.props
COPY .editorconfig ./.editorconfig
COPY ["webapi/web.API", "web.API/"]
RUN dotnet build "web.API/web.API.csproj" -c Release --self-contained true --runtime alpine-x64
RUN dotnet publish "webapi/web.API.csproj" -c Release -o /app/publish \
--no-restore \
--runtime alpine-x64 \
--self-contained true \
/p:PublishSingleFile=true
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0-alpine
WORKDIR /app
EXPOSE 80
EXPOSE 443
COPY --from=build /app/publish .
ENTRYPOINT ["./web.API"]
This results in the app starting up within the kubernetes cluster with the following logs:
Now listening on: http://[::]:80
Building with docker build
Using the same Dockerfile mentioned earlier with the same build context you can see in the docker-compose.yml, a deployment to k8s results in the following log:
Now listening on: http://localhost:5000
Running the image locally
Running the exact same image from the k8s cluster locally however results in
Now listening on: http://[::]:80
Already tried
As suggested in many posts, I tried setting the environment variable ASPNETCORE_URLS via Dockerfile or k8s deployment.yml- neither of which had an impact on the startup url.
I can't seem to figure out why there is a difference between those 2 ways of building an image.
Update
The only thing that seems to work is to add
builder.WebHost.ConfigureKestrel(option =>{
option.ListenAnyIP(80);
});
to the Program.cs.
Still not sure about the reason behind the behaviour though.
A few things:
I assume that the container already running and working on port 80 (docker run) is stopped before attempting to run docker-compose?
Environment variables can be used in docker-compose.yml file
Ports most likely need to be exposed correctly, which from the Dockerfile and docker-compose.yml seems like it is not?
Environment Variables
First off, before the environmental ENV ASPNETCORE_URLS=http://+:80 is going to be of any use, your docker-compose instance does not define which ports to use, your docker-compose (if trimmed) does not show any ports.
Perhaps because the ports aren't exposed, this means the environmental tries to connect to 80, which fails (already in use/not exposed) and then fails, and somehow connects on 5000.
Alternatively, more likely: it does not really not _see your ENV ASPNETCORE_URLS
You can try environment variables directly in your docker-compose file:
my-service:
image: ${IMAGE_NAME}
environment:
MY_SECRET_KEY: ${MY_SECRET_KEY}
Publishing ports
In docker-compose file you need this, to publish ports:
ports:
- "80"
- "443"
... or
ports:
- "80:80" // "host-port:container-port"
- "443:1234"
Additional information
The keyword EXPOSE\expose in Dockerfile/docker-compose.yml is just informative (comments in a sense), functionally it does not process anything. A port need to be exposed (published) to be used.
So, those EXPOSE 443 & 80 is not telling Docker to use it, perhaps you are running your container for example like this:
This exposes port 80 for it to be available.
docker run -p 127.0.0.1:80:80/tcp image command
In short, use ports keyword in docker-compose.yml.
EDIT:
I read your comment above:
But the app is not accessible in k8s when listening to localhost:5000 even with correct service and container configuration
This indicates what I am trying to say regarding the ports being published or not. Your port 5000 is also not exposed because nothing in your configuration shows that is the case.

Can't access Web API hosted inside Docker container from external device on same Network

I've created a default ASP.NET Core 5 Web API through Visual Studio 2019 and have it running inside a Docker container (no https to make this example simple). I am using Windows, but the image is running as a Linux Docker Container. When I run the application from Visual Studio, it is started with Docker Compose. When the application runs I'm able to access it from my browser on the Docker host machine, but I'm not able to access it from another device on the same network.
Below are the files I'm using. You can see that I am exposing port 61234 from docker-compose.yml. Assuming my Host IP address is 192.168.1.12, if I were to navigate to http://192.168.1.12:61234/weatherforecast from a web browser on the host machine, I get a REST response from the controller. If I access that same endpoint from a different laptop on the same Wi-Fi network, the endpoint is unreachable.
I have validated that the laptop can reach the REST endpoint if the application is not running within a Docker container. For this reason, I don't believe the Windows Firewall is getting in the way.
I've looked at everything I can think of. So my question is: Is there anything else I should look at? I assume I'm missing something simple, but just can't seem to find what that might be.
The only change I made to the C# code generated by Visual Studio is making a UseUrls() call when creating the web host builder: webBuilder.UseUrls("http://*:80").UseStartup<Startup>();
Here is my docker-compose.yml file. Note the exposed TCP port and the bridge network:
version: '3.4'
services:
webapplication1:
image: ${DOCKER_REGISTRY-}webapplication1
build:
context: .
dockerfile: WebApplication1/Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "61234:80"
networks:
- practice-webapi-network
networks:
practice-webapi-network:
driver: bridge
And here is the auto-generated Dockerfile that Visual Studio created:
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["WebApplication1/WebApplication1.csproj", "WebApplication1/"]
RUN dotnet restore "WebApplication1/WebApplication1.csproj"
COPY . .
WORKDIR "/src/WebApplication1"
RUN dotnet build "WebApplication1.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "WebApplication1.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebApplication1.dll"]
One thing I want to point out. I believe I would be able to work around this by changing the network driver to Host instead of Bridge, but I need to use a Bridge network for my application. This is just a proof of concept.
Edit 1: Added missing port to example endpoint

Dont receive any information from docker

I'm struggling to move my web api to the docker containers. However, it doesnt want to run.
Running docker-compose build and then docker-compose up console shows me that app is start listening on: http://localhost:5000 and https://localhost:5001, but before those line i'm receiving: " Unable to bind to http://localhost:5000 on the IPv6 loopback interface: 'Cannot assign requested address'."
Dockerfile:
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["ShoppingCart.API/ShoppingCart.API.csproj", "ShoppingCart.API/"]
#COPY ["ShoppingCart.Domain.Entities/ShoppingCart.Domain.Entities.csproj", "ShoppingCart.Domain.Entities/"]
#COPY ["ShoppingCart.Domain.Interfaces/ShoppingCart.Domain.Interfaces.csproj", "ShoppingCart.Domain.Interfaces/"]
#COPY ["ShoppingCart.Infrastructure.Data/ShoppingCart.Infrastructure.Data.csproj", "ShoppingCart.Infrastructure.Data/"]
#COPY ["ShoppingCart.Infrastructure.Business/ShoppingCart.Infrastructure.Business.csproj", "ShoppingCart.Infrastructure.Businesss/"]
#COPY ["ShoppingCart.Services.Interfaces/ShoppingCart.Services.Interfaces.csproj", "ShoppingCart.Services.Interfaces/"]
RUN dotnet restore "ShoppingCart.API/ShoppingCart.API.csproj"
COPY . .
WORKDIR "/src/ShoppingCart.API"
RUN dotnet build "ShoppingCart.API.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "ShoppingCart.API.csproj" -c Release -o /app/publish
WORKDIR /app
COPY --from=build /app/build .
ENTRYPOINT ["dotnet", "ShoppingCart.API.dll"]
Docker-compose:
version: '3.9'
networks:
localdev:
name: localdev
services:
main-api:
build: .
restart: always
ports:
- "5000:80"
- "5001:443"
networks:
- localdev
So, on http://localhost:5000 and https://localhost:5001 i dont see anything...
I even tried to add some arguments to Dockerfile:
ENTRYPOINT ["dotnet", "ShoppingCart.API.dll", "--urls", "https://0.0.0.0:5000"]
And after this, i dont receive the error of not assignning requested address. And also, cant reach any content on those ports...
Problem
You are binding port 5000 on your localhost to 80 on your docker container (and same with 5001:443). Is that really what you want to do? Since this is an aspnet-core project you are most likely running your webapp on port 5000 or 5001 (in the container), not 80 or 443. It also seems that you may already be running something on port 5000 on your localhost so docker is failing to bind it (I assume you're running your app probably).
Solution
You most likely need to:
Bind to ports 5000/5001 in your container, not 80/443.
Shut down what's running on port 5000 in your localhost environment, or pick another port to bind that isn't in use.
For example, lets pick a random higher port that isn't being used:
version: '3.9'
services:
main-api:
build: .
ports:
- "6000:5000"
- "6001:5001"
Bring this up with docker-compose up and then see what you get from http://localhost:6000 or https://localhost:6001.
Notes
It looks like you're attempting to create a multi-stage docker build where your app is built inside the sdk image and then run inside the aspnet image. But you are not introducing the aspnet image, so your container's runtime environment is still sdk which includes a lot of stuff we don't need in the runtime. You should add this line after your publish to change to the aspnet image. Example.
FROM mcr.microsoft.com/dotnet/aspnet:3.1

Could not access Web API inside docker container from localhost

I know that there are many discussion about this, but none of the proposed solutions worked for me, so I will have to know at least if I was doing something wrong or I was hitting a limitation.
Step 1.
I created the default .NET Core 2.0 WEB API project from Visual Studio, nothing special here, output type set to Console Application, running OK from Visual Stuido 2017 Community.
Step 2. I installed latest Docker Toolbox since I am running Windows 10 Home Edition, that installed also the Virtual Box.
Step 3. I added the following docker file next to the sln:
FROM microsoft/aspnetcore-build:2.0
WORKDIR /app
EXPOSE 80
COPY . .
RUN dotnet restore
RUN dotnet build
WORKDIR /app/DockerSample
ENTRYPOINT dotnet run
Next
Step 4. I successfully build the image with a command like 'docker build -t sample1 .'
Step 5. The container successfully started to run, it was started by the following command 'docker run -d -p 8080:80 sample1'
Step 6. Pull info about the container using command docker logs c6
The following info was shown:
Interesting here is the address where the service is listening, this seems to be the same with the address I was getting when running the service directly from Visual Studio.
Is this the service address from the virtual machine that is running inside Virtual box ? Why the port is not 8080 or 80 as I mentioned inside of the "run" command ?
The container looks ok, something like:
Step 7.
Now starts the fun trying to hit the service from Windows 10 machine, was impossible using calls like http://localhost:8080/values/api I also tried calls like http://192.168.99.100:8080/values/api where 192.168.99.100 is the address of the default docker machine.
I also tried with something like 'http://172.17.0.2:8080/values/api' where the IP address was got after a call like 'docker inspect a2', changing the port to 80 did not help :).
Trying to change the port number to 80 or 58954 , the one shown in red as listening, did not help. Also Windows Firewall or any other firewalls were stopped.
I tried to port forward from VirtualBox having something like
Trying to change the 80 and 8080 ports between them for host and guest also did not work.
Basically none of the suggested solutions I found did not gave me the chance to hit the service from my Windows machine.
Mainly I was following this tutorial https://www.stevejgordon.co.uk/docker-for-dotnet-developers-part-2 which explains quite well what should be done only that at some point is using the Docker Desktop for Windows so the Docker Toolbox was left behind.
Do you know what should I do so that I can hit the service from the docker container ?
In docker compose (visual studio add docker integration "docker-compose.yml") set this:
version: '3.4'
services:
webapi.someapi:
image: ${DOCKER_REGISTRY-}somenamesomeapi
build:
context: .
dockerfile: ../webapi/Dockerfile
environment:
- ASPNETCORE_URLS=https://+:443;http://+:80
- ASPNETCORE_HTTPS_PORT=443
ports:
- "80:80"
- "443:443"
in lunch settings specify your app to start on ports 80 and 443 https
Docker for visual studio code: https://marketplace.visualstudio.com/items?itemName=PeterJausovec.vscode-docker
Follow this steps to orchestrate your containers:
https://marketplace.visualstudio.com/items?itemName=PeterJausovec.vscode-docker
For your issue, it is caused by that you run the container under Development environment which did not use the port 80 for the application.
For FROM microsoft/aspnetcore-build:2.0, it seems you could not change the ASPNETCORE_ENVIRONMENT to Production.
For a solution, you could change your docker file like below which change the base image with microsoft/aspnetcore:2.0.
FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80
FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
COPY ["TestAPI/TestAPI.csproj", "TestAPI/"]
RUN dotnet restore "TestAPI/TestAPI.csproj"
COPY . .
WORKDIR "/src/TestAPI"
RUN dotnet build "TestAPI.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "TestAPI.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "TestAPI.dll"]

Resources