{"id":2607,"date":"2025-10-16T13:23:46","date_gmt":"2025-10-16T13:23:46","guid":{"rendered":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2025\/10\/16\/debug-docker-builds-with-visual-studio-code\/"},"modified":"2025-10-16T13:23:46","modified_gmt":"2025-10-16T13:23:46","slug":"debug-docker-builds-with-visual-studio-code","status":"publish","type":"post","link":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2025\/10\/16\/debug-docker-builds-with-visual-studio-code\/","title":{"rendered":"Debug Docker Builds with Visual Studio Code"},"content":{"rendered":"<p>Building Docker images is an important component of the software delivery pipeline for modern applications. It\u2019s how we package our apps and services so that they can be distributed to others and deployed to production. While the Dockerfile has long been the standard for defining container images, it is known to be challenging to make changes and debug when issues arise. It\u2019s currently a real <strong>pain to understand the build time state<\/strong> during the different stages of the build. What was the state of the ARG? Which files were copied into the image?<\/p>\n<p>Recently, we have been making updates to the Docker Build clients (<a href=\"https:\/\/github.com\/docker\/buildx\" target=\"_blank\">Buildx<\/a>) and our VS Code extension (<a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=docker.docker\" target=\"_blank\">Docker DX<\/a>) to improve the developer experience when using Docker. Today, we are sharing the next stage of that process with the introduction of Build Debugging in VS Code and Docker Build.<\/p>\n<p>With the new debugging feature in Buildx from Docker, you will be able to reduce the time you spend fixing your Docker builds. In this post, you\u2019ll learn how to configure the Buildx debugger in Visual Studio Code, step through a build and inspect variables and the image\u2019s file system, and open a shell inside the image being built. Finally, you will learn a little about the debugger\u2019s implementation and how it can be integrated into other editors.<\/p>\n\n<h2 class=\"wp-block-heading\">Configuring Visual Studio Code<\/h2>\n<p>To start debugging Dockerfiles in Visual Studio Code:<\/p>\n<p>Install the latest version of the <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=docker.docker\" target=\"_blank\">Docker DX extension<\/a>.<\/p>\n<p>Update to the latest version of Docker Desktop to ensure you have the latest Docker build tooling.<\/p>\n<p>Run docker buildx version and verify that your Buildx is at least version 0.29.x.<\/p>\n<h3 class=\"wp-block-heading\">Creating a Launch Configuration<\/h3>\n<p>Open up your Dockerfile and open the Run and Debug view in Visual Studio Code. If you do not have any launch configurations, you will see something like the following.<\/p>\n<div class=\"wp-block-ponyo-image\"><\/div>\n<p>Figure 1: Run and Debug view opened in Visual Studio Code with no launch configurations defined.<\/p>\n\n<p>Click on the \u201ccreate a launch.json file\u201d hyperlink. If you have launch configurations, open up your launch.json file by clicking on the cog icon in the top right hand corner of the Run and Debug view.<\/p>\n<p>In your launch.json file, create a new launch configuration for debugging your Docker build. You can use the sample below to get started. For a full description of the various attributes in a launch configuration, see <a href=\"https:\/\/github.com\/docker\/vscode-extension\/blob\/main\/DEBUGGING.md#debugging-with-a-launch-configuration\" target=\"_blank\">here<\/a>.<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n{<br \/>\n  &#8220;name&#8221;: &#8220;Docker: Build&#8221;,<br \/>\n  &#8220;type&#8221;: &#8220;dockerfile&#8221;,<br \/>\n  &#8220;request&#8221;: &#8220;launch&#8221;,<br \/>\n  &#8220;dockerfile&#8221;: &#8220;Dockerfile&#8221;,<br \/>\n  &#8220;contextPath&#8221;: &#8220;${workspaceFolder}&#8221;<br \/>\n}\n<\/div>\n<h3 class=\"wp-block-heading\">Adding a Breakpoint<\/h3>\n<p>Now that you have completed setting up your launch configuration, let\u2019s add a breakpoint to our Dockerfile. Place a breakpoint next to one of your RUN instructions by clicking in the editor\u2019s left margin or by pressing F9. A circle should appear to indicate that a breakpoint has been added.<\/p>\n<h3 class=\"wp-block-heading\">Launching the Debugger<\/h3>\n<p>We are now ready to start the debugger. Select the launch configuration you created and then hit F5. The build should pause at the RUN line where you placed the breakpoint.<\/p>\n<div class=\"wp-block-ponyo-image\"><\/div>\n<p>Figure 2: Docker build suspended by a breakpoint in Visual Studio Code.<\/p>\n\n<h2 class=\"wp-block-heading\">Debugging Features<\/h2>\n<p>We will now walk you through the three different features that the Buildx Debugger provides.<\/p>\n<h3 class=\"wp-block-heading\">Inspecting Variables<\/h3>\n<p>When a build is in a suspended state, you can look at any variables that may have been defined. In this example, by looking at the executed command\u2019s workdir value on the left-hand side, we can now see that the command is not being run in the right folder as we had copied the contents into \/app. We can fix this by adding WORKDIR \/app before the RUN line. Also note that we can view variables that have been defined by our image and the base image as seen by VAR and NODE_VERSION.<\/p>\n<div class=\"wp-block-ponyo-image\"><\/div>\n<p>Figure 3: Docker build encounters an error and is suspended by the debugger instead of terminating.<\/p>\n<h3 class=\"wp-block-heading\">File Explorer<\/h3>\n<p>In addition to inspecting variables, you can also look at the structure of the file system to see what is already there and what you have copied in. For text files, you can also see its file content as shown in the file\u2019s data field.<\/p>\n<div class=\"wp-block-ponyo-image\"><\/div>\n<p>Figure 4: View the file system of the Docker image being built.<\/p>\n<h3 class=\"wp-block-heading\">Interactive Debugging<\/h3>\n<p>Creating the right Dockerfile is often an iterative process. Part of this is usually because the host system you are developing on shares few similarities with the image you are building. Consider the differences between running Ubuntu locally but trying to build an Alpine Linux image. The small differences in package names creates a lot of back and forth between your editor and your browser as you search for the right name. You add a line here and then maybe comment another line somewhere else before running docker build again to just hope for the best.<\/p>\n<p>This iterative process can now be streamlined with the help of the debugger. When your build is in a suspended state, open the Debug Console view and then place your cursor in the input field at the bottom. Type in exec and then hit the enter key. The Terminal view should now open with a shell that is attached to the image that is being built.<\/p>\n<div class=\"wp-block-ponyo-image\"><\/div>\n<p>Figure 5: Use the Debug Console to open a shell into the Docker image being built by running exec.<\/p>\n<div class=\"wp-block-ponyo-image\"><\/div>\n<p>Figure 6: The Docker image that is being built can now be accessed and inspected with a terminal.<\/p>\n<p>This feature is a game changer as you can now easily open the image of a Dockerfile at any given step and inspect its content and run commands for testing. Previously, we would have to comment everything after the buggy line, build the Docker image, and then manually run and open a shell into the image. All of that is now condensed into adding a breakpoint in your editor and starting a debug session!<br \/>Keep in mind that <strong>none<\/strong> of the changes you make in the terminal are persisted so this is purely for experimentation. In the figure below, we can see that a file was created when the debugger was paused at line 3. When the debugger was advanced to line 4, the file disappeared.<\/p>\n<div class=\"wp-block-ponyo-image\"><\/div>\n<p>Figure 7: Changes to the Docker image inside the exec terminal will be reset when the debugger steps to another line.<\/p>\n<h2 class=\"wp-block-heading\">Integrations powered by an Open Specification<\/h2>\n<p>Just like our work with the <a href=\"https:\/\/github.com\/docker\/docker-language-server\" target=\"_blank\">Docker Language Server<\/a> that implements the <a href=\"https:\/\/microsoft.github.io\/language-server-protocol\/\" target=\"_blank\">Language Server Protocol<\/a>, the Buildx debugger is built on open standards as it implements the <a href=\"https:\/\/microsoft.github.io\/debug-adapter-protocol\" target=\"_blank\">Debug Adapter Protocol<\/a> which means that you can debug Dockerfile builds with any editor that supports the protocol. Besides Visual Studio Code, we also provide an official plugin for <a href=\"https:\/\/github.com\/docker\/nvim-dap-docker\" target=\"_blank\">Neovim<\/a>. For the JetBrains users out there, we have verified that it integrates well with the <a href=\"https:\/\/plugins.jetbrains.com\/plugin\/23257-lsp4ij\/\" target=\"_blank\">LSP4IJ plugin<\/a>. If your favourite editor supports the Debug Adapter Protocol, there should be a way for the Buildx debugger to integrate with it.<\/p>\n<h2 class=\"wp-block-heading\">Thank You<\/h2>\n<p>We want to take this opportunity to thank Kohei Tokunaga (<a href=\"https:\/\/github.com\/ktock\" target=\"_blank\">ktock<\/a>) for his ideas and initial work around this feature. The contributions he provided to Buildx gave us a great foundation for us to build out and complete this feature. This release would not have been possible without his help. Thank you, Kohei!<\/p>\n<h2 class=\"wp-block-heading\">Next Steps<\/h2>\n<p>Download the <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=docker.docker\" target=\"_blank\">Docker DX extension<\/a> and try out the new debugging feature.<\/p>\n<p>Share feedback and issues with us in our GitHub repositories for <a href=\"https:\/\/github.com\/docker\/vscode-extension\/issues\" target=\"_blank\">Docker DX<\/a> and <a href=\"https:\/\/github.com\/docker\/buildx\/issues\" target=\"_blank\">Buildx<\/a>.<\/p>\n<p>You can also submit feedback through the <a href=\"https:\/\/docs.docker.com\/desktop\/troubleshoot-and-support\/feedback\" target=\"_blank\">Docker feedback<\/a> page.<\/p>\n<h2 class=\"wp-block-heading\">Learn More<\/h2>\n<p>Setup the Buildx debugger in Neovim with <a href=\"https:\/\/github.com\/docker\/nvim-dap-docker\" target=\"_blank\">nvim-dap-docker<\/a>.<\/p>\n<p>Setup the Buildx debugger in a JetBrains editor with the <a href=\"https:\/\/github.com\/redhat-developer\/lsp4ij\/blob\/main\/docs\/dap\/user-defined-dap\/buildx-dockerfile.md\" target=\"_blank\">LSP4IJ plugin<\/a>.<\/p>\n<p>Read the Buildx documentation about our <a href=\"https:\/\/github.com\/docker\/buildx\/blob\/master\/docs\/dap.md\" target=\"_blank\">implementation of DAP<\/a> and <a href=\"https:\/\/github.com\/docker\/buildx\/blob\/master\/docs\/reference\/buildx_dap_build.md\" target=\"_blank\">configuring launches<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Building Docker images is an important component of the software delivery pipeline for modern applications. It\u2019s how we package our [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[4],"tags":[],"class_list":["post-2607","post","type-post","status-publish","format-standard","hentry","category-docker"],"_links":{"self":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/2607","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/comments?post=2607"}],"version-history":[{"count":0,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/2607\/revisions"}],"wp:attachment":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/media?parent=2607"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/categories?post=2607"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/tags?post=2607"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}