=====Overview=====
After we learned a little bit a docker and containers, let's use docker for what it was meant to :)
I have created a simple HTTP server which listens on port: 1234
Source code you can see in my [[https://github.com/JulienAndonov/C--Web/blob/master/Web%20Server%20-%20HTTP%20Protocol/HttpServerDemo/Program.cs|Git]]
Packaging application in image, we call dockerize and it is done pretty simle.
=====Steps=====
Firstly, you need a Dockerfile in the place of your project.
Since my project is on C#.NET Core and assuming your application is called: HttpServerDemo.dll, I have used the following Dockerfile:
==Dockerfile==
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "HttpServerDemo.dll"]
Now, let's go through the steps:
* Workdir - The workdir on the container which will be used.
* FROM - The external resources which will be used.
* COPY & RUN - These are self explanatory I hope.
You have to verify you have docker at least 17.05 or newer.
My current one is 19.03:
[root@postgresqlpgpool netcoreapp3.1]# docker --version
Docker version 19.03.5, build 633a0ea
====Build====
The building is also done fairy simple.
[root@postgresqlpgpool HttpServerDemo]# docker build -t httpserverdemo .
Sending build context to Docker daemon 398.3kB
Step 1/10 : FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
---> 2fe8fe202baf
Step 2/10 : WORKDIR /app
---> Using cache
---> 931056fe84ac
Step 3/10 : COPY *.csproj ./
---> Using cache
---> 33c701ccd6cf
Step 4/10 : RUN dotnet restore
---> Using cache
---> 2acbc600037a
Step 5/10 : COPY . ./
---> 68177b9bdcf6
Step 6/10 : RUN dotnet publish -c Release -o out
---> Running in 34db589b7d0b
Microsoft (R) Build Engine version 16.4.0+e901037fe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restore completed in 127.94 ms for /app/HttpServerDemo.csproj.
HttpServerDemo -> /app/bin/Release/netcoreapp3.1/HttpServerDemo.dll
HttpServerDemo -> /app/out/
Removing intermediate container 34db589b7d0b
---> d81f005279bc
Step 7/10 : FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
---> 5b704ff3cb6b
Step 8/10 : WORKDIR /app
---> Using cache
---> e35d6ba6b507
Step 9/10 : COPY --from=build-env /app/out .
---> dc3b27c05e4d
Step 10/10 : ENTRYPOINT ["dotnet", "HttpServerDemo.dll"]
---> Running in ff14d57a08fc
Removing intermediate container ff14d57a08fc
---> 46b4167e5b2d
Successfully built 46b4167e5b2d
Successfully tagged httpserverdemo:latest
[root@postgresqlpgpool HttpServerDemo]#
You can list the images as follows:
[root@postgresqlpgpool netcoreapp3.1]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
httpserverdemo latest 4ab730ac8ab5 6 hours ago 207MB
====Start====
Once the image has been built, you can start the container using that image:
[root@postgresqlpgpool HttpServerDemo]# docker run -d httpserverdemo 80:1234
c23e4bb41a9f660f8b409addb58d398b98dce38e93da00682214141f5bc719c9
[root@postgresqlpgpool HttpServerDemo]#
Finally, you can check the container:
[root@postgresqlpgpool netcoreapp3.1]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9afb2dcbd6c2 httpserverdemo "dotnet HttpServerDe…" 5 hours ago Up 5 hours 0.0.0.0:80->1234/tcp web
[root@postgresqlpgpool netcoreapp3.1]#
====Upload in docker hub====
Docker hub is the default registry for docker images. You can upload your image there if you want, bare in mind that it will be public.
==Login==
[root@postgresqlpgpool netcoreapp3.1]# docker login --username=andonovj
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@postgresqlpgpool netcoreapp3.1]#
==Package==
[root@postgresqlpgpool netcoreapp3.1]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
httpserverdemo latest 4ab730ac8ab5 3 hours ago 207MB
[root@postgresqlpgpool netcoreapp3.1]# docker tag 4ab730ac8ab5 andonovj/httpserverdemo
==Push==
[root@postgresqlpgpool netcoreapp3.1]# docker push andonovj/httpserverdemo
The push refers to repository [docker.io/andonovj/httpserverdemo]
6f2df37fa757: Pushed
64bca5e22c97: Pushed
05682a6a4056: Pushed
fcd021389694: Pushed
2c52aed6692d: Pushed
c51868eee26f: Pushed
556c5fb0d91b: Pushed
latest: digest: sha256:5e0866ff45e12c8e350923fbe32d94bd76bd2d1576722d4d55ca786043bfcbe1 size: 1791
[root@postgresqlpgpool netcoreapp3.1]#
Now you can also download this simple web from your docker hub or list it as follows:
[root@postgresqlpgpool ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
andonovj/httpserverdemo latest 4ab730ac8ab5 6 hours ago 207MB
[root@postgresqlpgpool ~]#
=====Troubleshooting=====
You can have the following error:
====Searching wrong Nuget====
Restore completed in 41.36 ms for /app/HttpServerDemo.csproj.
/usr/share/dotnet/sdk/3.1.201/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(234,5): error MSB4018: The "ResolvePackageAssets" task failed unexpectedly. [/app/HttpServerDemo.csproj]
/usr/share/dotnet/sdk/3.1.201/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(234,5): error MSB4018: NuGet.Packaging.Core.PackagingException: Unable to find fallback package folder 'C:\Program Files\dotnet\sdk\NuGetFallbackFolder'. [/app/HttpServerDemo.csproj]
/usr/share/dotnet/sdk/3.1.201/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(234,5): error MSB4018: at NuGet.Packaging.FallbackPackagePathResolver..ctor(String userPackageFolder, IEnumerable`1 fallbackPackageFolders) [/app/HttpServerDemo.csproj]
/usr/share/dotnet/sdk/3.1.201/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(234,5): error MSB4018: at Microsoft.NET.Build.Tasks.NuGetPackageResolver.CreateResolver(IEnumerable`1 packageFolders) [/app/HttpServerDemo.csproj]
/usr/share/dotnet/sdk/3.1.201/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(234,5): error MSB4018: at Microsoft.NET.Build.Tasks.NuGetPackageResolver.CreateResolver(LockFile lockFile) [/app/HttpServerDemo.csproj]
/usr/share/dotnet/sdk/3.1.201/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(234,5): error MSB4018: at Microsoft.NET.Build.Tasks.ResolvePackageAssets.CacheWriter..ctor(ResolvePackageAssets task) [/app/HttpServerDemo.csproj]
/usr/share/dotnet/sdk/3.1.201/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(234,5): error MSB4018: at Microsoft.NET.Build.Tasks.ResolvePackageAssets.CacheReader.CreateReaderFromDisk(ResolvePackageAssets task, Byte[] settingsHash) [/app/HttpServerDemo.csproj]
/usr/share/dotnet/sdk/3.1.201/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(234,5): error MSB4018: at Microsoft.NET.Build.Tasks.ResolvePackageAssets.CacheReader..ctor(ResolvePackageAssets task) [/app/HttpServerDemo.csproj]
/usr/share/dotnet/sdk/3.1.201/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(234,5): error MSB4018: at Microsoft.NET.Build.Tasks.ResolvePackageAssets.ReadItemGroups() [/app/HttpServerDemo.csproj]
/usr/share/dotnet/sdk/3.1.201/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(234,5): error MSB4018: at Microsoft.NET.Build.Tasks.ResolvePackageAssets.ExecuteCore() [/app/HttpServerDemo.csproj]
/usr/share/dotnet/sdk/3.1.201/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(234,5): error MSB4018: at Microsoft.NET.Build.Tasks.TaskBase.Execute() [/app/HttpServerDemo.csproj]
/usr/share/dotnet/sdk/3.1.201/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(234,5): error MSB4018: at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute() [/app/HttpServerDemo.csproj]
/usr/share/dotnet/sdk/3.1.201/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(234,5): error MSB4018: at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(ITaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask) [/app/HttpServerDemo.csproj]
The command '/bin/sh -c dotnet publish -c Release -o out' returned a non-zero code: 1
In that case, either:
* Delete the "obj" and "bin" folders from the directory
* Add a command to the "Dockerfile" to not upload these to the container as follows:
# copy and build everything else
COPY . ./
RUN find -type d -name bin -prune -exec rm -rf {} \; && find -type d -name obj -prune -exec rm -rf {} \; <- This line
ENTRYPOINT ["dotnet", "HttpServerDemo.dll"]
====Wrong ASP.NET====
Be careful about the dockerizing the application. I tried to build the application with ASP.NET 2.2 while the app was build with ASP.NET 3.1, so I had to update my Dockerfile as follows:
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env <- This line
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out
# Build runtime image
#FROM mcr.microsoft.com/dotnet/core/aspnet:2.2
FROM mcr.microsoft.com/dotnet/core/sdk:3.1
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "HttpServerDemo.dll"]
Otherwise, you will receive the following error:
It was not possible to find any compatible framework version
The specified framework 'Microsoft.NETCore.App', version '3.1.0' was not found.
- Check application dependencies and target a framework version installed at:
/usr/share/dotnet/
- Installing .NET Core prerequisites might help resolve this problem:
https://go.microsoft.com/fwlink/?LinkID=798306&clcid=0x409
- The .NET Core framework and SDK can be installed from:
https://aka.ms/dotnet-download
- The following versions are installed:
2.2.8 at [/usr/share/dotnet/shared/Microsoft.NETCore.App]