Host ASP.NET Core in Linux with Apache Docker

Viewed 1355

I am referencing this article on Microsoft's documentation:

https://docs.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!

1 Answers

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