Created an app, with websocket server, which should return some answer. I could establish a ws connection to a ws server when app is not containerized in docker.
But when I containerize it in a docker, I could not establish the ws connection:
docker-compose.yml
services:
myapp
container_name: MyApp
hostname: MyApp-host
image: ${DOCKER_REGISTRY-}myapp
deploy:
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
ports:
- "3003:3003"
environment:
ASPNETCORE_URLS : "https://+:3003"
build:
context: .
dockerfile: MyApp\Dockerfile
Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
ENV ASPNETCORE_URLS=https://+:3003
EXPOSE 3003
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["AppFolder/MyApp.csproj", "AppFolder/"]
RUN dotnet restore "AppFolder/MyApp.csproj"
COPY . .
WORKDIR "/src/AppFolder"
RUN dotnet build "MyApp.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "MyApp.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyApp.dll"]
My websocket server is listening on ws://127.0.0.1:3003.
I exposed port 3003 in Dockerfile and added it it docker-compose, but I'm receiving such answer when I'm trying to establish ws connection to app in docker container via postman:
May be I've missed something in docker settings?
Any help would be much appreciated. Thanks.
UPDATE
Removed from Dockerfile
ENV ASPNETCORE_URLS=https://+:3003
And docker-compose setting is in old variant
environment:
ASPNETCORE_URLS : "https://+:3003"
But nothing changed, when I replaced connection to wss:
after changes
Maybe it could be, because for some reason env variable did not changed in env container?
Env variables screenshot
UPDATE-1
Pasted the first answer code below, but nothing changed, still could connect with app only without docker
You are trying to connect to the HTTP endpoint ws://localhost:3003, but your server only listens to the HTTPS endpoints. Change server to listen to HTTP endpoints:
ASPNETCORE_URLS : "http://+:3003"
If you want to use secure WebSockets then keep your server settings but connect to wss://localhost:3003. You also can listen to both schemas:
ASPNETCORE_URLS : "http://+:3003;https://+:3004"
In that case, you can connect either to ws://localhost:3003 or to wss://localhost:3004 (don't forget to add port 3004 binding).
NOTE: You don't need to bake ASPNETCORE_URLS into your image and expose custom ports. Let the server use default ports (80 and 443) and allow users to bind them to any port on the host:
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["AppFolder/MyApp.csproj", "AppFolder/"]
RUN dotnet restore "AppFolder/MyApp.csproj"
COPY . .
WORKDIR "/src/AppFolder"
RUN dotnet build "MyApp.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "MyApp.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyApp.dll"]
Docker-compose:
services:
myapp
container_name: MyApp
hostname: MyApp-host
image: ${DOCKER_REGISTRY-}myapp
deploy:
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
ports:
- "3003:80"
- "3004:443"
build:
context: .
dockerfile: MyApp\Dockerfile`
Now you can connect to ws://localhost:3003 or wss://localhost:3004
As a result:
The reason was, that I've used the HttpListener class on a localhost IP.
First of all I changed listen address of WebSocket Server
from : http://127.0.0.1:3003/
to : http://*:3003/
AND added a string into a docker file, after default EXPOSE values:
USER ContainerAdministrator
After that I've been able to connect to port 56222, that you could establish in docker compose or it will be established by docker itslef(without docker compose):
enter image description here
on ANY ip with that port.
Related
So I have a .NET solution with two projects. These work fine when running with dotnet run, but I'm having issues with my docker compose. When adding env variables with url paths to talk between containers, i generally use something like host.docker.internal to resolve the path to the other container, but for some reason that doesn't resolve and just gets used as, for instance, https://host.docker.internal:49833/connect/authorize instead of https://localhost:49833/connect/authorize.
This doesn't make sense to me as i literally have another project on my machine that runs with this setup just fine. what am i missing?
project 1 has a dockerfile like this:
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY ["RecipeManagement/src/RecipeManagement/RecipeManagement.csproj", "./RecipeManagement/src/RecipeManagement/"]
#COPY ["SharedKernel/SharedKernel.csproj", "./SharedKernel/"]
RUN dotnet restore "./RecipeManagement/src/RecipeManagement/RecipeManagement.csproj"
# Copy everything else and build
COPY . ./
RUN dotnet build "RecipeManagement/src/RecipeManagement/RecipeManagement.csproj" -c Release -o /app/build
FROM build-env AS publish
RUN dotnet publish "RecipeManagement/src/RecipeManagement/RecipeManagement.csproj" -c Release -o /app/out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=publish /app/out .
ENV ASPNETCORE_URLS=http://+:8080
EXPOSE 8080
ENTRYPOINT ["dotnet", "/app/RecipeManagement.dll"]
project 2 has a dockerfile like this:
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app
RUN curl -sL https://deb.nodesource.com/setup_16.x | bash -
RUN apt install -y nodejs
# Copy csproj and restore as distinct layers
COPY ["AuthServerWithDomain/AuthServerWithDomain.csproj", "./AuthServerWithDomain/"]
#COPY ["SharedKernel/SharedKernel.csproj", "./SharedKernel/"]
RUN dotnet restore "./AuthServerWithDomain/AuthServerWithDomain.csproj"
# Copy everything else and build
COPY . ./
RUN dotnet build "AuthServerWithDomain/AuthServerWithDomain.csproj" -c Release -o /app/build
FROM build-env AS publish
RUN dotnet publish "AuthServerWithDomain/AuthServerWithDomain.csproj" -c Release -o /app/out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=publish /app/out .
ENV ASPNETCORE_URLS=http://+:8080
EXPOSE 8080
ENTRYPOINT ["dotnet", "/app/AuthServerWithDomain.dll"]
and the compose looks like this:
version: '3.7'
services:
recipemanagement-db:
image: postgres
restart: always
ports:
- '63230:5432'
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: dev_recipemanagement
volumes:
- recipemanagement-data:/var/lib/postgresql/data
recipemanagement-api:
build:
context: .
dockerfile: RecipeManagement/src/RecipeManagement/Dockerfile
ports:
- "63231:8080"
environment:
ASPNETCORE_ENVIRONMENT: "Development"
ASPNETCORE_URLS: https://+:8080;
ASPNETCORE_Kestrel__Certificates__Default__Path: "/https/aspnetappcert.pfx"
ASPNETCORE_Kestrel__Certificates__Default__Password: "password"
DB_CONNECTION_STRING: "Host=recipemanagement-db;Port=5432;Database=dev_recipemanagement;Username=postgres;Password=postgres"
"AUTH_AUDIENCE": "recipe_management"
"AUTH_AUTHORITY": "https://host.docker.internal:49833"
# ^^^^^^^^^^^ not sure why this and the below don't resolve *************************************************************************
"AUTH_AUTHORIZATION_URL": "https://host.docker.internal:49833/connect/authorize"
"AUTH_TOKEN_URL": "https://host.docker.internal:49833/connect/token"
"AUTH_CLIENT_ID": "recipe_management.swagger"
"AUTH_CLIENT_SECRET": "974d6f71-d41b-4601-9a7a-a33081f80687"
"RMQ_HOST": "localhost:TBDRMQPORT"
"RMQ_VIRTUAL_HOST": "/"
"RMQ_USERNAME": "guest"
"RMQ_PASSWORD": "guest"
volumes:
- ~/.aspnet/https:/https:ro
recipemanagement-authserver:
build:
context: .
dockerfile: AuthServerWithDomain/Dockerfile
ports:
- "49833:8080"
environment:
"ASPNETCORE_ENVIRONMENT": "Development"
ASPNETCORE_URLS: "https://+:8080;"
ASPNETCORE_Kestrel__Certificates__Default__Path: "/https/aspnetappcert.pfx"
ASPNETCORE_Kestrel__Certificates__Default__Password: "password"
volumes:
- ~/.aspnet/https:/https:ro
volumes:
recipemanagement-data:
See #DavidMaze comment. Best to search on Networking in Compose as the starting point.
(The Dockerfile's should be irrelevant to your question.)
There are a couple of options, with trial and error to get the exact behavior you want. I'd encourage you to find better explanations on the following suggestions:
In your compose file, at the 'service' level, you can add extra_hosts
my-service:
extra_hosts:
host.docker.internal:host-gateway
#host.docker.internal:127.0.0.1 for linux
But when using compose, a better option is to have docker create a network specific to your containers with
docker network create --driver bridge my_recipe_ntwk
and then at the top level of your compose:
services:
volumes:
networks:
my-private-ntwk:
external:
name: my_recipe_ntwk
and then at the 'service' level
my-service-1:
networks:
- my-private-ntwk
my-service-2:
networks:
- my-private-ntwk
For postgres running on the host, see this answer and there should be a few other similar answers.
I believe if all services are configured on the same bridge network, you actually use the service name, e.g. my-service-1:8080 and don't inclue the https. I might be wrong. (In my case, my containers connect to Postgres on the host itself, and that requries 'extra_hosts' and it's own special workaround.) You are hosting a Postgres container, so I believe your connection host and port, when using the bridge network, would simply be my-private-ntwk:5432
Currently, I have app (.Net Core 3.1) which is listening on port 40003. Now I'm trying to put it into a container. I created dockerfile:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 40003
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /src
COPY ["myProject/myProject/myProject.csproj", "myProject/myProject/"]
RUN dotnet restore "myProject/myProject/myProject.csproj" --configfile ./NuGet.Config
COPY . .
WORKDIR "/src/myProject/myProject"
RUN dotnet build "myProject.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "myProject.csproj" -c Release -o /app/publish
FROM base AS final
ENV ASPNETCORE_URLS=http://*:40003
ENV ASPNETCORE_ENVIRONMENT="development"
EXPOSE 40003
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "myProject.dll"]
As you see I exposed port 40003 and set variable ASPNETCORE_URLS.
I run it:
docker run -it --rm --name myTag -p 40003:40003 myTag
When I log into container:
docker exec -it myTag bash
and executing:
wget http://localhost:40003
I got the expected result. So I believe that my component inside the container is alive and listening
However when I am trying to go to
http://localhost:40003
from my local browser, I'm receiving ERR_EMPTY_RESPONSE.
Can you give some advice? Thank you in advance.
Edit:===================
I posted a complete docker file. (added first 3 lines to docker file which defines base).
Yes I'm sure that I posted to HTTP (not https).
http://localhost:40003 returns correct response which is a custom "selftest"
On not development env this endpoint is blocked. Something like:
[HttpGet]
[HttpPost]
public JsonResult<DiagnosticsResult> ServerStatus()
The response: I really got no response. No 200, 404 etc. simple nothing.
Also I'm logging now that result of self tests. Above when I'm inside the docker
INFORMATION 2021-11-30 09:15:48,738 [Omdc.SelfHost.Base.Tests.MinimumDiskSpaceTest.Run] MinimumDiskSpaceTest starting.
INFORMATION 2021-11-30 09:15:48,741 [Omdc.SelfHost.Base.Tests.MinimumDiskSpaceTest.Run] Drive: /, Volume label: /, Total available space: 82%
But when I'm requesting from a local browser there are neither console logs nor HTTP responses.
So my request to not reach the endpoint (?)
I'm having a lot of issues using docker for a C# application.
Here's the first issue I have: I need to run an image in a docker container running on port 8080. I have tried everything inside Visual Studio 2019 but I can't find a way to make it run on port 8080. Basically when I click on the play button it ignores the entry EXPOSE 8080/tcp of dockerfile and runs the image in a container on a random port.
I have tried running the immage from the command line by using "docker run -d -p 8080:80 aspnetapp" where 'aspnetapp' is the name of the image. Everything seems fine and and in Docker Desktop I can see it was trying to run on port 8080 but the container exits with error code 0.
When I run from Visual Studio everything works fine but I can't change to port 8080.
Here is my dockerfile:
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 8080/tcp
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["ProductDirectory.csproj", "."]
RUN dotnet restore "./ProductDirectory.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "ProductDirectory.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "ProductDirectory.csproj" -c Release -o /app/publish
EXPOSE 8080/tcp
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ProductDirectory.dll"]
It's a good idea to use multiple stage inside your Dockerfile.
but you should be careful about that because Docker take only the latest part of your dockerfile , in your case it's take only this part :
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ProductDirectory.dll"]
where you didn't define the port for your application .
to resolve this issue just add EXPOSE port and specify your port for this section, like that:
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
EXPOSE 8080
ENTRYPOINT ["dotnet", "ProductDirectory.dll"]
And I hope that can help you to fix your issue.
When I run my .net core3/angular spa application on my local machine everything works. But when I try to put everything in docker-compose while having 2 services one for front-end and one for API only the angular portion works. When angular makes a call to the API the endpoint cannot be reached.
here's my docker-compose
version: '3.4'
services:
test.ang.c:
image: ${DOCKER_REGISTRY-}test.ang.c
build:
context: ./test-ang
# dockerfile: JrTech.Angular.Docker/Dockerfile
test.ang.angular:
image: ${DOCKER_REGISTRY-}test.ang.angular
build:
context: ./test-ang
dockerfile: ./ClientApp/Dockerfile
args:
- skip_client_build=true
ports:
- "4200:4200"
- "49153:49153"
volumes:
- ./test-ang/ClientApp:/app
Dockerfile in test-ang/
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
# EXPOSE 4200
#EXPOSE 5001
# FROM node:10.15-alpine AS client
# ARG skip_client_build=false
# WORKDIR /app
# COPY ./ClientApp .
# RUN [[ ${skip_client_build} = true ]] && echo "Skipping npm install" || npm install
# RUN [[ ${skip_client_build} = true ]] && mkdir dist || npm run-script build
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
# RUN npm update
WORKDIR /src
COPY ["./test-ang.csproj", "."]
RUN dotnet restore "./test-ang.csproj"
COPY . .
WORKDIR "/src/test-ang"
# RUN echo ls
RUN dotnet build "../test-ang.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "../test-ang.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "./test-ang.dll"]
Dockerfile in ClientApp (angular app):
FROM node:10.15-alpine AS client
EXPOSE 4200 49153
USER node
RUN mkdir /home/node/.npm-global
ENV PATH=/home/node/.npm-global/bin:$PATH
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
RUN npm install -g #angular/cli#8.1.0
WORKDIR /app
CMD ["ng", "serve", "--port", "4200", "--host", "0.0.0.0", "--disable-host-check", "--poll", "2000"]
Startup.cs
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{ // This starts up npm with server
// spa.UseAngularCliServer(npmScript: "start");
// spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
spa.UseProxyToSpaDevelopmentServer("http://test.ang.angular:4200");
}
});
fetch-data.component.ts
#Component({
selector: 'app-fetch-data',
templateUrl: './fetch-data.component.html'
})
export class FetchDataComponent {
public forecasts: WeatherForecast[];
constructor(http: HttpClient, #Inject('BASE_URL') baseUrl: string) {
http.get<WeatherForecast[]>(baseUrl + 'weatherforecast').subscribe(result => {
this.forecasts = result;
}, error => console.error(error));
}
}
Quick answer:
Update angular code to access api using test.ang.c url such as http://test.ang.c/api/values. and you should be fine.
Long answer:
UseProxyToSpaDevelopmentServer is only intended to be used during development, and not after you deploy it to docker. IsDevelopment is already taking care of that so you don't have to worry.
While working on docker there are two networks:
1. Inside docker (docker network ls command will show you that)
2. Host machine network.
docker run -p <host port>:<docker port> <container name>
When you are inside the docker network you'll have to use <docker port> like 80/4200 for accessing from the local computer you'll have to use <host port>.
When you connect your angular app to your backend, you're loading the frontend from the server to your browser and also hitting the backend from your browser, that is from outside docker.
Your current problem is that you're not exposing the backend port in the docker-compose file and your browser can't reach it. You can expose that port with the ports: directive you're already using but applying it to the other container.
By the way, I've had some troubles exposing ports 80 and 443 to outside docker, apparently they sometimes generate problems for being reserved ports, I'd recommend to expose other ones.
I am using docker-compose to host a .Net Core Web application created using the template from .Net Core.
I have my docker-compose as follows:
version: '3.4'
services:
db:
image: mysql:5.7
container_name: mysql_db
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: "root"
MYSQL_HOST: "localhost"
MYSQL_ROOT_HOST: "%"
todoservice:
image: ${DOCKER_REGISTRY}todoservice
ports:
- "8000:80"
build:
context: .
dockerfile: ToDoService/Dockerfile
depends_on:
- db
volumes:
db_data:
In which I declare that my host machines port of 8000 will map to port 80 on this docker container. As well I have this dockerfile that defines how to build my .Net Core Web Api.
FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80
FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
COPY ToDoService/ToDoService.csproj ToDoService/
RUN dotnet restore ToDoService/ToDoService.csproj
COPY . .
WORKDIR /src/ToDoService
RUN dotnet build ToDoService.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish ToDoService.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "ToDoService.dll"]
After I run docker-compose up -d I see that my ToDoService is listing this information for PORTS:
0.0.0.0:8000->80/tcp, 0.0.0.0:32772->80/tcp
So where is that random 32772 port assignment coming from?
When I specify the :443 it runs the debug (docker compose set to VS) consistently using the port I set (here I picked my port as 51836). Also I get the Swagger endpoint on the same port: https://localhost:51836/swagger/index.html
My docker-compose.yml:
version: '3.4'
services:
company.api.authservices:
image: ${DOCKER_REGISTRY-}company-api-auth-services
build:
context: .
dockerfile: Company.Api.AuthServices/Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=Production
ports:
- "51830:80"
- "51836:443"