{"id":1857,"date":"2018-04-25T07:06:38","date_gmt":"2018-04-25T05:06:38","guid":{"rendered":"https:\/\/code-maze.com\/?p=1857"},"modified":"2020-09-02T21:51:18","modified_gmt":"2020-09-02T19:51:18","slug":"how-to-prepare-aspnetcore-app-dockerization","status":"publish","type":"post","link":"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/","title":{"rendered":"How to Prepare an ASP.NET Core Application for Dockerization"},"content":{"rendered":"<p>In this part, we are going to apply some modifications to our ASP.NET Core application in order to prepare it for the dockerization process.<\/p>\n<p>To follow along with this part you need:<\/p>\n<ul>\n<li>.NET Core 3.1 SDK<\/li>\n<li>Windows 10<\/li>\n<li>Git<\/li>\n<li>IDE of your choice (we use Visual Studio 2019)<\/li>\n<li>Docker Desktop (at least 2.1.0.5)<\/li>\n<\/ul>\n<p>These are not necessary but to achieve the best results we recommend this setup.<\/p>\n<ul id=\"series_parts\" style=\"display: none;\">\n<li>How to Prepare an ASP.NET Core Project for Dockerization (Current article)<\/li>\n<li><a href=\"https:\/\/code-maze.com\/why-docker-docker-cli-examples\/\" target=\"_blank\" rel=\"noopener noreferrer\">Why Docker: Docker CLI Through Examples<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/aspnetcore-app-dockerfiles\/\" target=\"_blank\" rel=\"noopener noreferrer\">Dockerizing ASP.NET Core Application with Dockerfiles<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/mysql-aspnetcore-docker-compose\/\" target=\"_blank\" rel=\"noopener noreferrer\">Adding MySQL to ASP.NET Core App With Docker Compose<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/docker-hub-vs-creating-docker-registry\/\" target=\"_blank\" rel=\"noopener noreferrer\">Docker Hub vs Creating a Local Docker Registry<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/preparing-ci-environment-docker\/\" target=\"_blank\" rel=\"noopener noreferrer\">Preparing a Continuous Integration Environment for Docker<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/ci-aspnetcoreapp-docker\/\" target=\"_blank\" rel=\"noopener noreferrer\">Continuous Integration with TeamCity and Docker<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/ci-jenkins-docker\/\" target=\"_blank\" rel=\"noopener noreferrer\">Continuous Integration with Jenkins and Docker<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/top-docker-monitoring-tools\/\" target=\"_blank\" rel=\"noopener noreferrer\">Top Docker Monitoring Tools<\/a><\/li>\n<\/ul>\n<div class=\"wrap-collabsible\">\r\n    <input id=\"collapsible\" class=\"toggle\" type=\"checkbox\">\r\n    <label for=\"collapsible\" class=\"lbl-toggle\" onclick=\"writeContent()\">This article is part of the series<\/label>\r\n    <div class=\"collapsible-content\">\r\n      <div class=\"content-inner\">\r\n        <p class=\"innerContent\" id=\"innerContent\"><\/p>\r\n        <script>\r\n           function writeContent(){\r\n               var links= document.getElementById(\"series_parts\").innerHTML;\r\n               document.getElementById(\"innerContent\").innerHTML = links;\r\n           }\r\n       <\/script>\r\n      <\/div>\r\n    <\/div>\r\n<\/div>\r\n\n<p>For the purposes of this article, we are going to re-use the application from our <a href=\"https:\/\/code-maze.com\/net-core-series\/\" target=\"_blank\" rel=\"noopener noreferrer\">.NET Core Series<\/a>, more concretely\u00a0<a href=\"https:\/\/code-maze.com\/net-core-web-development-part6\/\" target=\"_blank\" rel=\"noopener noreferrer\">part 6<\/a> of the series. The main reason for this decision is that if you are not familiar with the ASP.NET Core, you can go through the series and learn <strong>how to make ASP.NET Core WebApi application<\/strong> from scratch.<\/p>\n<p>Since we are going to make some changes to the code, if you want to follow along with the steps of this course, you can find the starting point on the <strong>master branch<\/strong>\u00a0<a href=\"https:\/\/github.com\/CodeMazeBlog\/docker-series.git\" target=\"_blank\" rel=\"noopener noreferrer\">docker-series<\/a><\/p>\n<p>If you want to skip the preparation phase and jump right into Docker goodness, you can switch to the\u00a0<strong><a href=\"https:\/\/github.com\/CodeMazeBlog\/docker-series\/tree\/docker-series-app-prepared\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">docker-series-app-prepared<\/a>\u00a0<\/strong>branch\u00a0of the <a href=\"https:\/\/github.com\/CodeMazeBlog\/docker-series.git\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">docker-series<\/a> repo and go quickly through this section. It might be beneficial\u00a0for you to follow along if you are not familiar with some of the changes we are going to implement.<\/p>\n<p>These are the changes we&#8217;re going to make to the original project:<\/p>\n<ul>\n<li><a href=\"#memdb\">Switching to an In-Memory Database<\/a><\/li>\n<li><a href=\"#account\">Introducing AccountController<\/a><\/li>\n<li><a href=\"#swagger\">Introducing Swagger<\/a><\/li>\n<li><a href=\"#launch\">Modifying the launchSettings.json\u00a0File<\/a><\/li>\n<li><a href=\"#test\">Adding the Test Project and a Unit Test<\/a><\/li>\n<\/ul>\n<p>There is a lot to cover, so let&#8217;s get down to business.<\/p>\n<h2><a id=\"memdb\"><\/a>Switching to an In-Memory Database<\/h2>\n<p>First things first.<\/p>\n<p>To be able to dockerize our application and make it work without relying on external resources (database) we are going to make some changes to the configuration. We are going to re-introduce MySQL later in the series, but for now, we are going to rely on an in-memory database to store our data.<\/p>\n<p>So, let&#8217;s modify our <code>ServiceExtensions.cs<\/code> class:<br \/>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-highlight=\"3\" data-enlighter-title=\"\">public static void ConfigureMySqlContext(this IServiceCollection services, IConfiguration config)\r\n{\r\n\tservices.AddDbContext&lt;RepositoryContext&gt;(o =&gt; o.UseInMemoryDatabase(&quot;accountowner&quot;));\r\n}<\/pre><br \/>\nThe <code>UseInMemoryDatabase<\/code> method is part of the <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.EntityFrameworkCore.InMemory\/3.1.0\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Microsoft.EntityFrameworkCore.InMemory<\/a> NuGet package, so make sure to import it to the <code>AccountOwnerServer<\/code> project!<\/p>\n<p>That&#8217;s it!<\/p>\n<p>We successfully removed the reference to the MySQL database and added an in-memory database in a single line of code.<\/p>\n<p>Don&#8217;t worry about the hanging connection string in the <code>appsettings.json<\/code> file, we don&#8217;t need to remove it since we are going to use it in the next part.<\/p>\n<h2><a id=\"account\"><\/a>Introducing AccountController<\/h2>\n<p>To make our API functional on its own, we are going to modify and rename existing <code>WeatherForecastController<\/code>. So, first, we are going to rename it to <code>AccountController<\/code>, and then add some new code to it.<\/p>\n<p>We are going to add <code>GetAllAccounts<\/code> method and the <code>CreateAccount<\/code> method that will give us more options to play around with our API.<\/p>\n<pre  class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" title=\"AccountController.cs\">[ApiController]\r\n\t[Route(\"api\/[controller]\")]\r\n\tpublic class AccountController : Controller\r\n\t{\r\n\t\tprivate ILoggerManager _logger;\r\n\t\tprivate IRepositoryWrapper _repository;\r\n\t\tprivate IMapper _mapper;\r\n\r\n\t\tpublic AccountController(ILoggerManager logger, IRepositoryWrapper repository, IMapper mapper)\r\n\t\t{\r\n\t\t\t_logger = logger;\r\n\t\t\t_repository = repository;\r\n\t\t\t_mapper = mapper;\r\n\t\t}\r\n\r\n\t\t[HttpGet]\r\n\t\tpublic IActionResult GetAllAccounts()\r\n\t\t{\r\n\t\t\ttry\r\n\t\t\t{\r\n\t\t\t\tvar accounts = _repository.Account.GetAllAccounts();\r\n\r\n\t\t\t\t_logger.LogInfo($\"Returned all accounts from database.\");\r\n\r\n\t\t\t\tvar accountDtos = _mapper.Map&lt;IEnumerable&lt;AccountDto&gt;&gt;(accounts);\r\n\t\t\t\treturn Ok(accountDtos);\r\n\t\t\t}\r\n\t\t\tcatch (Exception ex)\r\n\t\t\t{\r\n\t\t\t\t_logger.LogError($\"Something went wrong inside GetAllAccounts action: {ex}\");\r\n\t\t\t\treturn StatusCode(500, \"Internal server error\");\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t[HttpPost]\r\n\t\tpublic IActionResult CreateAccount([FromBody]AccountForCreationDto account)\r\n\t\t{\r\n\t\t\ttry\r\n\t\t\t{\r\n\t\t\t\tif (account == null)\r\n\t\t\t\t{\r\n\t\t\t\t\t_logger.LogError(\"Object sent from client is null.\");\r\n\t\t\t\t\treturn BadRequest(\"Object is null\");\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (!ModelState.IsValid)\r\n\t\t\t\t{\r\n\t\t\t\t\t_logger.LogError(\"Invalid object sent from client.\");\r\n\t\t\t\t\treturn BadRequest(\"Invalid model object\");\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar accountEntity = _mapper.Map&lt;Account&gt;(account);\r\n\r\n\t\t\t\t_repository.Account.CreateAccount(accountEntity);\r\n\t\t\t\t_repository.Save();\r\n\r\n\t\t\t\tvar createdAccount = _mapper.Map&lt;AccountDto&gt;(accountEntity);\r\n\r\n\t\t\t\treturn CreatedAtRoute(\"AccountById\", new { id = createdAccount.Id }, createdAccount);\r\n\t\t\t}\r\n\t\t\tcatch (Exception ex)\r\n\t\t\t{\r\n\t\t\t\t_logger.LogError($\"Something went wrong inside CreateAccount action: {ex}\");\r\n\t\t\t\treturn StatusCode(500, \"Internal server error\");\r\n\t\t\t}\r\n\t\t}\r\n\t}<\/pre>\n<p>Of course, the compiler won&#8217;t let us build this since we need to implement\u00a0<code>GetAllAccounts<\/code> and <code>CreateAccount<\/code> methods in our <code>AccountRepository<\/code>.<\/p>\n<p>So let&#8217;s do exactly that.<\/p>\n<p>Add the method declarations to the <code>IAccountRepository<\/code>:<\/p>\n<pre  class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public interface IAccountRepository\r\n{\r\n\tIEnumerable&lt;Account&gt; GetAllAccounts();\r\n\tvoid CreateAccount(Account account);\r\n}<\/pre>\n<p>And the implementation of the <code>AccountRepository<\/code>:<\/p>\n<pre  class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public IEnumerable&lt;Account&gt; GetAllAccounts()\r\n{\r\n\treturn FindAll()\r\n\t\t.OrderBy(ac =&gt; ac.DateCreated);\r\n}\r\n\r\npublic void CreateAccount(Account account)\r\n{\r\n\taccount.Id = Guid.NewGuid();\r\n\tCreate(account);\r\n\tSave();\r\n}<\/pre>\n<p>Now run the <code>dotnet build<\/code> on the entire solution, and the project should compile.<\/p>\n<p>Great, now we have a working AccountController.<\/p>\n<h2><a id=\"swagger\"><\/a>Introducing Swagger<\/h2>\n<p>Swagger is one of the most popular and versatile frameworks for tooling your APIs.<\/p>\n<p>Here is how we are going to add it to our project.<\/p>\n<p>Navigate to the <code>\/AccountOwnerServer<\/code> folder. After that execute the command:<br \/>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"ps\" data-enlighter-title=\"\">dotnet add package Swashbuckle.AspNetCore --version 5.0.0-rc5<\/pre><br \/>\nThis will add the reference to the <a href=\"https:\/\/www.nuget.org\/packages\/Swashbuckle.AspNetCore\/5.0.0-rc5\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Swashbuckle NuGet package for ASP.NET Core<\/a> to our project (5.0.0-rc5 is the current version, for now, you can use the latest one). In short, Swashbuckle will help us integrate Swagger into our application.<\/p>\n<p>After that, we have to enable Swagger by changing our <code>Startup.cs<\/code> file a bit.<\/p>\n<p>To the <code>ConfigureServices<\/code> method, just before the <code>service.AddControllers()<\/code> line, we are going to add:<\/p>\n<pre  class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" title=\"Adding Swagger\">services.AddSwaggerGen(c =&gt;\r\n{\r\n\tc.SwaggerDoc(\"v1\", new OpenApiInfo\r\n\t{\r\n\t\tTitle = \"AccountOwner API\",\r\n\t\tVersion = \"v1\"\r\n\t});\r\n});\r\n\r\nservices.AddControllers();<\/pre>\n<p>And to the Configure method just after the\u00a0<code>app.UseEndpoints()<\/code> line:<\/p>\n<pre  class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">app.UseSwagger();\r\n\r\napp.UseSwaggerUI(c =&gt;\r\n{\r\n\tc.SwaggerEndpoint(\"\/swagger\/v1\/swagger.json\", \"AccountOwner API V1\");\r\n});<\/pre>\n<p>Great.<\/p>\n<p>But, what have we gained by doing all this?<\/p>\n<p>If you run the application now and go navigate to\u00a0<code>http:\/\/localhost:5000\/swagger\/v1\/swagger.json<\/code> to see the information about your API presented in JSON format.<\/p>\n<p>This information is the power behind the more interesting part of Swagger, the interactive documentation which you can get by navigating to <code>http:\/\/localhost:5000\/swagger<\/code>. If you did everything right you should see the documentation page like this one:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2019\/12\/Swagger-UI.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-49843\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2019\/12\/Swagger-UI.png\" alt=\"Swagger UI\" width=\"933\" height=\"888\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2019\/12\/Swagger-UI.png 933w, https:\/\/code-maze.com\/wp-content\/uploads\/2019\/12\/Swagger-UI-300x286.png 300w, https:\/\/code-maze.com\/wp-content\/uploads\/2019\/12\/Swagger-UI-768x731.png 768w\" sizes=\"auto, (max-width: 933px) 100vw, 933px\" \/><\/a><\/p>\n<p>This is a great way to document and explore an API. Since our application has no frontend attached, you can test the API directly using this documentation page, without the need to use external tools like Postman or Fiddler.<\/p>\n<p>To learn more about configuring Swagger in-depth, we suggest reading this article: <a href=\"https:\/\/code-maze.com\/swagger-ui-asp-net-core-web-api\/\" target=\"_blank\" rel=\"noopener noreferrer\">Configuring and Using Swagger UI in ASP.NET Core Web API<\/a>.<\/p>\n<p>Let&#8217;s move on.<\/p>\n<h2><a id=\"launch\"><\/a>Modifying the launchSettings.json File<\/h2>\n<p>We are going to change the <code>applicationUrl<\/code> property from <code>http:\/\/localhost:5000\/<\/code> to <code>http:\/\/0.0.0.0:5000\/<\/code> because otherwise, we are going to have problems with exposing our application to the local environment.<br \/>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-highlight=\"6,24\" data-enlighter-title=\"\">{\r\n  &quot;iisSettings&quot;: {\r\n    &quot;windowsAuthentication&quot;: false,\r\n    &quot;anonymousAuthentication&quot;: true,\r\n    &quot;iisExpress&quot;: {\r\n      &quot;applicationUrl&quot;: &quot;http:\/\/0.0.0.0:5000\/&quot;,\r\n      &quot;sslPort&quot;: 0\r\n    }\r\n  },\r\n  &quot;profiles&quot;: {\r\n    &quot;IIS Express&quot;: {\r\n      &quot;commandName&quot;: &quot;IISExpress&quot;,\r\n      &quot;launchBrowser&quot;: false,\r\n      &quot;environmentVariables&quot;: {\r\n        &quot;ASPNETCORE_ENVIRONMENT&quot;: &quot;Development&quot;\r\n      }\r\n    },\r\n    &quot;AccountOwnerServer&quot;: {\r\n      &quot;commandName&quot;: &quot;Project&quot;,\r\n      &quot;launchBrowser&quot;: false,\r\n      &quot;environmentVariables&quot;: {\r\n        &quot;ASPNETCORE_ENVIRONMENT&quot;: &quot;Development&quot;\r\n      },\r\n      &quot;applicationUrl&quot;: &quot;http:\/\/0.0.0.0:5000\/&quot;\r\n    }\r\n  }\r\n}<\/pre><\/p>\n<h2><a id=\"test\"><\/a>Adding the Test Project and a Unit Test<\/h2>\n<p>For testing purposes, we&#8217;re going to use the xUnit tool and Moq for mocking our data.<\/p>\n<p>The easiest way to add a testing project in ASP.NET Core is with the dotnet CLI. Navigate to the root of the solution and type:<br \/>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"ps\" data-enlighter-title=\"\">dotnet new xunit -o Tests<\/pre><br \/>\nThis will create the project using the xUnit template and restore the needed packages.<\/p>\n<p>After that we can add the project to the solution:<br \/>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"ps\" data-enlighter-title=\"\">dotnet sln AccountOwnerServer.sln add .\\Tests\\Tests.csproj<\/pre><br \/>\nAnd because we need to use the Moq library, we are going to navigate to Tests project and add it too:<br \/>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-title=\"\">cd Tests\r\ndotnet add package Moq\r\ndotnet restore<\/pre><br \/>\nAnd finally, reference the projects we need in order to write unit tests:<br \/>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"ps\" data-enlighter-title=\"\">dotnet add reference ..\\Contracts\\Contracts.csproj<\/pre><br \/>\nThat&#8217;s it for the setup part.<\/p>\n<p>Now we can easily add our first unit test to the project.<\/p>\n<p>First, rename the default <code>UnitTests1.cs<\/code> file to something more appropriate like <code>OwnerRepositoryTests.cs<\/code> in which we can test our owner repository logic.<\/p>\n<p>Now, let&#8217;s add our unit test:<\/p>\n<pre  class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">[Fact]\r\npublic void GetAllOwners_ReturnsListOfOwners_WithSingleOwner()\r\n{\r\n\t\/\/ Arrange\r\n\tvar mockRepo = new Mock&lt;IOwnerRepository&gt;();\r\n\tmockRepo.Setup(repo =&gt; (repo.GetAllOwners())).Returns(GetOwners());\r\n\r\n\t\/\/ Act\r\n\tvar result = mockRepo.Object.GetAllOwners().ToList();\r\n\r\n\t\/\/ Assert\r\n\tAssert.IsType&lt;List&lt;Owner&gt;&gt;(result);\r\n\tAssert.Single(result);\r\n}\r\n\r\npublic List&lt;Owner&gt; GetOwners()\r\n{\r\n\treturn new List&lt;Owner&gt;\r\n\t{\r\n\t\tnew Owner\r\n\t\t{\r\n\t\t\tId = Guid.NewGuid(),\r\n\t\t\tName = \"John Keen\",\r\n\t\t\tDateOfBirth = new DateTime(1980, 12, 05),\r\n\t\t\tAddress = \"61 Wellfield Road\"\r\n\t\t}\r\n\t};\r\n}<\/pre>\n<p>This is a simple demo test to check if the <code>GetAllOwners<\/code> method returns a list of <code>Owner<\/code> objects and if it returns exactly one owner as we defined in the <code>GetOwners<\/code> helper method.<\/p>\n<p>Now if you run <code>dotnet test<\/code> you should get something like this:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/Vlada\/DockerKubernetesSeries\/TestResults.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1911\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/Vlada\/DockerKubernetesSeries\/TestResults.png\" alt=\"Test Results\" width=\"615\" height=\"193\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/Vlada\/DockerKubernetesSeries\/TestResults.png 615w, https:\/\/code-maze.com\/wp-content\/uploads\/Vlada\/DockerKubernetesSeries\/TestResults-600x188.png 600w, https:\/\/code-maze.com\/wp-content\/uploads\/Vlada\/DockerKubernetesSeries\/TestResults-300x94.png 300w\" sizes=\"auto, (max-width: 615px) 100vw, 615px\" \/><\/a><\/p>\n<p>Excellent!<\/p>\n<p>We have completed the preparation part of the project. We have a working ASP.NET Core application, together with interactive documentation and some unit tests.<\/p>\n<p>Everything is set for the next step, which is why we did all this preparation. Now it&#8217;s time to dockerize our ASP.NET Core application.<\/p>\n<p>To check if everything works alright, run <code>dotnet build<\/code> and <code>dotnet test<\/code>. This is how we do it usually during the development phase. This time around we&#8217;ll use docker images and containers to do the same thing and bring our software development skills to another level.<\/p>\n<h2>Conclusion<\/h2>\n<p>That wraps it up for this part of the series. Although we haven&#8217;t even touched upon Docker yet, the changes we made here are important for the parts to come. These changes will help us soften the learning curve by introducing the concepts one by one.<\/p>\n<p>In the <a href=\"https:\/\/code-maze.com\/why-docker-docker-cli-examples\/\" target=\"_blank\" rel=\"noopener noreferrer\">next part<\/a> of the series, we are going to learn more about Docker, the reasons for using it, and we&#8217;re going to execute some basic Docker CLI commands.<\/p>\n<p>You can find all the changes up to this point by checking out the <a href=\"https:\/\/github.com\/CodeMazeBlog\/docker-series\/tree\/docker-series-app-prepared\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">docker-series-app-prepared<\/a> branch of the <a href=\"https:\/\/github.com\/CodeMazeBlog\/docker-series.git\" target=\"_blank\" rel=\"noopener noreferrer\">docker-series repository<\/a>.<\/p>\n<!-- Shortcode [subscribe] does not exist -->\n","protected":false},"excerpt":{"rendered":"<p>In this part, we are going to apply some modifications to our ASP.NET Core application in order to prepare it for the dockerization process. To follow along with this part you need: .NET Core 3.1 SDK Windows 10 Git IDE of your choice (we use Visual Studio 2019) Docker Desktop (at least 2.1.0.5) These are [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":54842,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"off","_et_pb_old_content":"In this part, we are going to apply some modifications to our ASP.NET Core application in order to prepare it for the dockerization process.\r\n\r\nTo <strong>follow along with this part<\/strong> you need .NET Core 2.0, Git, an IDE of your choice, and Docker.\r\n<ul id=\"series_parts\" style=\"display: none;\">\r\n \t<li>How to Prepare an ASP.NET Core Project for Dockerization (Current article)<\/li>\r\n \t<li><a href=\"https:\/\/code-maze.com\/why-docker-docker-cli-examples\/\" target=\"_blank\" rel=\"noopener noreferrer\">Why Docker: Docker CLI Through Examples<\/a><\/li>\r\n \t<li><a href=\"https:\/\/code-maze.com\/aspnetcore-app-dockerfiles\/\" target=\"_blank\" rel=\"noopener noreferrer\">Dockerizing ASP.NET Core Application with Dockerfiles<\/a><\/li>\r\n \t<li><a href=\"https:\/\/code-maze.com\/mysql-aspnetcore-docker-compose\/\" target=\"_blank\" rel=\"noopener noreferrer\">Adding MySQL to ASP.NET Core App With Docker Compose<\/a><\/li>\r\n \t<li><a href=\"https:\/\/code-maze.com\/docker-hub-vs-creating-docker-registry\/\" target=\"_blank\" rel=\"noopener noreferrer\">Docker Hub vs Creating a Local Docker Registry<\/a><\/li>\r\n \t<li><a href=\"https:\/\/code-maze.com\/preparing-ci-environment-docker\/\" target=\"_blank\" rel=\"noopener noreferrer\">Preparing a Continuous Integration Environment for Docker<\/a><\/li>\r\n \t<li><a href=\"https:\/\/code-maze.com\/ci-aspnetcoreapp-docker\/\" target=\"_blank\" rel=\"noopener noreferrer\">Continuous Integration with TeamCity and Docker<\/a><\/li>\r\n \t<li><a href=\"https:\/\/code-maze.com\/ci-jenkins-docker\/\" target=\"_blank\" rel=\"noopener noreferrer\">Continuous Integration with Jenkins and Docker<\/a><\/li>\r\n \t<li><a href=\"https:\/\/code-maze.com\/top-docker-monitoring-tools\/\" target=\"_blank\" rel=\"noopener noreferrer\">Top Docker Monitoring Tools<\/a><\/li>\r\n<\/ul>\r\n[sc name=\"part_of_series\" headline=\"This article is part of the series\"]\r\n\r\nFor the purposes of this article, we are going to re-use the application from our <a href=\"https:\/\/code-maze.com\/net-core-series\/\" target=\"_blank\" rel=\"noopener noreferrer\">.NET Core Series<\/a>, more concretely\u00a0<a href=\"https:\/\/code-maze.com\/net-core-web-development-part6\/\" target=\"_blank\" rel=\"noopener noreferrer\">part 6<\/a> of the series. The main reason for this decision is that if you are not familiar with the ASP.NET Core, you can go through the series and learn <strong>how to make ASP.NET Core WebApi application<\/strong> from scratch.\r\n\r\nSince we are going to make some changes to the code, if you want to follow along with the steps of this course, you can find the starting point on the <strong>master branch<\/strong>\u00a0<a href=\"https:\/\/github.com\/CodeMazeBlog\/docker-series.git\" target=\"_blank\" rel=\"noopener noreferrer\">docker-series<\/a>\r\n\r\nIf you want to skip the preparation phase and jump right into Docker goodness, you can switch to the\u00a0<strong><a href=\"https:\/\/github.com\/CodeMazeBlog\/docker-series\/tree\/docker-series-app-prepared\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">docker-series-app-prepared<\/a>\u00a0<\/strong>branch\u00a0of the <a href=\"https:\/\/github.com\/CodeMazeBlog\/docker-series.git\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">docker-series-app-prepared<\/a> repo and go quickly through this section. It might be beneficial\u00a0for you to follow along if you are not familiar with some of the changes we are going to implement.\r\n\r\nThis is the first article of our Docker Series. You can find the other parts on our <a href=\"https:\/\/code-maze.com\/docker-series\/\" target=\"_blank\" rel=\"noopener noreferrer\">Docker Series page<\/a>.\r\n\r\nThese are the changes we're going to make to the project:\r\n<ul>\r\n \t<li><a href=\"#memdb\">Switching to an In-Memory Database<\/a><\/li>\r\n \t<li><a href=\"#account\">Introducing AccountController<\/a><\/li>\r\n \t<li><a href=\"#swagger\">Introducing Swagger<\/a><\/li>\r\n \t<li><a href=\"#launch\">Modifying the launchSettings.json\u00a0File<\/a><\/li>\r\n \t<li><a href=\"#test\">Adding the Test Project and a Unit Test<\/a><\/li>\r\n<\/ul>\r\nThere is a lot to cover, so let's get down to business.\r\n<h2><a id=\"memdb\"><\/a>Switching to an In-Memory Database<\/h2>\r\nFirst things first.\r\n\r\nTo be able to dockerize\u00a0our app and make it work without relying on external resources (database) we are going to make some changes to the configuration. We are going to re-introduce MySQL later in the series, but for now, we are going to rely on an in-memory database to store our data into.\r\n\r\nSo, let's modify our <code>ServiceExtensions.cs<\/code> class:\r\n<pre class=\"lang:c# mark:3 decode:true\">public static void ConfigureMySqlContext(this IServiceCollection services, IConfiguration config)\r\n{\r\n\tservices.AddDbContext<RepositoryContext>(o => o.UseInMemoryDatabase(\"accountowner\"));\r\n}<\/pre>\r\nThat's it!\r\n\r\nWe successfully removed the reference to the MySQL database and added an in-memory database in a single line of code.\r\n\r\nIsn't that just great?\r\n\r\nDon't worry about the hanging connection string in the <code>appsettings.json<\/code> file, we don't need to remove it since we are going to use it in the next part.\r\n<h2><a id=\"account\"><\/a>Introducing AccountController<\/h2>\r\nTo make our API functional on its own, we are going to modify and rename existing <code>ValuesController<\/code>. So, first, we are going to rename it to <code>AccountController<\/code>, and then add some new code to it. We are going to add <code>GetAllAccounts<\/code> method and <code>CreateAccount<\/code> method which will give us more freedom to play with our API.\r\n<pre class=\"lang:c# decode:true\">[Route(\"api\/[controller]\")]\r\npublic class AccountController : Controller\r\n{\r\n\tprivate ILoggerManager _logger;\r\n\tprivate IRepositoryWrapper _repository;\r\n\r\n\tpublic AccountController(ILoggerManager logger, IRepositoryWrapper repository)\r\n\t{\r\n\t\t_logger = logger;\r\n\t\t_repository = repository;\r\n\t}\r\n\r\n\t[HttpGet]\r\n\tpublic IActionResult GetAllAccounts()\r\n\t{\r\n\t\ttry\r\n\t\t{\r\n\t\t\tvar accounts = _repository.Account.GetAllAccounts();\r\n\r\n\t\t\t_logger.LogInfo($\"Returned all accounts from database.\");\r\n\r\n\t\t\treturn Ok(accounts);\r\n\t\t}\r\n\t\tcatch (Exception ex)\r\n\t\t{\r\n\t\t\t_logger.LogError($\"Something went wrong inside GetAllAccounts action: {ex}\");\r\n\t\t\treturn StatusCode(500, \"Internal server error\");\r\n\t\t}\r\n\t}\r\n\r\n\t[HttpPost]\r\n\tpublic IActionResult CreateOwner([FromBody]Account account)\r\n\t{\r\n\t\ttry\r\n\t\t{\r\n\t\t\tif (account.IsObjectNull())\r\n\t\t\t{\r\n\t\t\t\t_logger.LogError(\"Object sent from client is null.\");\r\n\t\t\t\treturn BadRequest(\"Object is null\");\r\n\t\t\t}\r\n\r\n\t\t\tif (!ModelState.IsValid)\r\n\t\t\t{\r\n\t\t\t\t_logger.LogError(\"Invalid object sent from client.\");\r\n\t\t\t\treturn BadRequest(\"Invalid model object\");\r\n\t\t\t}\r\n\r\n\t\t\t_repository.Account.CreateAccount(account);\r\n\r\n\t\t\treturn CreatedAtRoute(\"AccountById\", new { id = account.Id }, account);\r\n\t\t}\r\n\t\tcatch (Exception ex)\r\n\t\t{\r\n\t\t\t_logger.LogError($\"Something went wrong inside CreateAccount action: {ex}\");\r\n\t\t\treturn StatusCode(500, \"Internal server error\");\r\n\t\t}\r\n\t}\r\n}<\/pre>\r\nOf course, the compiler won't let us build this since we need to implement\u00a0<code>GetAllAccounts<\/code> and <code>CreateAccount<\/code> methods in our <code>AccountRepository<\/code>.\r\n\r\nSo let's do exactly that.\r\n\r\nAdd the method declarations to the <code>IAccountRepository<\/code>:\r\n<pre class=\"lang:c# decode:true\">public interface IAccountRepository\r\n{\r\n\tIEnumerable<Account> GetAllAccounts();\r\n\tvoid CreateAccount(Account account);\r\n}<\/pre>\r\nAnd the implementation the <code>AccountRepository<\/code>:\r\n<pre class=\"lang:c# decode:true\">public IEnumerable<Account> GetAllAccounts()\r\n{\r\n\treturn FindAll()\r\n\t\t.OrderBy(ac => ac.DateCreated);\r\n}\r\n\r\npublic void CreateAccount(Account account)\r\n{\r\n\taccount.Id = Guid.NewGuid();\r\n\tCreate(account);\r\n\tSave();\r\n}<\/pre>\r\nNow run the <code>dotnet build<\/code> on the entire solution, and the project should compile.\r\n\r\nAnd just like that, we have a working AccountController.\r\n<h2><a id=\"swagger\"><\/a>Introducing Swagger<\/h2>\r\nSwagger is one of the most popular and versatile frameworks for tooling your APIs.\r\n\r\nHere is how we are going to add it to our project.\r\n\r\nNavigate to the <code>\/AccountOwnerServer<\/code> folder. After that execute the command:\r\n<pre class=\"lang:ps highlight:0 decode:true\">dotnet add package Swashbuckle.AspNetCore --version 2.3.0<\/pre>\r\nThis will add the reference to <a href=\"https:\/\/github.com\/domaindrivendev\/Swashbuckle.AspNetCore\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Swashbuckle package for ASP.NET Core<\/a> to our project (2.3.0 is the current version, for now). In short, Swashbuckle will help us integrate Swagger into our application.\r\n\r\nAfter that, we have to enable Swagger by changing our <code>Startup.cs<\/code> file a bit.\r\n\r\nTo the <code>ConfigureServices<\/code> method, just after the <code>service.AddMvc()<\/code> line, we are going to add:\r\n<pre class=\"lang:c# decode:true\">services.AddSwaggerGen(c =>\r\n{\r\n\tc.SwaggerDoc(\"v1\", new Info { Title = \"AccountOwner API\", Version = \"v1\" });\r\n});<\/pre>\r\nAnd to the Configure method just after the\u00a0<code>app.UseMvc()<\/code> line:\r\n<pre class=\"lang:c# decode:true \">app.UseSwagger();\r\n\r\napp.UseSwaggerUI(c =>\r\n{\r\n\tc.SwaggerEndpoint(\"\/swagger\/v1\/swagger.json\", \"AccountOwner API V1\");\r\n});<\/pre>\r\nGreat. That wasn't too hard, was it?\r\n\r\nBut, what have we gained by doing all this?\r\n\r\nIf you run the application now and go navigate to\u00a0<code>http:\/\/localhost:5000\/swagger\/v1\/swagger.json<\/code> to see the information about your API presented in JSON format.\r\n\r\nThis information is the power behind the more interesting part of Swagger, the interactive documentation which you can get by navigating to <code>http:\/\/localhost:5000\/swagger<\/code>. If you did everything right you should see the documentation page like this one:\r\n\r\n<a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/Vlada\/DockerKubernetesSeries\/Swagger-UI.png\"><img class=\"alignnone size-full wp-image-1906\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/Vlada\/DockerKubernetesSeries\/Swagger-UI.png\" alt=\"Swagger UI\" width=\"842\" height=\"879\" \/><\/a>\r\n\r\nThis is a great way to document and explore an API. Since our application has no frontend attached, you can test the API directly using this documentation page, without the need to use external tools like Postman or Fiddler.\r\n\r\nLet's move on.\r\n<h2><a id=\"launch\"><\/a>Modifying the launchSettings.json File<\/h2>\r\nWe are going to change the <code>http:\/\/localhost:5000\/<\/code> to <code>http:\/\/[::]:5000\/<\/code> because otherwise, we are going to have problems with exposing our application to the local environment. <code>http:\/\/0.0.0.0:5000\/<\/code> works too.\r\n<pre class=\"lang:js mark:6,24 decode:true\">{\r\n  \"iisSettings\": {\r\n    \"windowsAuthentication\": false,\r\n    \"anonymousAuthentication\": true,\r\n    \"iisExpress\": {\r\n      \"applicationUrl\": \"http:\/\/[::]:5000\/\",\r\n      \"sslPort\": 0\r\n    }\r\n  },\r\n  \"profiles\": {\r\n    \"IIS Express\": {\r\n      \"commandName\": \"IISExpress\",\r\n      \"launchBrowser\": false,\r\n      \"environmentVariables\": {\r\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\r\n      }\r\n    },\r\n    \"AccountOwnerServer\": {\r\n      \"commandName\": \"Project\",\r\n      \"launchBrowser\": false,\r\n      \"environmentVariables\": {\r\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\r\n      },\r\n      \"applicationUrl\": \"http:\/\/[::]:5000\/\"\r\n    }\r\n  }\r\n}<\/pre>\r\n<h2><a id=\"test\"><\/a>Adding the Test Project and a Unit Test<\/h2>\r\nFor the testing purposes, we're going to use xUnit tool and Moq for mocking our data.\r\n\r\nThe easiest way to add a testing project in ASP.NET Core is with the dotnet CLI. Navigate to the root of the solution and type:\r\n<pre class=\"lang:ps highlight:0 decode:true\">dotnet new xunit -o Tests<\/pre>\r\nThis will create the project using the xUnit template and restore the needed packages.\r\n\r\nAfter that we can add the project to the solution:\r\n<pre class=\"lang:ps highlight:0 decode:true\">dotnet sln AccountOwnerServer.sln add .TestsTests.csproj<\/pre>\r\nAnd because we need to use Moq library, we are going to navigate to Tests project and add it too:\r\n<pre class=\"lang:c# highlight:0 decode:true\">cd Tests\r\ndotnet add package Moq\r\ndotnet restore<\/pre>\r\nAnd finally, reference the projects we need in order to write unit tests:\r\n<pre class=\"lang:ps highlight:0 decode:true\">dotnet add reference ..ContractsContracts.csproj<\/pre>\r\nThat's it for the setup part.\r\n\r\nNow we can easily add our first unit test to the project.\r\n\r\nFirst, rename the default <code>UnitTests1.cs<\/code> file to something more appropriate like <code>OwnerRepositoryTests.cs<\/code> in which we can test our owner repository logic.\r\n\r\nNow, let's add our unit test:\r\n<pre class=\"lang:c# decode:true\">[Fact]\r\npublic void GetAllOwners_ReturnsListOfOwners_WithSingleOwner()\r\n{\r\n\t\/\/ Arrange\r\n\tvar mockRepo = new Mock<IOwnerRepository>();\r\n\tmockRepo.Setup(repo => (repo.GetAllOwners())).Returns(GetOwners());\r\n\r\n\t\/\/ Act\r\n\tvar result = mockRepo.Object.GetAllOwners().ToList();\r\n\r\n\t\/\/ Assert\r\n\tAssert.IsType<List<Owner>>(result);\r\n\tAssert.Single(result);\r\n}\r\n\r\npublic List<Owner> GetOwners()\r\n{\r\n\treturn new List<Owner>\r\n\t{\r\n\t\tnew Owner\r\n\t\t{\r\n\t\t\tId = Guid.NewGuid(),\r\n\t\t\tName = \"John Keen\",\r\n\t\t\tDateOfBirth = new DateTime(1980, 12, 05),\r\n\t\t\tAddress = \"61 Wellfield Road\"\r\n\t\t}\r\n\t};\r\n}<\/pre>\r\nThis is a simple demo test to check if the <code>GetAllOwners<\/code> method returns a list of <code>Owner<\/code> objects and if it returns exactly one owner like we defined in <code>GetOwners<\/code> helper method.\r\n\r\nNow if you run <code>dotnet test<\/code> you should get something like this:\r\n\r\n<a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/Vlada\/DockerKubernetesSeries\/TestResults.png\"><img class=\"alignnone size-full wp-image-1911\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/Vlada\/DockerKubernetesSeries\/TestResults.png\" alt=\"Test Results\" width=\"615\" height=\"193\" \/><\/a>\r\n\r\nGreat!\r\n\r\nWe have completed the preparation part of the project. We have a working ASP.NET Core application, together with interactive documentation and some unit tests.\r\n\r\nEverything is set for the next step, which is why we did all this preparation for and that's the Dockerization of our ASP.NET Core application.\r\n\r\nTo check if everything works alright, run <code>dotnet build<\/code> and <code>dotnet test<\/code>. This is how we do it usually during the development phase. But, to lift this up a level, we're going to try it out by using Docker images and containers in this series.\r\n<h2>Conclusion<\/h2>\r\nThat wraps it up for this part of the series. Although we haven't touched Docker yet, the changes we made here are important for the parts to come. These changes will help us soften the learning curve by introducing the concepts one by one.\r\n\r\nIn the <a href=\"https:\/\/code-maze.com\/why-docker-docker-cli-examples\/\" target=\"_blank\" rel=\"noopener noreferrer\">next part<\/a>, we are going to learn more about Docker, the reasons for using it, and we're going to execute some basic Docker CLI commands.\r\n\r\nYou can find all the changes up to this point by checking out the <a href=\"https:\/\/github.com\/CodeMazeBlog\/docker-series\/tree\/docker-series-app-prepared\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">docker-series-app-prepared<\/a> branch of the <a href=\"https:\/\/github.com\/CodeMazeBlog\/docker-series.git\" target=\"_blank\" rel=\"noopener noreferrer\">docker-series repository<\/a>.\r\n\r\n[sc name=\"subscribe\" formNumber=\"2792\" contentType=\"Web Development\"]","_et_gb_content_width":"","footnotes":""},"categories":[66],"tags":[22,79,85,83,82,84,45],"class_list":["post-1857","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","tag-net-core","tag-asp-net-core","tag-aspnetcore","tag-devops","tag-docker","tag-dotnetcore","tag-web-development","et-has-post-format-content","et_post_format-et-post-format-standard"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>How to Prepare an ASP.NET Core Application for Dockerization - Code Maze<\/title>\n<meta name=\"description\" content=\"In this part of the series, we are preparing our ASP.NET Core application for the process of dockerization that we will perform later in the series.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Prepare an ASP.NET Core Application for Dockerization - Code Maze\" \/>\n<meta property=\"og:description\" content=\"In this part of the series, we are preparing our ASP.NET Core application for the process of dockerization that we will perform later in the series.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/\" \/>\n<meta property=\"og:site_name\" content=\"Code Maze\" \/>\n<meta property=\"article:published_time\" content=\"2018-04-25T05:06:38+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-09-02T19:51:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/docker-part1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1100\" \/>\n\t<meta property=\"og:image:height\" content=\"620\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Vladimir Pecanac\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/PecanacVladimir\" \/>\n<meta name=\"twitter:site\" content=\"@CodeMazeBlog\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Vladimir Pecanac\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/\"},\"author\":{\"name\":\"Vladimir Pecanac\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/50de31ad4e1992752e972e4715d93739\"},\"headline\":\"How to Prepare an ASP.NET Core Application for Dockerization\",\"datePublished\":\"2018-04-25T05:06:38+00:00\",\"dateModified\":\"2020-09-02T19:51:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/\"},\"wordCount\":1270,\"commentCount\":11,\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/docker-part1.png\",\"keywords\":[\".NET CORE\",\"asp.net core\",\"aspnetcore\",\"DevOps\",\"Docker\",\"dotnetcore\",\"web development\"],\"articleSection\":[\"DevOps\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/\",\"url\":\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/\",\"name\":\"How to Prepare an ASP.NET Core Application for Dockerization - Code Maze\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/docker-part1.png\",\"datePublished\":\"2018-04-25T05:06:38+00:00\",\"dateModified\":\"2020-09-02T19:51:18+00:00\",\"description\":\"In this part of the series, we are preparing our ASP.NET Core application for the process of dockerization that we will perform later in the series.\",\"breadcrumb\":{\"@id\":\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#primaryimage\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/docker-part1.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/docker-part1.png\",\"width\":1100,\"height\":620,\"caption\":\"docker getting started\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/code-maze.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Prepare an ASP.NET Core Application for Dockerization\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/code-maze.com\/#website\",\"url\":\"https:\/\/code-maze.com\/\",\"name\":\"Code Maze\",\"description\":\"Learn. Code. Succeed.\",\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/code-maze.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/code-maze.com\/#organization\",\"name\":\"Code Maze\",\"url\":\"https:\/\/code-maze.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"width\":3511,\"height\":3510,\"caption\":\"Code Maze\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/CodeMazeBlog\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/50de31ad4e1992752e972e4715d93739\",\"name\":\"Vladimir Pecanac\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2016\/02\/profile_image-100x100.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2016\/02\/profile_image-100x100.png\",\"caption\":\"Vladimir Pecanac\"},\"description\":\"Hi, my name is Vladimir Pecanac, and I am a full-time .NET developer and DevOps enthusiast. I created this blog so I can share the things I learn in the hope of both helping others and deepening my own knowledge of the topics I write about. The best way to learn is to teach.\",\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/vladimir-pecanac\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/PecanacVladimir\"],\"url\":\"https:\/\/code-maze.com\/author\/codemaze_blog\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to Prepare an ASP.NET Core Application for Dockerization - Code Maze","description":"In this part of the series, we are preparing our ASP.NET Core application for the process of dockerization that we will perform later in the series.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/","og_locale":"en_US","og_type":"article","og_title":"How to Prepare an ASP.NET Core Application for Dockerization - Code Maze","og_description":"In this part of the series, we are preparing our ASP.NET Core application for the process of dockerization that we will perform later in the series.","og_url":"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/","og_site_name":"Code Maze","article_published_time":"2018-04-25T05:06:38+00:00","article_modified_time":"2020-09-02T19:51:18+00:00","og_image":[{"width":1100,"height":620,"url":"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/docker-part1.png","type":"image\/png"}],"author":"Vladimir Pecanac","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/PecanacVladimir","twitter_site":"@CodeMazeBlog","twitter_misc":{"Written by":"Vladimir Pecanac","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#article","isPartOf":{"@id":"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/"},"author":{"name":"Vladimir Pecanac","@id":"https:\/\/code-maze.com\/#\/schema\/person\/50de31ad4e1992752e972e4715d93739"},"headline":"How to Prepare an ASP.NET Core Application for Dockerization","datePublished":"2018-04-25T05:06:38+00:00","dateModified":"2020-09-02T19:51:18+00:00","mainEntityOfPage":{"@id":"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/"},"wordCount":1270,"commentCount":11,"publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"image":{"@id":"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/docker-part1.png","keywords":[".NET CORE","asp.net core","aspnetcore","DevOps","Docker","dotnetcore","web development"],"articleSection":["DevOps"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/","url":"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/","name":"How to Prepare an ASP.NET Core Application for Dockerization - Code Maze","isPartOf":{"@id":"https:\/\/code-maze.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#primaryimage"},"image":{"@id":"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/docker-part1.png","datePublished":"2018-04-25T05:06:38+00:00","dateModified":"2020-09-02T19:51:18+00:00","description":"In this part of the series, we are preparing our ASP.NET Core application for the process of dockerization that we will perform later in the series.","breadcrumb":{"@id":"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#primaryimage","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/docker-part1.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/docker-part1.png","width":1100,"height":620,"caption":"docker getting started"},{"@type":"BreadcrumbList","@id":"https:\/\/code-maze.com\/how-to-prepare-aspnetcore-app-dockerization\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/code-maze.com\/"},{"@type":"ListItem","position":2,"name":"How to Prepare an ASP.NET Core Application for Dockerization"}]},{"@type":"WebSite","@id":"https:\/\/code-maze.com\/#website","url":"https:\/\/code-maze.com\/","name":"Code Maze","description":"Learn. Code. Succeed.","publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/code-maze.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/code-maze.com\/#organization","name":"Code Maze","url":"https:\/\/code-maze.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","width":3511,"height":3510,"caption":"Code Maze"},"image":{"@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/CodeMazeBlog"]},{"@type":"Person","@id":"https:\/\/code-maze.com\/#\/schema\/person\/50de31ad4e1992752e972e4715d93739","name":"Vladimir Pecanac","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/person\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2016\/02\/profile_image-100x100.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2016\/02\/profile_image-100x100.png","caption":"Vladimir Pecanac"},"description":"Hi, my name is Vladimir Pecanac, and I am a full-time .NET developer and DevOps enthusiast. I created this blog so I can share the things I learn in the hope of both helping others and deepening my own knowledge of the topics I write about. The best way to learn is to teach.","sameAs":["https:\/\/www.linkedin.com\/in\/vladimir-pecanac\/","https:\/\/x.com\/https:\/\/twitter.com\/PecanacVladimir"],"url":"https:\/\/code-maze.com\/author\/codemaze_blog\/"}]}},"_links":{"self":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/1857","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/comments?post=1857"}],"version-history":[{"count":0,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/1857\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media\/54842"}],"wp:attachment":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media?parent=1857"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/categories?post=1857"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/tags?post=1857"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}