Host ASP.NET Core in Linux with Apache Docker - c#

I am referencing this article on Microsoft's documentation:
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-apache?view=aspnetcore-3.1
Has anyone tried to accomplish these steps in Docker container?
I have been at this for a couple of days and I can't get the kestrel-helloapp.service file to start my application automatically when I run the container.
After running the container I am able to manually go into it and start my application with dotnet WebApplication3.dll.
I am under the impression that this should happen automatically after enabling the service file.
The only way I am able to get it to work is by adding this to the Dockerfile:
ENTRYPOINT ["dotnet" ,"WebApplication3.dll"]
But when I do this it causes the Apache server to not start up automatically.
Here is my Dockerfile:
FROM centos:7
# install sudo and dotnet sdk
RUN yum install sudo -y
RUN sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm
RUN yum install epel-release -y
RUN yum install dnf -y
RUN sudo dnf install dotnet-sdk-3.1 -y
# copy app files over
COPY ["./publish/", "/var/www/helloapp/publish/"]
# install apache and enable it
RUN sudo yum -y install httpd mod_ssl
RUN systemctl enable httpd.service
RUN yum install initscripts -y
RUN sudo service httpd configtest
# copy and enable service file
COPY ["./kestrel-helloapp.service", "/etc/systemd/system/"]
RUN sudo systemctl enable kestrel-helloapp.service
# start apache
CMD ["-D", "FOREGROUND"]
ENTRYPOINT ["/usr/sbin/httpd"]
EXPOSE 80
docker run command:
docker run -v "C:\Users\Nick\source\repos\docker-testing\version1\helloapp.conf:/etc/httpd/conf.d/helloapp.conf" -e "ASPNETCORE_URLS=http://+:8080" -p 80:80 -p 8080:8080 -t version1
helloapp.conf file:
<VirtualHost *:*>
RequestHeader set "X-Forwarded-Proto" expr="http"
</VirtualHost>
<VirtualHost *:8080>
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
ServerName www.example.com
ServerAlias *.example.com
ErrorLog /var/log/httpd/helloapp-error.log
CustomLog /var/log/httpd/helloapp-access.log common
</VirtualHost>
kesterl-helloapp.service file:
[Unit]
Description=Example .NET Web MVC App running on CentOS 7
[Service]
WorkingDirectory=/var/www/helloapp/publish
ExecStart=/usr/local/bin/dotnet /var/www/helloapp/publish/WebApplication3.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=apache
Environment=ASPNETCORE_ENVIRONMENT=Production
[Install]
WantedBy=multi-user.target
I know the configuration is correct because everything works fine when I start the application manually. The service file just seems to be not starting the application on boot.
Any help would be greatly appreciated. Thanks!

I've run into a similar problem (just with an ubuntu base image). The problem that you are likely experiencing is related to the fact that there is one process launched from the docker container on entry point and that is not the system daemon (init, systemd, not sure which one centos is using). As a result, your services are actually not started as you described, because they would be launched on system run level change, by that exact same system daemon.
In my opinion, not launching the system daemon is a good thing as you want to minimize services running inside of your container.
On the other hand, you might actually want multiple services inside of the container. An actual solution to your problem is to write an entry point shell script and launch the services that you want to run in parallel of your main application. In my case, I wanted a customized Jenkins image, which has an entry point of /usr/local/bin/jenkins.sh. You can find this in the Dockerfile of the base image that you are using.
I've replaced the original entry point:
ENTRYPOINT ["/bin/tini", "--", "/usr/local/bin/jenkins.sh"]
with:
ENTRYPOINT ["/bin/tini", "--", "/docker-entrypoint.sh"]
Where the content of /docker-entrypoint.sh is:
#! /bin/bash
/usr/bin/cron & # This is the additional service I wanted in the background
/usr/local/bin/jenkins.sh

Related

.net core assembly can not concurrently run on linux

I wrote an dotnet core app for running on linux.
published a single executable file with self-contained enabled.
dotnet publish -c Release -r linux-x64 -o ${dst_path} -v n /p:PublishTrimmed=true /p:PublishSingleFile=true
But strangely it can only run a single instance.
Because when it's running, it will remove the execute permission of the file.
$ ./Test
10/21/2020 11:50:27 AM [Info] Server started at ws://0.0.0.0:12500 (actual port 12500)
$ ls -l Test <---------Test is running, ls -l is executed in another terminal
-rw-rw-rw- 1 root root 53081298 10月 21 11:50 Test
And execute permission is added back after the runnning process exited.
$ ls -l Test <------------Test is not running.
-rwxrwxrwx 1 root root 53081298 10月 21 11:50 Test
So I can not start more than one process.
I am really confused with this problem.
Could anyone help?
Sorry for bothering, I found the root reason.
Just in case other may encount the same stupid situation, leave a message here.
My problem is caused by virutalBox.
Because I put my published assembly Test in the shared directory of my host between shared virtual machine.
After move my file Test to virtual machine's home directory, it works well.
And thank you for your help #jdoer1997

How to create and use docker volumes on Asp core Web app (MVC)

I have web app and I'm using docker to deploy it to Linux server. I'm using ASP .NET CORE 2.1, MVC model for my app, and I publish it through Visual studio's integrated Container Registry to docker hub. from my server i pull image, and then run it. Problem is, every time I publish update to my app it resets all files in app, as it should, that's how containers work. But I need some files to stay in server and not to reset every time i update my app, so i need to use volumes. But I can't figure out how to use ASP CORE app and docker volumes, I think i can create them, but how to access them from app ?
I'v tried some methods I found on web,
So normaly I to run docker I pull it from hub.docker with: docker pull mydockerid/appname:tag
Then, run it with command: docker run -p 3000:80 mydockerid/appname:tag
and that's it.
I'v tried : docker run -p 3000:80 -v ~mnt/files/xml:/xml mydockerid/appname:tag
As I understood it it should make docker use server folder, "mnt/files/xml" as folder in my app named "xml", but doesn't work.
I'm also Using Digital ocean and directory "mnt/files/xml" is volume connected to droplet.
Perfect solution would be so I could create docker volume inside droplets volume, but really any solution that works would be great !
Thanks, for Help !
Okay so I was close,
to create volume in docker you need to chose directory from server and folder from app.
the problem for me was, I was showing wrong directory in app. Because in docker container lets say root folder is under /app/root, so was my xml folder, all I needed to fix is to use docker run -p 3000:80 -v ~mnt/files/xml:/app/xml mydockerid/appname:tag instead of docker run -p 3000:80 -v ~mnt/files/xml:/xml mydockerid/appname:tag first directory is always from server and second is always from app.
As for volumes in digital Ocean:
Go to Volumes under manage on left.
Press Create Volume button on top right.
Choose configuration of Volume, then attach it to your droplet.
to mount it:
$ mkdir -p /mnt/files
# Mount your volume at the newly-created mount point:
$ mount -o discard,defaults,noatime /dev/disk/by-id/scsi-0DO_volume_name /mnt/files
# Change fstab so the volume will be mounted after a reboot
$ echo '/dev/disk/by-id/scsi-0DO_volume_name /mnt/files ext4 defaults,nofail,discard 0 0' | sudo tee -a /etc/fstab
Digital Ocean will actualy show all these comands with your volume names if you go into "Config instruction" under "More" on your Volume.
Then becouse my DO volume is mounted to /mnt/files I connect to server via filezila, put needed files there in folder called "xml" and run the docker container with docker run -p 3000:80 -v ~mnt/files/xml:/xml mydockerid/appname:tag, Now whatever is in folder xml in server. will be read at it is inside my app inside, folder called xml, and I can update app and the folder will never loose data. Also I can move this DO volume to another DO droplet without data loss.

Can't build ASP.Net container

Windows 10 version 1607
Docker for Windows: Version 17.06.1-ce-win24 (13025)
I'm trying to build a asp .net 4.6 container using the provided docs and its not working.
I'm using this provided dockerfile. I copied it to the root of one of my asp .net solutions.
And the I ran this command:
$ docker build -t aspnet-site --build-arg site_root=/
This is the output
PS> docker build -t aspnet-site . --build-arg 'site_root=/'
Sending build context to Docker daemon 326.1MB
Step 1/6 : FROM microsoft/dotnet-framework:4.6.2
4.6.2: Pulling from microsoft/dotnet-framework
3889bb8d808b: Pull complete
9f5eeabe6154: Pull complete
Digest: sha256:c281f2c09c9446f1896806933013a350f19db8f5a009e633ebd9701c470de35b
Status: Downloaded newer image for microsoft/dotnet-framework:4.6.2
---> be84290c2315
Step 2/6 : SHELL powershell -Command $ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';
---> Running in 1fd036b1b56e
---> 413164f1a97c
Removing intermediate container 1fd036b1b56e
Step 3/6 : RUN Add-WindowsFeature Web-Server; Add-WindowsFeature NET-Framework-45-ASPNET; Add-WindowsFeature Web-Asp-Net45; Remove-Item -Recurse C:\inetpub\wwwroot\*
---> Running in 4b0e5751281b
Success Restart Needed Exit Code Feature Result
------- -------------- --------- --------------
True No Success {Common HTTP Features, Default Documen...
True No Success {ASP.NET 4.6}
True No Success {Application Development, ASP.NET 4.6,...
---> 9afab6bfa836
Removing intermediate container 4b0e5751281b
Step 4/6 : ADD ServiceMonitor.exe /
ADD failed: GetFileAttributesEx \\?\C:\WINDOWS\TEMP\docker-builder455754487\ServiceMonitor.exe: The system cannot find the file specified.
So it does say this in the docs (so I tried commenting out the servicemonitor stuff and it worked):
There is no need to specify an ENTRYPOINT in your Dockerfile since the
microsoft/aspnet base image already includes an entrypoint application
that monitors the status of the IIS World Wide Web Publishing Service
(W3SVC).
Try with this dockerfile instead. It will use the aspnet image:
FROM microsoft/aspnet
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]
EXPOSE 80
RUN Remove-WebSite -Name 'Default Web Site'
RUN New-Website -Name 'YourSiteName' -Port 80 -PhysicalPath 'C:\YourFolderName' -ApplicationPool '.NET v4.5'
ADD "LocalFolderPath" /YourFolderName

Install .NET Framework 3.5 on Windows Server Core Docker

I am struggling to install .NET Framework 3.5 on docker container. I have 4.5 installed already, but need 3.5 to run one Service. Here is my Dockerfile:
FROM microsoft/windowsservercore
SHELL ["powershell"]
RUN Install-WindowsFeature NET-Framework-45-ASPNET ; \
Install-WindowsFeature Web-Asp-Net45
RUN dism /online /enable-feature /featurename:NetFX3 /all
COPY Startup Startup
COPY Service Service
RUN "C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe" WCS.WindowsService.exe
RUN mkdir Temp\Logs
ENTRYPOINT C:\Startup\setupBatch.bat
COPY ContainerApi ContainerApi
RUN Remove-WebSite -Name 'Default Web Site'
RUN New-Website -Name 'ContainerApi' -Port 80 \
-PhysicalPath 'C:\ContainerApi' -ApplicationPool '.NET v4.5'
EXPOSE 80
CMD ["ping", "-t", "localhost"]
When I try to build this, it gives me error on line RUN dism
Error: 0x800f081f
The source files could not be found.
Use the "Source" option to specify the location of the files that are required to restore the feature. For more information on specifying a source location, see http://go.microsoft.com/fwlink/?LinkId=243077.
Now, even if I run dism /online /enable-feature /featurename:NetFX3 /all inside the docker (docker exec) it will still give me the same error.
Anyone with any help?
I took the following steps to resolve this issue:
Got hold of the Windows Server 2016 Core ISO file. Mounted the file on local computer.
Extracted the {mount}:/sources/sxs folder into a zip file (sxs.zip). Ensure that the .NET Framework 3.5 cab file (microsoft-windows-netfx3-ondemand-package.cab) is present in the sxs folder. In my case, this was the only file present in the sxs folder.
Copy the sxs.zip file to my container. I copied it using the dockerfile of the image.
Unzip the file to C:\sources\sxs folder in the container.
Used the Install-WindowsFeature powershell command to install the feature.
Install-WindowsFeature -Name NET-Framework-Features -Source C:\sources\sxs -Verbose
Hope this helps. I also found the following blog useful in understanding the on-demand features.
https://blogs.technet.microsoft.com/askcore/2012/05/14/windows-8-and-net-framework-3-5/
For those who are still are in need of .Net3.5 and .Net4.X (4.7.2 for my case) version in one image.
Please note that MSFT is aware of this demand, and have a base image for this scenario.
Use FROM mcr.microsoft.com/dotnet/framework/sdk:3.5-20191008-windowsservercore-ltsc2019 in your dockerfile.
Saved me all the installation hassles.

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