{"id":14916,"date":"2015-01-14T09:13:00","date_gmt":"2015-01-14T09:13:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/webdev\/2015\/01\/14\/running-asp-net-5-applications-in-linux-containers-with-docker\/"},"modified":"2024-01-22T14:01:29","modified_gmt":"2024-01-22T22:01:29","slug":"running-asp-net-5-applications-in-linux-containers-with-docker","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/running-asp-net-5-applications-in-linux-containers-with-docker\/","title":{"rendered":"Running ASP.NET 5 applications in Linux Containers with Docker"},"content":{"rendered":"<p>As a part of our ASP.NET 5 cross-platform efforts, we are actively working on making applications written in ASP.NET 5 easy to deploy and ship on Linux and Mac OS X. A while ago, we have released the first official Docker image by Microsoft: the&nbsp;<a href=\"http:\/\/registry.hub.docker.com\/u\/microsoft\/aspnet\/\">ASP.NET 5 Preview Docker Image<\/a>.<\/p>\n<p><a href=\"http:\/\/docker.com\/\">Docker<\/a> is an open source project that makes it easier to run applications in sandboxed application containers on Linux. With the ASP.NET 5 Docker image, you can get a base image where the ASP.NET 5 bits are already installed to run on Linux for you. All you need to do is add your application to the image and ship it so it will run in an app container!<\/p>\n<blockquote class=\"twitter-tweet\" lang=\"en\">\n<p>Hey, look at that <a href=\"https:\/\/twitter.com\/aspnet\">@aspnet<\/a> 5 docker image in the Docker Repository. <a href=\"https:\/\/t.co\/hfBmVUgrwK\">https:\/\/t.co\/hfBmVUgrwK<\/a><\/p>\n<p>&mdash; The ASP.NET Team (@aspnet) <a href=\"https:\/\/twitter.com\/aspnet\/status\/533394519199592451\">November 14, 2014<\/a><\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<p>In this tutorial we will show how a simple application written in ASP.NET 5 Preview can be deployed to a Linux Virtual Machine running on Microsoft Azure cloud using Docker. The tutorial can be executed on a Linux or Mac OS X machine where Docker client is installed (or you can ssh into the Linux VM you will use). Once Windows client for Docker is available, you will be able to run these commands on Windows and once Windows Server container support comes out you will be able to use Docker to manage Windows Server containers.<\/p>\n<blockquote>\n<p><strong>NOTE<\/strong>: Both ASP.NET 5 (vNext) and the Docker image are in preview and the following instructions are subject to change in the future. Please refer to&nbsp;<a href=\"http:\/\/registry.hub.docker.com\/u\/microsoft\/aspnet\/\">Docker Hub<\/a>&nbsp;page and&nbsp;<a href=\"https:\/\/github.com\/aspnet\/aspnet-docker\">GitHub repository<\/a>&nbsp;for latest documentation on how to use the Docker image for ASP.NET 5.<\/p>\n<\/blockquote>\n<h2>Step 1: Create a Linux VM with Docker<\/h2>\n<p>As Docker only runs on Linux today, you will need a Linux machine or VM to run Docker on your server. You can find Docker installation instructions&nbsp;<a href=\"https:\/\/docs.docker.com\/installation\/ubuntulinux\/\">here<\/a>&nbsp;or follow the&nbsp;<a href=\"http:\/\/azure.microsoft.com\/en-us\/documentation\/articles\/virtual-machines-docker-ubuntu-quickstart\/\">Getting Started with Docker on Azure<\/a>&nbsp;to get a Docker-ready Linux VM on Azure.<\/p>\n<p>In this tutorial we will assume you have a Linux Virtual Machine on Azure with Docker installed. If you are using some other machine, most of this tutorial will still be relevant.<\/p>\n<h2>Step 2: Create a container image for your app<\/h2>\n<p>In order to deliver your ASP.NET application to the cloud, you will need to create a container image containing your application.<\/p>\n<p>Docker container images are layers on top of each other. This means your application is an addition on top of a &ldquo;base image&rdquo; &ndash;in this case the base image will be&nbsp;<a href=\"http:\/\/registry.hub.docker.com\/u\/microsoft\/aspnet\/\"><code>microsoft\/aspnet<\/code><\/a>. The image layers are stored as diffs, therefore while deploying your application, your image will not contain the Linux distribution or the ASP.NET binaries; it will only contain your application, making it small in size and quickly deployable.<\/p>\n<p>Creating a Docker image is done using a file called&nbsp;<code>Dockerfile<\/code>. Similar to a Makefile, the Dockerfile contains instructions telling Docker how to build the image.<\/p>\n<p>For the sake of this tutorial, we will use the&nbsp;<a href=\"https:\/\/github.com\/aspnet\/Home\/tree\/master\/samples\/HelloWeb\">sample&nbsp;<code>HelloWeb<\/code>&nbsp;application<\/a>&nbsp;from&nbsp;<a href=\"https:\/\/github.com\/aspnet\/Home\/\">aspnet\/Home<\/a>&nbsp;repository on GitHub. First, clone this repository on your development machine and go to the&nbsp;<code>HelloWeb<\/code>&nbsp;directory using git:<\/p>\n<blockquote>\n<pre>git clone git@github.com:aspnet\/Home.git aspnet-Home\r\ncd aspnet-Home\/samples\/HelloWeb<\/pre>\n<\/blockquote>\n<p>In this directory you will see the following files:<\/p>\n<blockquote>\n<pre>\u251c\u2500\u2500 Startup.cs\r\n\u251c\u2500\u2500 image.jpg\r\n\u2514\u2500\u2500 project.json<\/pre>\n<\/blockquote>\n<p>We are going to create a file called&nbsp;<code>Dockerfile<\/code>&nbsp;in this directory with the following contents:<\/p>\n<blockquote>\n<pre>FROM microsoft\/aspnet\r\n\r\nCOPY . \/app\r\nWORKDIR \/app\r\nRUN [\"dnu\", \"restore\"]\r\n\r\nEXPOSE 5004\r\nENTRYPOINT [\"dnx\", \"-p\", \"project.json\", \"kestrel\"]<\/pre>\n<\/blockquote>\n<p>Let&#8217;s go through this Dockerfile line by line. The first&nbsp;<code>FROM<\/code>&nbsp;line tells Docker that we will use the&nbsp;<a href=\"http:\/\/registry.hub.docker.com\/u\/microsoft\/aspnet\/\">official ASP.NET image<\/a>&nbsp;on Docker Hub as our base image.<\/p>\n<p>The&nbsp;<code>COPY<\/code>&nbsp;line tells Docker that we will copy contents of this folder (<code>.<\/code>) to the&nbsp;<code>\/app<\/code>&nbsp;directory of the container and the&nbsp;<code>WORKDIR<\/code>&nbsp;instruction will move to the&nbsp;<code>\/app<\/code>&nbsp;directory.<\/p>\n<p>The&nbsp;<code>RUN<\/code>&nbsp;instruction tells Docker to run the&nbsp;<code>dnu restore<\/code>&nbsp;command to install the dependencies of the application. We do this before running out application for the first time.<\/p>\n<p>The&nbsp;<code>EXPOSE<\/code>&nbsp;instruction will inform Docker that this image has a service which will be listening at port 5004 (see&nbsp;<code>project.json<\/code>&nbsp;of the sample file for details). Lastly, the&nbsp;<code>ENTRYPOINT<\/code>&nbsp;instruction is the command executed to start the container and keep it up and running. In this case it is the &#8220;<code>dnx . kestrel\"&nbsp;<\/code>command, starting the&nbsp;<a href=\"https:\/\/github.com\/aspnet\/KestrelHttpServer\">Kestrel<\/a>&nbsp;development server for ASP.NET 5. Once executed, this process will start listening to HTTP connections coming from port 5004.&nbsp;<\/p>\n<h2>Step 3: Build the container image<\/h2>\n<p>Once we have Dockerfile ready, the directory should look like this, a Dockerfile residing with next to the application:<\/p>\n<blockquote>\n<pre>\u251c\u2500\u2500 Dockerfile\r\n\u251c\u2500\u2500 Startup.cs\r\n\u251c\u2500\u2500 image.jpg\r\n\u2514\u2500\u2500 project.json<\/pre>\n<\/blockquote>\n<p>Now we will actually build the Docker image. It is very simple &ndash;just run the following Docker command in this directory:<\/p>\n<blockquote>\n<pre>docker build -t myapp .<\/pre>\n<\/blockquote>\n<p>This will build an image using the Dockerfile we just created and call it&nbsp;<code>myapp<\/code>. Every time you change your application, a new image can be built using this command. After this command finishes, we should be able to see our application in the list of Docker images on our Linux VM by running the following command on our development machine:<\/p>\n<blockquote>\n<pre>$ docker images\r\nREPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE\r\nmyapp               latest              ccb7994d2bc1        39 seconds ago      499.8 MB\r\nmicrosoft\/aspnet    latest              16b1838c0b34        12 days ago         473.4 MB\r\n<\/pre>\n<\/blockquote>\n<p>As you can see, your app and the ASP.NET image are listed as images that exist on your machine.<\/p>\n<p>Now we are ready to deploy our application to the cloud.<\/p>\n<h2>Step 4: Run the container<\/h2>\n<p>Running the container is the easiest part of the tutorial. Run the following Docker command on your development machine:<\/p>\n<blockquote>\n<pre>docker run -t -d -p 80:5004 myapp<\/pre>\n<\/blockquote>\n<ul class=\"task-list\">\n<li>The&nbsp;<code>-t<\/code>&nbsp;switch attaches a pseudo-tty to the container (this switch will not be necessary in future versions of ASP.NET 5).<\/li>\n<li>The&nbsp;<code>-d<\/code>&nbsp;switch runs the container in the background, otherwise the web server&#8217;s standard input\/output streams would be attached to our development machine&#8217;s shell.<\/li>\n<li>The&nbsp;<code>-p<\/code>&nbsp;switch maps port 80 of the VM to port 5004 of the container. In this case, connections coming to port 80 of the VM will be forwarded to our container listening on port 5004.<\/li>\n<li>Lastly,&nbsp;<code>myapp<\/code>&nbsp;is the Docker image name we are using to start the container. We built this image in the previous step.<\/li>\n<\/ul>\n<p>Once the container is started, the following command can be used to show containers running on your machine:<\/p>\n<blockquote>\n<pre>$ docker ps\r\nCONTAINER ID        IMAGE               COMMAND                CREATED              STATUS              PORTS                  NAMES\r\nf70bd9ffbc36        myapp:latest        \"\/bin\/sh -c 'dnx .     About a minute ago   Up About a minute   0.0.0.0:80-&gt;5004\/tcp   mad_goodall\r\n<\/pre>\n<\/blockquote>\n<p>Our container has started! However, we are not quite done yet. We need to complete the&nbsp;<strong>endpoint port mapping for Azure VM<\/strong>. You need to go to the Azure Management Portal to map public TCP port 80 to internal port 80 on your Linux VM (see relevant tutorial&nbsp;<a href=\"http:\/\/azure.microsoft.com\/en-us\/documentation\/articles\/virtual-machines-set-up-endpoints\/\">here<\/a>).<\/p>\n<p>Now let&#8217;s head to the browser to see if it is working. Open&nbsp;<code>http:\/\/your-cloud-service-name.cloudapp.net:80\/<\/code>&nbsp;in your web browser:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2015\/01\/1401.Image202015-01-1020at2011.26.5020AM.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2015\/01\/1401.Image202015-01-1020at2011.26.5020AM.png\" alt=\"\" border=\"0\" \/> <\/a><\/p>\n<p>Voila, you have an ASP.NET 5 application running on Linux inside a Docker container!<\/p>\n<p>If your application is slightly different than the single-project sample application we used, you can learn more about writing Dockerfiles&nbsp;<a href=\"https:\/\/docs.docker.com\/reference\/builder\/\">here<\/a>&nbsp;and build your own images with custom commands.<\/p>\n<h2>Conclusion<\/h2>\n<p>We will continue to invest in running ASP.NET 5 applications on Linux and Docker and we are happy to bring you the Microsoft&#8217;s first official Docker image:&nbsp;<a href=\"http:\/\/registry.hub.docker.com\/u\/microsoft\/aspnet\/\">ASP.NET 5 Preview Image<\/a>.<\/p>\n<p>Since this tutorial depends on previews of ASP.NET 5 and its Docker image, the exact usage instructions may change over time. Please head over to&nbsp;<a href=\"http:\/\/registry.hub.docker.com\/u\/microsoft\/aspnet\/\">Docker Hub<\/a>&nbsp;page or&nbsp;<a href=\"https:\/\/github.com\/aspnet\/aspnet-docker\">GitHub repository<\/a>&nbsp;to see up-to-date instructions.<\/p>\n<p>Please send us your feedback and help us improve this Docker image by opening new issues on&nbsp;<a href=\"https:\/\/github.com\/aspnet\/aspnet-docker\">GitHub repository<\/a>.<\/p>\n<p><a href=\"http:\/\/ahmetalpbalkan.com\">Ahmet Alp Balkan<\/a> (<a href=\"https:\/\/twitter.com\/ahmetalpbalkan\">@ahmetalpbalkan<\/a>)<br \/>Software Engineer, Microsoft Azure<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As a part of our ASP.NET 5 cross-platform efforts, we are actively working on making applications written in ASP.NET 5 easy to deploy and ship on Linux and Mac OS X. A while ago, we have released the first official Docker image by Microsoft: the&nbsp;ASP.NET 5 Preview Docker Image. Docker is an open source project [&hellip;]<\/p>\n","protected":false},"author":406,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197],"tags":[7465,37,60],"class_list":["post-14916","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspnet","tag-asp-net-vnext","tag-azure","tag-docker"],"acf":[],"blog_post_summary":"<p>As a part of our ASP.NET 5 cross-platform efforts, we are actively working on making applications written in ASP.NET 5 easy to deploy and ship on Linux and Mac OS X. A while ago, we have released the first official Docker image by Microsoft: the&nbsp;ASP.NET 5 Preview Docker Image. Docker is an open source project [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/14916","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/406"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=14916"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/14916\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=14916"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=14916"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=14916"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}