简体   繁体   中英

API with dotnet/angular spa app cannot be reached inside docker container but can be reached outside docker container

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM