{"id":20395,"date":"2018-08-13T10:00:25","date_gmt":"2018-08-13T17:00:25","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vcblog\/?p=20395"},"modified":"2019-02-18T17:47:49","modified_gmt":"2019-02-18T17:47:49","slug":"using-msvc-in-a-docker-container-for-your-c-projects","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/using-msvc-in-a-docker-container-for-your-c-projects\/","title":{"rendered":"Using MSVC in a Docker Container for Your C++ Projects"},"content":{"rendered":"<p>Containers encapsulate the runtime environment of an application: the file system, environment settings, and virtualized OS are bundled into a package. <span><a href=\"https:\/\/www.docker.com\/what-container\">Docker containers<\/a><\/span> have changed the way we think about build and test environments since they were introduced five years ago.<\/p>\n<p>Visual Studio\u2019s setup and install expert, <span><a href=\"https:\/\/blogs.msdn.microsoft.com\/heaths\/\">Heath Stewart<\/a><\/span>, blogs regularly about how to install the <span><a href=\"https:\/\/aka.ms\/buildtools\">Visual Studio Build Tools<\/a><\/span> in a Windows Docker Container. Recently he explained <span><a href=\"https:\/\/devblogs.microsoft.com\/setup\/no-container-image-for-build-tools-for-visual-studio-2017\/\">why you won\u2019t find a container image for build tools<\/a><\/span>. Basically, any install that has a workload installed that you aren\u2019t using is going to be bigger than you want. You should tailor an install for your needs. So here we are going to show how to create and use an MSVC Docker container.<\/p>\n<p>The first step is to <span><a href=\"https:\/\/docs.docker.com\/docker-for-windows\/install\">install Docker Community Edition<\/a><\/span>. If you don\u2019t have Hyper-V enabled, the installer will prompt you to enable it and reboot. After it is installed you need to switch to Windows containers. The official documentation on how to <span><a href=\"https:\/\/docs.microsoft.com\/en-us\/visualstudio\/install\/build-tools-container\">Install Build Tools into a Container<\/a><\/span> walks through this in much more detail. If you refer to that, stop at step 5 and read the following instructions for creating an MSVC Docker container.<\/p>\n<p>Remember that the <span><a href=\"https:\/\/www.visualstudio.com\/license-terms\/mlt553512\/\">VS Build Tools are licensed as a supplement<\/a><\/span> to your existing Visual Studio license. Any images built with these tools should be for your personal use or for use in your organization in accordance with your existing Visual Studio and Windows licenses. Please don\u2019t share these images on a public Docker hub.<\/p>\n<h2>Visual Studio Build Tools Dockerfiles<\/h2>\n<p>To help you get started in creating Dockerfiles tailored for your needs we have <span><a href=\"https:\/\/github.com\/Microsoft\/vs-Dockerfiles\">VS Build Tools Dockerfile samples<\/a><\/span> available. Clone that repository locally. There you will find a directory for native-desktop that contains the files we will use as our starting point. If you open that Dockerfile you will see the following line within.<\/p>\n<pre>--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended \\<\/pre>\n<p>That line adds the VCTools workload and additional recommended components that today include CMake and the current Windows SDK. This is a smaller installation than our other sample that includes support for building managed and native projects. To learn more about how you can find the components you need see our <span><a href=\"http:\/\/aka.ms\/vs\/workloads\">additional workloads and components<\/a><\/span> documentation.<\/p>\n<p>Open PowerShell in the native-desktop directory or this repo and build the Docker image.<\/p>\n<pre>docker build -t buildtools2017native:latest -m 2GB .<\/pre>\n<p>The first time you build the image it will pull down the windowsservercore image, download the build tools, and install them into a local container image.<\/p>\n<p>When this is done you can see the images available locally.<\/p>\n<pre>docker images\nREPOSITORY\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0TAG\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0IMAGE ID\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 CREATED\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0SIZE\nBuildtools2017native\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 latest\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a04ff1cd971254 \u00a0\u00a03 minutes ago\u00a0\u00a0 14.9GB\nBuildtools2017\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0latest\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 325048ba2240\u00a0\u00a0 4 hours ago\u00a0\u00a0\u00a0\u00a0 22.4GB\nmicrosoft\/dotnet-framework 3.5-sdk-windowsservercore-1709 7d89a4baf66c\u00a0 \u00a03 weeks ago\u00a0\u00a0\u00a0\u00a0 13.2GB\n<\/pre>\n<p>While our buildtoolsmsvc image is large, it is significantly smaller than the VS Build Tools image that includes managed support. Note that these image sizes include the base image so they can be deceiving in terms of actual disk space used.<\/p>\n<h2>Trying it all out<\/h2>\n<p>Let\u2019s test out our build tools container using a simple little program. Create a new Windows Console Application project in Visual Studio. Add iostream and write out a hello world message as so.<\/p>\n<pre>#include \"stdafx.h\"\n#include &lt;iostream&gt;\nusing namespace std;\nint main()\n{\n  cout &lt;&lt; \"I was built in a container...\" &lt;&lt; endl;\n}\n<\/pre>\n<p>We are going to want to deploy this in a future post to a Windows Nano Server container so change the platform target to x64. Go to your project properties and under C\/C++ change the Debug Information Format to C7 compatible.<\/p>\n<p>Now we are going to create a build container for our project. Note this line in the Dockerfile we used to create our buildtoolsmsvc image.<\/p>\n<pre>ENTRYPOINT C:\\BuildTools\\Common7\\Tools\\VsDevCmd.bat &amp;&amp;<\/pre>\n<p>The &amp;&amp; in that line allows us to pass parameters in when we create a container using this image. Here we will use that to pass in the msbuild command with the options necessary to build our solution. When we start our container for the first time we will map our local source into a directory in the container using the -v option. We will also give the container a name using &#8211;name to remember what it is for later. That also makes it easier to run again as we update our source code.<\/p>\n<pre>docker run -v C:\\source\\ConsoleApplication1:c:\\ConsoleApplication1 --name ConsoleApplication1 buildtoolsmsvc msbuild c:\\ConsoleApplication1\\ConsoleApplication1.sln \/p:Configuration=Debug \/p:Platform=x64<\/pre>\n<p>This will spin up a container, use msbuild to build our solution, then exit, and stop the container. You should see output from this process as it runs. Since we mapped to our local volume you will find the build output under your solution directory under x64\\Debug. You can run ConsoleApplication1.exe from there and you\u2019ll see the output<\/p>\n<pre>I was built in a container...<\/pre>\n<p>As you change your sources you can run the container again by running this command (omit the -a attach option if you don\u2019t need to see the output from within the container).<\/p>\n<pre>docker start -a ConsoleApplication1<\/pre>\n<h2>Conclusion<\/h2>\n<p>This has gotten us a working MSVC toolset in an isolated, easy-to-use Docker container. You can now spin up additional containers for different projects using the approach outlined above. The disk space used by additional containers using the same base image is miniscule compared to spinning up VMs to get isolated build environments.<\/p>\n<p>In a future post we\u2019ll cover how to take the build output from this process, run it in a container, then attach to the process in the container and debug it.<\/p>\n<p>If you are using containers or doing cloud development with C++ we would love to hear from you. We wouldd appreciate it if you could take a few minutes to take our <span><a href=\"https:\/\/www.surveymonkey.com\/r\/W35QZCF\">C++ cloud and container development survey<\/a><\/span>. This will help us focus on topics that are important to you on the blog and in the form of product improvements.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Containers encapsulate the runtime environment of an application: the file system, environment settings, and virtualized OS are bundled into a package. Docker containers have changed the way we think about build and test environments since they were introduced five years ago. Visual Studio\u2019s setup and install expert, Heath Stewart, blogs regularly about how to install [&hellip;]<\/p>\n","protected":false},"author":677,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[292],"tags":[],"class_list":["post-20395","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-containers"],"acf":[],"blog_post_summary":"<p>Containers encapsulate the runtime environment of an application: the file system, environment settings, and virtualized OS are bundled into a package. Docker containers have changed the way we think about build and test environments since they were introduced five years ago. Visual Studio\u2019s setup and install expert, Heath Stewart, blogs regularly about how to install [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/20395","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/677"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=20395"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/20395\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=20395"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=20395"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=20395"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}