ASP.NET Docker image exits immediately in AWS ECS - asp.net

I have a dockerized ASP.NET application that I am hosting on AWS ECS. I have a task definition with one container image: the ASP.NET app, which is marked as essential. When I run that task in a service, the task provisions, is running, and then immediately changes to DEPROVISIONING (Essential container in task exited). I can run the image on my machine (with Docker Desktop) with no problem, the image listens on the specified port and doesn't exit, as expected. The issue seems to be that when I run that container on ECS, the container immediately exits.
Here is my Dockerfile, I don't see anything wrong, but I could be mistaken.
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /App
# Copy everything
COPY . ./
# Restore as distinct layers
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
EXPOSE 80
WORKDIR /App
COPY --from=build-env /App/out .
ENTRYPOINT ["dotnet", "webapi.dll"]

I found my issue after looking at the logs like Hans Kilian was wondering.
The error I was getting was "exec /usr/bin/dotnet: exec format error". After reading This post, I discovered that the platform I was building for was specific to my machine, an m1 mac. In order to run my container on AWS Fargate, I had to build for linux amd64, using this command: docker buildx build --platform=linux/amd64 -t {app-name}:latest.

Related

Docker Windows Container API with EFCore connecting to microsoft/mssql-server-windows-developer container

Fact 1. I've got 2 windows containers for:
MSSQL Server Developer Edition (microsoft/mssql-server-windows-developer)
Asp.Net Core API 5.0 (5.0.102) (solomiosisante/consequence:api)
Fact 2. No problem accessing the SQLServer container data from Management Studio (SSMS).
Fact 3. No problem when I run the API project from Visual Studio accessing the SQLServer container.
Fact 4. The problem is when I run both containers, the error says:
fail: Microsoft.EntityFrameworkCore.Database.Connection[20004]
An error occurred using the connection to database 'Consequence' on
server 'localhost,14344'.
fail: Microsoft.EntityFrameworkCore.Query[10100]
An exception occurred while iterating over the results of a query for
context type 'Consequence.EF.Models.ConsequenceContext'.
Microsoft.Data.SqlClient.SqlException (0x80131904): A network-related
or instance-specific error occurred while establishing a connection to
SQL Server. The server was not found or was not accessible. Verify
that the instance name is correct and that SQL Server is configured to
allow remote connections. (provider: TCP Provider, error: 0 - No
connection could be made because the target machine actively refused
it.)
SQL Server Container:
The SQL Container came from the image I built using microsoft/mssql-server-windows-developer. I attached my db and created an image and uploaded it to my docker hub existing repo solomiosisante/consequence:sqlexpress. I used the sqlexpress image before, thus the tagname :sqlexpress. I've yet to change it to :developer.
API Dockerfile:
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["Consequence.API/Consequence.API.csproj", "Consequence.API/"]
RUN dotnet restore "Consequence.API/Consequence.API.csproj"
COPY . .
WORKDIR "/src/Consequence.API"
RUN dotnet build "Consequence.API.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Consequence.API.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENV ASPNETCORE_URLS="https://+;http://+"
ENV ASPNETCORE_HTTPS_PORT=44388
ENV ASPNETCORE_Kestrel__Certificates__Default__Password="P#ssw0rd123"
ENV ASPNETCORE_Kestrel__Certificates__Default__Path=/src/certs/consequence.pfx
ENTRYPOINT ["dotnet", "Consequence.API.dll"]
I also tried:
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
#COPY ["Consequence.API/Consequence.API.csproj", "Consequence.API/"]
#COPY ["Consequence.EF/Consequence.EF.csproj", "Consequence.EF/"]
#COPY ["Consequence.Repositories/Consequence.Repositories.csproj", "Consequence.Repositories/"]
COPY . .
RUN dotnet restore "Consequence.API/Consequence.API.csproj"
Build and Run Scripts:
SQL Container:
docker run --name=sqlserver-container -d -p 14344:1433 -e sa_password=P#ssw0rd123 -e ACCEPT_EULA=Y solomiosisante/consequence:sqlexpress
ASP.Net Core 5.0.102 Container:
dotnet dev-certs https -ep certs\consequence.pfx -p P#ssw0rd123
dotnet dev-certs https --trust
docker build --pull -t consequenceapi:latest --file Consequence.API/Dockerfile .
docker run -d -p 8088:80 -p 44388:443 -v C:\SolRepo\Consequence\certs\:C:\src\certs --name consequenceapi consequenceapi:latest
Dockerhub repo for API: solomiosisante/consequence:api
I also tried:
docker run -d -p 8088:80 -p 44388:443 -e ASPNETCORE_URLS="https://+;http://+" -e ASPNETCORE_HTTPS_PORT=8001 -e ASPNETCORE_Kestrel__Certificates__Default__Password="P#ssw0rd123" -e ASPNETCORE_Kestrel__Certificates__Default__Path=\https\aspnetapp.pfx -v $env:USERPROFILE\.aspnet\https:C:\https\ --name consequenceapi solomiosisante/consequence:api
I've read about docker network and tried all sorts. Still no luck. I'm hoping that this is not because I'm using Windows containers and that is one of the limitations of using it.
Given these facts, any ideas, comments, thanks in advance.

In Docker for windows, how do i access a webapi running on my dev machine from the container i aslo have on my machine?

I am currently running docker for windows with a container using the asp.net core 2.0 image.
I also have a web api application running on iis on the development machine (the same machine i have docker installed with the container)
I need to be able to make an API request to the api on my dev machine.
I cant seem to get this to work.
Any help would be appreciated
Update:
My docker file
FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80
FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
COPY mysol.sln ./
COPY mysol.Web/mysol.Web.csproj mysol.Web/
RUN dotnet restore -nowarn:msb3202,nu1503
COPY . .
WORKDIR /src/CraOrchestrator.Web
RUN dotnet build -c Release -o /app
FROM build AS publish
RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "mysol.Web.dll"]
I am running the container with
docker run -dit -p 1253:80 -v c:/data:/data --name sol mysol:latest
There should not be any problem for your containerised app to reach an app running on the host or even a different container. The problem may be in the .dockerfile.
You only need the executables in your image to correctly run your application. Your .dockerfile may look like:
# use microsoft dotnet core as base image - including ASP.NET Core
FROM microsoft/dotnet:2.0.5-runtime
# set the working directory
WORKDIR /app
# copy executables
ADD . /app
# make port 5050 available - should not matter much since this is a client app
EXPOSE 5050
# run app
CMD ["dotnet", "mysol.Web.dll"]
To create the image:
docker build -t app-image .
To run the container (and so your application):
docker run --name myapp -p 4000:5050 app-image
You may not require the port setup since the application you run is the one performing requests to the Web API running in IIS.

Why does aspnet core start on port 80 from within Docker?

TL;DR: Why does an aspnet core app run on port 80 from within a Docker image, but 5000 outside a docker image.
Elaborate
I went through the aspnet core / docker tutorial found here:
https://learn.microsoft.com/en-us/dotnet/core/docker/building-net-docker-images
Half way through the page, I start the application with the following as prescribed:
dotnet run
Among other things, this prints this:
Now Listening on: http://localhost:5000
Great. That is what I expected. The next thing in the tutorial is to start the exact same application from within a Docker image.
docker build -t aspnetapp .
docker run -it --rm -p 5000:80 --name aspnetcore_sample aspnetapp
This results in
Now listening on: http://[::]:80
Wait. Wat? Why is the aspnet core app running on port 80? It was running on port 5000 when I ran it directly from the machine. There were no configuration file changes.
I suspect that it has something to do with the base docker images, but am not yet skilled enough in docker to track this down.
The microsoft/aspnetcore-build container builds on top of the
microsoft/aspnetcore container. The dockerhub page for that says:
A note on ports
This image sets the ASPNETCORE_URLS environment variable to http://+:80 which means that if you have not explicity set a URL in your application, via app.UseUrl in your Program.cs for example, then your application will be listening on port 80 inside the container.
So this is the container actively setting the port to 80. You can override it, if you want, by doing this in your Dockerfile:
ENV ASPNETCORE_URLS=http://+:5000
Also, it is worth noting that because of the docker command you are using, you will still be able to access the application at http://localhost:5000 whether you are running the application directly or in a container.
without dockerfile you can set any port out of the docker container. (.NET Core 3.1, .NET 5, .NET 6, .NET 7+) with docker args
docker run -it --rm -p 5000:80 -p 5001:443 -e ASPNETCORE_HTTPS_PORT=https://+:5001
-e ASPNETCORE_URLS=http://+:5000 --name aspnetcore_sample aspnetapp
more details:
https://github.com/dotnet/dotnet-docker/blob/17c1eec582e84ba9cbea5641cd9cc13fe1a41c39/samples/run-aspnetcore-https-development.md?plain=1#L85
https://github.com/dotnet/dotnet-docker/blob/5926a01d44bd47b6202ba71e30f9faa08fad1aec/samples/run-in-sdk-container.md?plain=1#L109
If you are using .NET Core 2.2 or higher, then you should to use another image: mcr.microsoft.com/dotnet/core/aspnet:2.2. In that case specifying ENV ASPNETCORE_URLS=http://+:5000 does not help. You still can force app to listen to port 5000 by using UseUrls("http://*:5000") in Programs.cs file.
Some links in other answers are for older versions, or no longer exist. The below applies to v6.
All the mcr.microsoft.com/dotnet/aspnet images are here. Suppose you are using the alpine version.
The aspnet image is based on the runtime image, as shown here.
The runtime image is based on the runtime-deps image, as shown here.
The runtime-deps image is based on the amd64/alpine image, as shown here (an older version, but with the same structure). And it sets ENV ASPNETCORE_URLS=http://+:80, as shown here, which means the container is listening on port 80.
Windows Networking Stack Limitation plays hard on Windows Docker Container.Reference Video
docker run -it --rm -p ${host_computer_port}:${container_port} --name ${container_name} ${image_name}
Example of the command:
docker run -it --rm -p 5000:8090 --name dockerwebapp9172020c dockerwebapp9172020
What is above command mean?
Your machine Port (5000) is mapped to container Port (8090). It does not mean that application running in container listening on PORT: 8090. See docker file below on how to map container port to application port.
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-nanoserver-1903 AS base
WORKDIR /app
EXPOSE 8090
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-nanoserver-1903 AS build
WORKDIR /src
COPY ["DockerWebApp/DockerWebApp.csproj", "DockerWebApp/"]
RUN dotnet restore "DockerWebApp/DockerWebApp.csproj"
COPY . .
WORKDIR "/src/DockerWebApp"
RUN dotnet build "DockerWebApp.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "DockerWebApp.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENV ASPNETCORE_URLS http://*:8090
ENTRYPOINT ["dotnet", "DockerWebApp.dll"]
Testing
Windows Networking Stack Limitation will not allow to run following command directly.
http://localhost:5000
Let's get on with first workaround.
Workaround-1 Directly hit Container. (Below command in PowerShell or Command Prompt)
ps c:/>docker inspect f31e8add55af
Find IP Address of a container from "NETWORKS" node at very end and run command in browser.
http://{container IP}:8090
Workaroud-2 From Windows Host
Let's find Your Machine IP address first.
c:\>ipconfig
Once you find your Machine IP, run following command.
http://{Your Machine IP}:5000
since 5000 is mapped to container port(8090) and asp.net core application is also listening to 8090 port within container.
Reference:Windows Containers and Docker: 101

Asp.Net Core on Docker

I'm currently trying to launch a Docker component with a ASP.NET Core application.
I use the following repo for my test : https://github.com/aspnet/cli-samples
I ran the following commande without any issue :
git clone https://github.com/aspnet/cli-samples aspnet-Home
cd aspnet-Home/HelloWeb
cat Dockerfile
FROM microsoft/aspnetcore
WORKDIR /app
COPY . .
ENTRYPOINT ["dotnet", "helloweb.dll"]
sudo docker build –t helloweb .
sudo docker run -d helloweb
The image is visible using the sudo docker images, but the container doesn't launch and is not visible with sudo docker ps:
And if I browse my website, obsviously I do not see data.
Is the repo not good for my test ? Is there any mistake I do on the docker container creation ?
Running the -it command give me the following output:
The error you highlighted is because helloweb.dll you set as the ENTRYPOINT doesn't exist. There could be two reasons for it
1 You didn't build the project yet
In this case you should run dotnet restore from the project home directory, then navigate to HelloWeb directory and run dotnet publish. When I run this command, I see the following:
publish: Published to /code/HelloWeb/bin/Debug/netcoreapp1.0/publish
Published 1/1 projects successfully
2 You built the project, but the ENTRYPOINT path is wrong
COPY . . directive will copy everything from the current directory into your app directory. That means HelloWeb.dll will actually be in bin/Debug/netcoreapp1.0/publish/ (or bin/Release/... for release builds).
Option 1: Modify your entrypoint with the full path
ENTRYPOINT ["dotnet", "bin/Debug/netcoreapp1.0/publish/HelloWeb.dll"]
Your application should happily start and serve requests.
Option 2: Modify your COPY directive
Once your project has been published, everything you'll need to run it will be in the publish directory. You could copy the contents of that into the /app directory and your entrypoint will be correct. That would look like this
FROM microsoft/aspnetcore
WORKDIR /app
COPY ./bin/Debug/netcoreapp1.0/publish/ .
EXPOSE 80
ENTRYPOINT ["dotnet", "HelloWeb.dll"]
You will also probably want to add the EXPOSE directive to tell Docker that your container will be listening on port 80.
When that succeeds, you should see (if you run in interactive mode)
docker run -it helloweb
Hosting environment: Production
Content root path: /app
Now listening on: http://+:80
Application started. Press Ctrl+C to shut down.
You could also use the microsoft/dotnet:latest image instead. That image comes with the SDK installed and a very convenient run command. The Dockerfile would look like this
FROM microsoft/dotnet:latest
COPY . /app
WORKDIR /app
RUN dotnet restore
ENV ASPNETCORE_URLS http://*:5000
EXPOSE 5000
ENTRYPOINT ["dotnet", "run"]
and you should be able to modify your source and build and run your container.

Docker ASP.net 5 beta4 kestrel doesn't keep container running

I was playing with ASP.net 5 beta 4 docker image.
I am running the container with the entrypoint dnx /app kestrel.
The Dockerfile is standard from tutorials:
FROM microsoft/aspnet:1.0.0-beta4
MAINTAINER "xxxx" <xxxx>
#this contains project.json etc
COPY ./app /app
WORKDIR /app
RUN ["dnu", "restore"]
EXPOSE 5004
ENTRYPOINT ["dnx", "/app", "kestrel"]
The container starts and exits immediately, the logs for the container shows:
"Started" which indicates that there were no errors starting kestrel.
The docker command I used was docker run -d -p "5004:5004" my_asp_net_5_docker_image:1.0.0
What intrigues me is that if I run the container with a pseudo-tty, by doing
docker run -t -i -p "5004:5004" --entrypoint="/bin/bash" my_asp_net_5_docker_image:1.0.0
and then when I am inside the docker container I run the entrypoint command manually dnx /app kestrel, kestrel starts, the output is "Started" and it remains alive, and I can access the HelloWorld website successfully.
I wonder why this difference of behaviour. Why doesn't dnx /app kestrel
keep the container alive when I run it in the entrypoint but it does when I run it from inside the container.
UPDATE:
I found something interesting here
This is a change in asp.net git hub that says "Don't require a TTY on Unix." there was a line after "Started" that did a Console.ReadLine(), it could be that this code still be in the asp.net docker image therefore it only works with tty...
UPDATE 2:
I can get it working by opening stdin (-i): docker run -d -i -p "5004:5004" my_asp_net_5_docker_image:1.0.0
Which suggests that the Console.ReadLine() could be the issue. This solves the problem for me now, but I don't think we should have to use -i to get the container running.

Resources