Original link: Https://dzone.com/articles/the-evolution-of-a-linux-container
Right now. NET developers can use Linux containers such as Docker without hindrance, let's try to configure a container in the right way.
It might be better to change the title of the article to "The evolution of Linux container developers". Because. NET can run on Linux (as well as Windows and MacOS), so the entire world of Linux containers and microservices is open to. NET developers.
The. NET, which has a large number of developers, long-running records and excellent performance indicators, now offers Windows-centric developers an opportunity to use Linux containers.
While it is tempting to try to run. NET code in a Linux container, there are subtle differences, but it is not wrong to do so. You can easily put some. NET code is pushed into the mirror.
After all, everything happened so fast, it must be good. Right?
That is not the case. It's not easy to run. NET code in a Linux container, but remember: "Let it work first, and then let it work quickly." ”
In the following example, the "quick" above refers to the time required to build the image, the time it takes to start the mirror, and the performance of the mirrored internal code. This article will first discuss the mirroring build time and start time, followed by a simple. NET program runs on container-based applications and then observes changes in the size of the mirror, ultimately shortening the build and load times of the image. In addition, code optimization is another topic in this article.
A short stay
Consider a very simple microservices example that gives only a "Hello world" type of HTTP response. That is, when you fill in the URL in the browser, you get a Web page that includes the hostname.
We can download the source code from this library (HTTPS://GITHUB.COM/DONSCHENCK/DOTNET_DOCKER_MSA), And make the first Dockerfile (DOCKERFILE.ATTEMPT1), and then use the following command to build the image:
# docker build -t attempt1 -f Dockerfile.attempt1 .
Then run the mirror in the container:
# docker run -d -p 5000:5000 --name attempt1 attempt1
Point the URL of the browser to the IP address of the host, as follows:
Digital
It took 95 seconds to build the image for the first time. Among them, download Red Hat Enterprise Linux (RHEL) image and install the. NET SDK, these files are altogether 490MB. Finally, the mirror size is 659MB.
In general, subsequent builds of the mirror will be faster because the Docker image is already available on the host. After changing the source code, we run the build again. This time the image is built, which takes about 50 seconds to get a mirror of the same size, which is 659MB.
The size of the image is important. Because mirroring uses the operating system's storage space, although space is cheap, it is still a limited commodity. When using containers on a regular basis, it is easy to ignore outdated images, but it still occupies the disk. If you are not careful, disk space will be exhausted soon.
How to make the image as small as possible?
Remove unwanted parts of the image
Use the command dotnet restore --no-cache
to eliminate any caches, so that the size of the mirror drops to 608.6MB, reducing 50.6 MB and shrinking by more than 7%.
Build your app before you build the image
The app is built when the mirror is running in the container. NET program. It takes about 1.6 seconds--although not long, it's a waste of time.
The dotnet build command is inserted before the restore, and the application is built before the image is built, so that the container will start faster. This result can be achieved in DOCKERFILE.ATTEMPT3.
At the same time, the image size is increased to 610.2MB, and we have to run the dotnet build, although it now takes the time to benefit from each boot of the container.
Run the dotnet Publish command
Because the container is a runtime environment, why don't we use the dotnet Publish command to publish the code and then put the code in the mirror? If we do this, we don't need to install it in the mirror. NET program. After all, what we need is an application that can run independently anywhere.
Publishing code with dotnet reduces the size of the mirror and shortens the container startup time. Change the Project.json file and comment out the contents of the red box, which tells the compiler that this file is built for a platform. You can see it in:
Next, we use dotnet publish-c release-r rheh.7.2-x64 to publish the code, which will put all the compiled files and run-time files into a folder, we copy this folder into the mirror.
Because we no longer need to install. NET program, as long as a base image containing Rhel files can be, which reduces the size of the image. This is the fourth iteration of the Dockerfile--DOCKERFILE.ATTEMPT4:
From registry.Access.Redhat.Com/rhel7run Yum Install- yLibunwindrun Yum Install- yLibicuadd Bin/release/netcoreapp1. 0/rhel. 7. 2-x64/publish/./opt/app-root/src/Workdir/opt/app-root/src/EXPOSE theCmd["/bin/bash","-C","/opt/app-root/src/dotnet_docker_msa"]
Please note that the Yum install command installs some. NET requires a dependent file, and then runs the Docker build command, resulting in a 694.6MB mirror.
Who needs the cache?
Run the Yum install command multiple times, and the previous operation will build the cache for the next time. If we clear the cache immediately after each yum install command, the effect will be good. The following is the fifth iteration of Dockerfile ——— dockerfile.attempt5:
From registry.Access.Redhat.Com/rhel7run Yum Install- yLibunwind&&Yum Clean AllRUN Yum Install- yLibicu&&Yum Clean AllADD Bin/release/netcoreapp1. 0/rhel. 7. 2-x64/publish/./opt/app-root/src/Workdir/opt/app-root/src/EXPOSE theCmd["/bin/bash","-C","/opt/app-root/src/dotnet_docker_msa"]
The image built on Dockerfile.attempt5 is reduced to 293.7MB in size, which is 55% smaller than the first build.
Stacking commands
To make a final change to dockerfile, we need to stack the Yum Install command, as follows:
From registry.Access.Redhat.Com/rhel7run Yum Install- yLibunwind Libicu&&Yum Clean AllADD Bin/release/netcoreapp1. 0/rhel. 7. 2-x64/publish/./opt/app-root/src/Workdir/opt/app-root/src/EXPOSE theCmd["/bin/bash","-C","/opt/app-root/src/dotnet_docker_msa"]
The resulting image size is 257.5MB, which is 60% smaller than the first build.
Here is a comparison of the image sizes built by each dockerfile:
Summarize
When exploring new technologies and new models, we cannot confuse early results with best practices. While early success can give us excitement and encouragement, it can also lead us to lose momentum for progress. Diligence, and then constantly trying, and always accepting suggestions for improvement, will help us go farther.
. NET program's evolution in Linux containers