Run console application in google cloud>kubernetes - c#

My Code:
public static void Start()
{
tcpListener = new TcpListener(IPAddress.Any, 26950);
tcpListener.Start();
tcpListener.BeginAcceptTcpClient(TCPConnectCallback, null);
while(true){Thread.Sleep(500);}
}
private static void TCPConnectCallback(IAsyncResult _result)
{
TcpClient _client = tcpListener.EndAcceptTcpClient(_result);
//Assign _client to local server
}
My Dockerfile to create and upload an Image:
FROM mcr.microsoft.com/dotnet/sdk
COPY . /app
WORKDIR /app
RUN dotnet publish -c Release -o out
ENTRYPOINT ["dotnet", "Test.dll"]
Command in Cloud Shell:
gcloud builds submit --tag gcr.io/t****/i****
After this, I deploy it on Kubernetes Engine>Workloads
Error: CrashLoopBackOff
Solution:
FROM mcr.microsoft.com/dotnet/sdk:3.1
WORKDIR /app
COPY . .
ENTRYPOINT ["dotnet", "run"]

The error CrashLoopBackOff indicates that a container is repeatedly crashing after restarting. A container might crash for many reasons
For example:
The application inside the container keeps crashing
Some type of parameters of the pod or container have been configured incorrectly
An error has been made when deploying Kubernetes
You can get more info about your error the CrashLoopBackOff error to know why your Pod's container is crashing
To see all Pods running in your cluster, run the following command:
kubectl get pods
And to get the Pod's logs, run the following command:
kubectl logs [POD_NAME]
You can also pass in the -p flag to get the logs for the previous instance of a Pod's container, if it exists.
Check "Exit Code" of the crashed container
You can find the exit code by performing the following tasks:
Run the following command:
kubectl describe pod [POD_NAME]
Review the value in the containers: CONTAINER_NAME: last state: exit code
Additionally, check if it has restarts.
For example you can use the command
watch -n1 kubectl get pods POD_NAME
To see if the pod got some of the following states:
creatingContainer --> running --> completed --> crashloopbackoff
You could see more information about it in the following link
Also you can check this article that can help you with this issue What is a CrashLoopBackOff? How to alert, debug / troubleshoot, and fix Kubernetes CrashLoopBackOff events.
Finally, if you provide more information like the logs and more details, the community could help you more.
Edit 1
Looks like your problem come from the FROM mcr.microsoft.com/dotnet/sdk
I have found the following documentation: Create a Dockerfile for an ASP.NET Core application
You could try to use something like:
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
According to the official documentation : microsoft-dotnet-sdk these are the feature tags:
5.0 (Current)
docker pull mcr.microsoft.com/dotnet/sdk:5.0
3.1 (LTS)
docker pull mcr.microsoft.com/dotnet/sdk:3.1

Related

Can't access an ASP.NET application started in a docker container

I started a docker container with an ASP.NET app inside. The logs say that the application started successfully and is alive, but when I try to access the home page of the app I get the ERR_EMPTY_RESPONSE and the error page of the browser.
Here is my dockerfile:
# syntax=docker/dockerfile:1
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
COPY /bin/Debug/net5.0/ App/
WORKDIR /App
ENTRYPOINT ["dotnet", "TritaniumLocal.Web.Host.dll"]
Here is my docker build command: docker build -t "tritaniumlocal" .
Here is my docker run command: docker run -d -p 44311:44311 tritaniumlocal aspnetapp2.
The app starts from Visual Studio on port 44311. I tried also without port remap, but nothing helped
UPD: Here is a part of a log which can help:
warn: Microsoft.AspNetCore.Server.Kestrel[0] Unable to bind to http://localhost:44311 on the IPv6 loopback interface: 'Cannot assign requested address'. Hosting environment: Production Content root path: /App Now listening on: http://localhost:44311 Application started. Press Ctrl+C to shut down.

ASP.NET docker-compose app not coming up on assigned PORT

working my way through tutorials on dockerized the API WeatherForecast web template from ASP.NET core:
https://code.visualstudio.com/docs/containers/quickstart-aspnet-core
https://code.visualstudio.com/docs/containers/docker-compose
I had to start from here, because I wasn't getting a new image to build using the tutorial here: https://docs.docker.com/compose/aspnet-mssql-compose/
"1" works, which is great. However, "2" will not work on the localhost:5000/WeatherForecast port as advertised, and I'm having some trouble debugging why after many reviews of the available docs.
I should make a note that in creating the templated app from the command line, I did choose the --no-https option.
I then used docker ps to bring up the PORTS . The web app is using 5000/tcp, 0.0.0.0:32779->80/tcp . When I substitute 5000 for 32779 , I get the API string returned instead!
I know I'm missing something within docker-compose and could use some extra eyes on it. Thank you!
EDIT: For reference, the files below were generated by my VSCode editor.
1. I ran dotnet new webapi --no-https
2. I then brought up the VSCode "command pallete" and ran Docker: Add Dockerfiles to Workspace and selected 'yes' for the inclusion of docker-compose.yml file and Linux. I also choose to use port 5000. I use Fedora 30.
4. I run dotnet build from the project root in the terminal.
5. If I run from docker commands and make the ports explicit it will work as advertised, but if I run docker-compose -f <yml-file> up -d- --build, it will not.
I just re-read this and find it annoying that I'm stuck within VSCode to fix the issue (according to the docs)
By default Docker will assign a randomly chosen host port to a port exposed by a container (the container port). In this case the exposed (container) port is 5000, but it will be exposed on the host via a random port, such as 32737.
You can use specific port on the host by changing the Docker run options used by docker-run: debug task (defined in .vscode/tasks.json file). For example, if you want to use the same port (5000) to expose the service, the docker-run: debug task definition would look like this:
a. Dockerfile
# Please refer https://aka.ms/HTTPSinContainer on how to setup an
https developer certificate for your ASP .NET Core service.
version: '3.4'
services:
aspdotnetdocker2:
image: aspdotnetdocker2
build:
context: .
dockerfile: Dockerfile
ports:
- 5000
b. docker-compose.yml
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 5000
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /src
COPY ["aspdotnet_docker2.csproj", "./"]
RUN dotnet restore "./aspdotnet_docker2.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "aspdotnet_docker2.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "aspdotnet_docker2.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "aspdotnet_docker2.dll"]
Have a look at docker-compose docs:
SHORT SYNTAX
Either specify both ports (HOST:CONTAINER), or just the container port (an ephemeral host port is chosen).
So try:
ports:
- "5000:<port in ASPNETCORE_URLS>"
# e.g.
# - "5000:80"
# - "44388:443"

Process.Start does not redirect message to the parent context hosted by docker?

This issues has taken me one day, really I just thought it's simple at first.
I have a host machine (Windows 10) with Docker desktop for Windows installed.
From the host machine, I would like to use docker run to start a container which contains some simple code to run.
Here is the code (which is built in the container), this is a .NET core Console app (suppose its built name is console.dll):
static void Main(string[] args)
{
Console.WriteLine("Running...");
_execTest();
Console.WriteLine("Finished!");
Console.ReadLine();
}
static void _execTest()
{
var sharedFilePath = Path.Combine(Environment.CurrentDirectory, "Temp", "test.exe");
var si = new ProcessStartInfo(sharedFilePath);
si.RedirectStandardOutput = false;
si.RedirectStandardError = false;
si.RedirectStandardInput = false;
Console.WriteLine("Starting ..." + sharedFilePath);
var p = Process.Start(si);
p.WaitForExit();
}
The main code is just to start another program named test.exe. This program is put in the shared folder Temp (which is established at the time calling docker run by mounting the folders between the host machine and the container).
Here is the code for the test.exe (which is just a .NET console app):
static void Main(string[] args)
{
Console.WriteLine("Something went wrong!");
Console.Write("Welldone!");
}
So I expect that all the messages written in test.exe using Console should be directed back to the parent context (which should use one same STDOUT).
I've tested the code by running the code for container directly using dotnet console.dll and I can see the messages (from test.exe) printed expectedly.
However after deploying the console.dll to an image (console) and try the following command to run the container:
docker run --rm -v D:\SourceFolder:C:\app\Temp console
Then the messages (from test.exe) are not printed. Only the messages written directly in the parent context are printed (Running..., Starting... and Finished!).
You can see that the command above uses -v to mount the folder C:\app\Temp in container to the source folder D:\SourceFolder in the host machine.
And the test.exe is put in D:\SourceFolder.
I'm sure that the container's code can access this file via the shared folder.
This is so weird and hard to diagnose.
Without sharing messages back and forth between the container and the host, running docker like this is just useless.
I hope someone here could give me some some suggestion so that I can try and sort this out. Thanks!
UPDATE:
If I use cmd.exe (which is already existed in the docker image) with argument of /?, then I can see the output of it. So looks like this is some problem of executing an EXE shared via folder.
However I've tried copying the shared file to the some local folder of the container first and run that file instead but still the same issue. So looks like it may be the problem of the test.exe file itself? so ridiculous.
UPDATE: thanks to #jazzdelightsme for his helpful suggestion about checking the ExitCode, so actually the environment in the container has something missing that cannot start the test.exe correctly. I've tried compiling the test.exe targeting the lowest .NET Framework version 2.0 but still that same error. Here is Dockerfile's content which should provide some info about the container's environment:
FROM microsoft/dotnet:2.1-runtime-nanoserver-1709 AS base
WORKDIR /app
FROM microsoft/dotnet:2.1-sdk-nanoserver-1709 AS build
WORKDIR /src
COPY ConsoleApp/ConsoleApp.csproj ConsoleApp/
RUN dotnet restore ConsoleApp/ConsoleApp.csproj
COPY . .
WORKDIR /src/ConsoleApp
RUN dotnet build ConsoleApp.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish ConsoleApp.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "ConsoleApp.dll"]
A general troubleshooting thing to check is the exit code of the process. This will often give a clue what the problem is.
In this case, the exit code was STATUS_DLL_NOT_FOUND. This alone may be enough of a clue if you understand your app's dependencies, because you can just manually examine the container and figure out what is missing.
If you don't know what is missing, a direct way to debug is by using the Windows Debuggers and turning on "Show Loader Snaps". Info about getting Windows Debuggers here. You can xcopy them into the container. You would use a command line like C:\Debuggers\cdb.exe -xe "ld ntdll" test.exe, which launches test.exe under the debugger, stopping as soon as ntdll.dll is loaded (which is earlier than normal). Once it stops, you run !gflag +sls to turn on loader snaps, then run g to continue execution. Examining the spew should tell you what is missing or failing to load.
In this particular case, STATUS_DLL_NOT_FOUND is likely because test.exe is a .NET Framework app, but the full .NET Framework is not present in the nanoserver image.

Connect to MySQL container from Web Api .Net Core Container? How to get Ip Address?

I know this is such a noob problem but I am having trouble understanding how to get my .Net Core website to connect to my MySql container. So some background, both the MySql and the .Net core website are in their separate containers. I have already started the MySql container and setup the root account to work. I am using Entity Framework inside of .Net Core project.
I created the MySql container using this statement:
docker run --name mysql_container -d -p 3306:3306
Below is the dockerfile that Visual Studio generated for me.
So what do I tell my .Net Core program to is the IP address of the MySql container if the IP can change?
Inside of .Net Core Program:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
var connection = $"Server={GetDBAddress()};Database=myDataBase;Uid=root;Pwd=root;";
services.AddDbContext<ToDoContext>(options => options.UseMySQL(connection));
}
If I write the GetDBAddress function what goes in there? I cannot simply return localhost because it's another docker container? As of right now I am trying to use localhost and I get connection refused. But I am able to connect to the MySql db using workbench.
Also I am not sure but can these two setups be combined into some file I think they're called docker-compose files maybe?
Dockerfile
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"]
If you've launched MySQL exposing the ports you should be able to reach it connecting from localhost, with the port 3306.
Otherwise, as you suggested, there is the possibility to set up a docker-compose file. This file usually contains all the configuration your application needs to run. So, for example, a suitable configuration for your application (note: I'm assuming you're using MySQL 5.7 since you haven't specified one) could be:
version: '3.3'
services: # list of services composing your application
db: # the service hosting your MySQL instance
image: mysql:5.7 # the image and tag docker will pull from docker hub
volumes: # this section allows you to configure persistence within multiple restarts
- db_data:/var/lib/mysql
restart: always # if the db crash somehow, restart it
environment: # env variables, you usually set this to override existing ones
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: todoservice
MYSQL_USER: root
MYSQL_PASSWORD: root
todoservice: # you application service
build: ./ # this tells docker-compose to not pull from docker hub, but to build from the Dockerfile it will find in ./
restart: always
depends_on: # set a dependency between your service and the database: this means that your application will not run if the db service is not running, but it doesn't assure you that the dabase will be ready to accept incoming connection (so your application could crash untill the db initializes itself)
- db
volumes:
db_data: # this tells docker-compose to save your data in a generic docker volume. You can see existing volumes typing 'docker volume ls'
To launch and deploy your application, now you need to type in a terminal:
docker-compose up
This will bring up your deploy. Note that no ports are exposed here: only your service will be able to access the database from db:3306 (you don't need to refer by IP, but you can reach other services using the service name).
For debug purposes, you can still open your db ports adding this line under image:
ports:
- "3306:3306"
Note that this port has to be free (no other system services are using it), otherwise the entire deployment will fail.
Final note: since docker-compose will try to avoid to build your images every time you bring up the service, to force it to build a new one you have to append --build to the docker-compose up command.
To bring down your deploy just use docker-compose down. To delete all the persistent data related to your deploy (i.e. starting with a new db) append the -v flag at the end of the previous command.
Hope it helps!

Cannot run asp.net 5 from docker

I have followed the following guide: Running ASP.NET 5 applications in Linux Containers with Docker and I cannot get this to work on my Windows PC or Linux server. My dockerfile looks like this:
FROM microsoft/aspnet
COPY . /app
WORKDIR /app
RUN ["dnu", "restore"]
EXPOSE 5000/tcp
ENTRYPOINT ["dnx", "-p", "project.json", "web"]
I then ran docker build -t myapp . and then docker run -d -p 80:5000 myapp it says it is running but I cannot open the website in the browser. I know on Windows you are supposed to find the ip address that the actual virtual machine is running against by using docker-machine ip default which ended up being 192.168.99.100 but when I navigated to http://192.168.99.100 I just get the generic "This webpage is not available" error message. I have also tried different variations of this docker run command, such as docker run -it -p 80:5000 myapp, docker run -p 80:5000 myapp, and I have also tried different ports, such as docker run -d -p 5000:5000 myapp but nothing seems to work.
I have tried this both on my windows machine and on my linux server, but they both do not work.
I am able to run dnx web without docker and everything works as expected.
Take a look at my answer here: ASP.NET 5.0 beta 8 in Docker doesn't start
Essentially, Docker is forwarding requests to your container on the 0.0.0.0 network interface, but Kestrel is only listening on localhost by default.
So yes, the requests are being passed off to your docker container, but they are not being accepted by the Kestrel webserver. For that reason, you need to override the server.urls property as others have posted:
ENTRYPOINT ["dnx", "web", "--server.urls", "http://0.0.0.0:5000"]
You should then see:
Now listening on: http://0.0.0.0:5000
when running your container. You can also do a quick docker ps command to verify that 0.0.0.0 is in fact the network interface that Docker is forwarding requests for.
I also wrote a bit about how to get ASP.NET 5 running on Docker on Windows - it's a bit more involved since not only does Docker have to forward requests to the container, but we have to get VirtualBox to pass off requests to the Docker virtual machine boot2docker (typically called default in Virtual Box) before Docker can hand them off to our container.
Post is here: http://dotnetliberty.com/index.php/2015/10/25/asp-net-5-running-in-docker-on-windows/
For a more complete understanding of your app environment, please post your project.json file and the beta version of ASP.net you are working with.
For now you can try cleaning up your Dockerfile by taking out "project.json" and "-p" arguments from the ENTRYPOINT instruction, remove tcp from the EXPOSE command, and finally, specify the "--server.urls" argument in the ENTRYPOINT instruction so that it uses 0.0.0.0 instead of the default localhost as follows:
FROM microsoft/aspnet
COPY . /project
WORKDIR /project
RUN ["dnu", "restore"]
EXPOSE 5000
ENTRYPOINT ["dnx", "web", "--server.urls"]
Alternatively, you can try dropping the EXPOSE command altogether and expose the docker port, 5000, in the ENTRYPOINT instruction as follows:
FROM microsoft/aspnet
COPY . /project
WORKDIR /project
RUN ["dnu", "restore"]
ENTRYPOINT ["dnx", "web", "--server.urls", "http://0.0.0.0:500"]
Either way you would then build your container and run it using something like the following:
$ docker run -it -p 80:5000 myapp
For anyone having this issue now in RC2, commands no longer exists. You have to update Program.cs by chaining in .UseUrls("http://0.0.0.0:5000"). You can also change from 5000 to whatever your desired port is here.
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.UseUrls("http://0.0.0.0:5000")
.Build();
host.Run();
}
}
You can find a working, step-by-step tutorial for Docker and ASP.NET Core RC1 here:
https://www.sesispla.net/blog/language/en/2015/12/recipe-asp-net-5-net-core-to-the-docker-container/
The tricky part probably you are missing is to modify your projects.json command as follows:
"commands": {
"web": "Microsoft.AspNet.Server.Kestrel --server.urls http://0.0.0.0:5000"
},
By default, kestrel only accepts localhost connections... With this change you allow connection from any source.

Categories

Resources