<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bruce MacKenzie</title>
    <description>The latest articles on DEV Community by Bruce MacKenzie (@bruc3mackenzi3).</description>
    <link>https://dev.to/bruc3mackenzi3</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F470169%2F42e14e92-3a02-4f81-affa-2b07036224a4.jpeg</url>
      <title>DEV Community: Bruce MacKenzie</title>
      <link>https://dev.to/bruc3mackenzi3</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bruc3mackenzi3"/>
    <language>en</language>
    <item>
      <title>Managing Multiple Git Accounts on a single machine</title>
      <dc:creator>Bruce MacKenzie</dc:creator>
      <pubDate>Sat, 15 Jul 2023 18:44:19 +0000</pubDate>
      <link>https://dev.to/bruc3mackenzi3/working-with-multiple-git-accounts-31km</link>
      <guid>https://dev.to/bruc3mackenzi3/working-with-multiple-git-accounts-31km</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Suppose you want to work with git repositories whose remotes are authenticated with different user accounts.  Maybe you have work and personal GitHub accounts, or you work with repositories from multiple hosting services like GitLab or Sourcehut.&lt;/p&gt;

&lt;p&gt;The simplest solution is to clone the repositories using HTTPS (instead of SSH). But who wants to enter a username and password for every authenticated command? This post will demonstrate an SSH-based configuration for seamless operations.&lt;/p&gt;

&lt;p&gt;Ready?  Let's get into it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Your remote git accounts (e.g. with GitHub or GitLab) are configured for SSH authentication, and your machine is configured for SSH authentication with one of these accounts.&lt;/p&gt;

&lt;p&gt;If not, refer to &lt;a href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh"&gt;GitHub's website for setup instructions&lt;/a&gt;, or the instructions provided by the hosting service of your choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  SSH Key Setup
&lt;/h2&gt;

&lt;p&gt;SSH keys are stored in &lt;code&gt;~/.ssh/&lt;/code&gt; as public/private key pairs. By default the files are named after the encryption algorithm; for RSA you will find:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;id_rsa
id_rsa.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or for ed25519:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;id_ed25519
id_ed25519.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the second pair of keys you wish to authenticate with to &lt;code&gt;~/.ssh/&lt;/code&gt;. Give them a unique name to set them apart from the first pair, e.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;id_rsa -&amp;gt; id_rsa_gitlab
id_rsa.pub -&amp;gt; id_rsa_gitlab.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set correct file permissions for private and public key files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;600 id_rsa_gitlab &lt;span class="c"&gt;# only owner can read/write&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;644 id_rsa_gitlab.pub &lt;span class="c"&gt;# owner can read/write, everyone else can read&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Git Configuration at Repository Level
&lt;/h2&gt;

&lt;p&gt;This setup is the simplest method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config core.sshCommand &lt;span class="s2"&gt;"ssh -o IdentitiesOnly=yes -i ~/.ssh/id_rsa_gitlab -F /dev/null"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you only require alternate authentication with a few repositories, this may be good enough.  But if you want a single configuration that works across all repos in your user environment, continue reading below.&lt;/p&gt;

&lt;h2&gt;
  
  
  SSH Config Entry
&lt;/h2&gt;

&lt;p&gt;To make this work with a single configuration in your user environment, we will use the SSH config.&lt;/p&gt;

&lt;p&gt;Make SSH aware of the additional keys by editing &lt;code&gt;~/.ssh/config&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the file doesn't exist create it first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; ~/.ssh/config
&lt;span class="nb"&gt;chmod &lt;/span&gt;600 ~/.ssh/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add &lt;code&gt;Host&lt;/code&gt; entries to the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# GitHub account
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa

# GitLab account
Host gitlab.com
HostName gitlab.com
User git
IdentityFile ~/.ssh/id_rsa_gitlab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When performing SSH authentication, the correct keys are determined by matching the config entry with the user and host names in the repository's remote URL.&lt;/p&gt;

&lt;p&gt;To confirm an existing repository is configured to use SSH check the remote origin URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To change the remote URL run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote set-url origin git@github.com:&amp;lt;user&amp;gt;/&amp;lt;repository&amp;gt;.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To do this with a new repository clone with the SSH - not HTTPS - URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github.com:&amp;lt;user&amp;gt;/&amp;lt;repository&amp;gt;.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github.com:bruc3mackenzi3/go-microservice-template.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Entries for the Same Host
&lt;/h3&gt;

&lt;p&gt;The example above will not work if both accounts are with the same host.  For this a &lt;em&gt;host alias&lt;/em&gt; is required:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Work GitHub account
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa

# Personal GitHub account
Host github.com_personal
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;github.com_personal&lt;/code&gt; is just an alias, anything will work here.&lt;/p&gt;

&lt;p&gt;Now, with one of the commands provided above, clone or edit the remote origin URL to use the alias.  E.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git@github.com_personal:bruc3mackenzi3/go-microservice-template.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Optional - Configure User Name and Email
&lt;/h2&gt;

&lt;p&gt;It's also a good idea to set the user name and email for the repository. Even though this isn't used in the authentication process, this information shows up in commits and is used by GitHub to associate with a user account. Since you're reading this article, chances are your global Git configuration is set to another account.&lt;/p&gt;

&lt;p&gt;Before changing, you can check the current value by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config user.email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To set a different email:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config user.email &amp;lt;your-github-account-email&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note this sets &lt;code&gt;user.email&lt;/code&gt; in the repository configration file, &lt;code&gt;.git/config&lt;/code&gt;. If you saw a different email prior, chances are it was set in the global configuration and is still present. It is this email that will continue to be used in other repositories, unless they also overwrite the global &lt;code&gt;user.email&lt;/code&gt; value with their own configuration.&lt;/p&gt;

&lt;p&gt;You can confirm this by getting all values for an option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--get-all&lt;/span&gt; user.email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeat the same for username with the same commands, by replacing &lt;code&gt;user.email&lt;/code&gt; with &lt;code&gt;user.name&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verifying the configuration works
To verify the setup is working, we need to perform a git operation that requires priveledged access to a repository. If you went with the cloning option in section #3, and that repo is private then you've already confirmed it's working! Another way to verify is by pushing a new branch:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; test-ssh-config
git push &lt;span class="nt"&gt;--set-upstream&lt;/span&gt; origin test-ssh-config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;To explore this topic further, you can check out &lt;a href="https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-your-personal-account/managing-multiple-accounts"&gt;GitHub documentation on managing multiple accounts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thank you for checking out this post on improving development workflows with git repositories from different user accounts.  I hope you find this configuration handy in creating a more seamless development experience.  Happy &lt;code&gt;git push&lt;/code&gt;'ing!&lt;/p&gt;

</description>
      <category>git</category>
      <category>ssh</category>
      <category>github</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Developing and Deploying Microservices with Go</title>
      <dc:creator>Bruce MacKenzie</dc:creator>
      <pubDate>Sun, 08 Jan 2023 17:27:16 +0000</pubDate>
      <link>https://dev.to/bruc3mackenzi3/developing-and-deploying-microservices-with-go-3ldo</link>
      <guid>https://dev.to/bruc3mackenzi3/developing-and-deploying-microservices-with-go-3ldo</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Entire books have been written on the subject of microservices.  This post will scratch the surface by exploring the key ingredients that go into development and deployment of microservices.  &lt;a href="https://github.com/bruc3mackenzi3/go-microservice-template" rel="noopener noreferrer"&gt;A demo microservice app&lt;/a&gt; will be used as a case study, presenting popular technologies to bring the concept into motion.&lt;/p&gt;

&lt;p&gt;Go is a popular language of choice for modern, service-based architectures.  The term &lt;em&gt;cloud native&lt;/em&gt; is often used to describe Go, but what does it mean?&lt;/p&gt;

&lt;p&gt;Go is a compiled language, meaning a Go program can be run on a target machine without the installation of dependencies.  A higher level language by comparison, like Java or Python, requires its runtime environment and all 3rd party dependencies be installed.  This has a number of drawbacks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Added complexity to the build process&lt;/li&gt;
&lt;li&gt;Built images have larger file size&lt;/li&gt;
&lt;li&gt;CICD pipelines, image builds, cloud deployments, etc all take longer to run&lt;/li&gt;
&lt;li&gt;All dependencies must be installed on target machines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A modern, compiled language like Go on the other hand has such advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dependencies are only required on the build machine&lt;/li&gt;
&lt;li&gt;A single, executable file is deployed to target machines which need only provide a compatible operating system&lt;/li&gt;
&lt;li&gt;The build machine can compile the program to run on different operating systems and CPU architectures, simply by specifying these as arguments to the compiler&lt;/li&gt;
&lt;li&gt;Compiled programs run faster, improving application performance and reducing infrastructure costs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Microservices in Action
&lt;/h2&gt;

&lt;p&gt;To get started building a Go microservice, head over to my Go Microservice Repository to explore the technologies I've integrated.  You can pick and choose certain technologies to apply to your own project, &lt;a href="https://github.com/bruc3mackenzi3/go-microservice-template/fork" rel="noopener noreferrer"&gt;or fork the repository&lt;/a&gt; to start a new project using it as a template.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technologies Used
&lt;/h3&gt;

&lt;p&gt;For a rundown of tools and frameworks used to bring a Go microservice to life, &lt;a href="https://github.com/bruc3mackenzi3/go-microservice-template#tech-stack" rel="noopener noreferrer"&gt;see the repo readme&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>community</category>
      <category>softwaredevelopment</category>
      <category>collaboration</category>
      <category>gratitude</category>
    </item>
    <item>
      <title>Debugging a Go Application Inside Docker Using VSCode</title>
      <dc:creator>Bruce MacKenzie</dc:creator>
      <pubDate>Wed, 03 Aug 2022 23:54:00 +0000</pubDate>
      <link>https://dev.to/bruc3mackenzi3/debugging-go-inside-docker-using-vscode-4f67</link>
      <guid>https://dev.to/bruc3mackenzi3/debugging-go-inside-docker-using-vscode-4f67</guid>
      <description>&lt;p&gt;The ability to debug is an important tool for a developer to keep in their toolbox.  While it's ideal to debug by running the application natively, there are scenarios where this either isn't possible or the issue must be reproduced in a particular environment.&lt;/p&gt;

&lt;p&gt;The required setup to debug a Go app running inside a Docker container is non-trivial.  In this post I will walk through the configuration to achieve this using VSCode and the &lt;a href="https://github.com/go-delve/delve" rel="noopener noreferrer"&gt;Delve debugger&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Consider this simple Go server app which listens on port 80 and has a simple handler at the &lt;code&gt;GET /hello&lt;/code&gt; endpoint:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/hello endpoint called"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hello&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server up and listening..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":80"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And the Dockerfile:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; golang:1.18-alpine&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; hello.go ./&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; GO111MODULE=off&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go build &lt;span class="nt"&gt;-o&lt;/span&gt; hello-app .

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; [ "./hello-app" ]&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;golang:1.18-alpine&lt;/code&gt; is the base image we'll build from&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WORKDIR /app&lt;/code&gt; declares the working directory; all relative paths referenced thereafter are from this location&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;COPY&lt;/code&gt; directive simply copies files from the host to the image being built&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RUN go build -o hello-app .&lt;/code&gt; compiles our program, producing the executable file &lt;code&gt;hello-app&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Since we are not working with Go Modules &lt;code&gt;ENV GO111MODULE=off&lt;/code&gt; is required to build our program correctly&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Finally, &lt;code&gt;CMD&lt;/code&gt; provides Docker with a run command for our app when the container is started&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Build, run, and query with these commands:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

docker build &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--tag&lt;/span&gt; hello-image
docker run &lt;span class="nt"&gt;--publish&lt;/span&gt; 80:80 &lt;span class="nt"&gt;--name&lt;/span&gt; hello-image hello-server
curl http://localhost/hello


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Note: Docker Compose is a more user-friendly tool for managing container lifecycle, but for the sake of simplicity I've decided to work with Docker directly.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Delve provides a server running in the Docker container which VSCode connects to in order to interact with the debugging session.&lt;/p&gt;

&lt;p&gt;This requires creating a new Dockerfile with modifications from the original.  We'll call this file &lt;code&gt;Dockerfile.debug&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; golang:1.18-alpine&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80 4000&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; hello.go ./&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 go &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-ldflags&lt;/span&gt; &lt;span class="s2"&gt;"-s -w -extldflags '-static'"&lt;/span&gt; github.com/go-delve/delve/cmd/dlv@latest

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; GO111MODULE=off&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 go build &lt;span class="nt"&gt;-gcflags&lt;/span&gt; &lt;span class="s2"&gt;"all=-N -l"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; hello-app .

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; [ "/go/bin/dlv", "--listen=:4000", "--headless=true", "--log=true", "--accept-multiclient", "--api-version=2", "exec", "/app/hello-app" ]&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There are a few differences here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We install the Delve package with &lt;code&gt;RUN CGO_ENABLED=0 go install...&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We've added the flag &lt;code&gt;-gcflags "all=-N -l"&lt;/code&gt; to the build command.  This is to disable inlining and optimizations that can interfere with debugging.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CMD&lt;/code&gt; is now running Delve, telling it to listen for connections on port 4000, and how to run our program&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also need a custom debug configuration for VSCode, stored in &lt;code&gt;.vscode/launch.json&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Remote Docker App",
            "type": "go",
            "request": "attach",
            "mode": "remote",
            "port": 4000,
            "host": "127.0.0.1"
        }
    ]
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Running the debug container requires slightly different commands:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

docker build &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--tag&lt;/span&gt; debug-image &lt;span class="nt"&gt;--file&lt;/span&gt; Dockerfile.debug
docker run &lt;span class="nt"&gt;--publish&lt;/span&gt; 80:80 &lt;span class="nt"&gt;--publish&lt;/span&gt; 4000:4000 &lt;span class="nt"&gt;--name&lt;/span&gt; debug-server debug-image


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;The non-standard filename &lt;code&gt;Dockerfile.debug&lt;/code&gt; must be explicitly referenced&lt;/li&gt;
&lt;li&gt;There is an additional port to publish, &lt;code&gt;4000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We use a different image tag and container name so we don't overwrite the original build

&lt;ul&gt;
&lt;li&gt;This speeds up build time when switching between the debug and standard environments&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;At this point we are ready to debug our program!  Go to the &lt;em&gt;Run and Debug tab&lt;/em&gt;, select &lt;code&gt;Remote Docker App&lt;/code&gt; and hit the Start Debugging play button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftoiiehe2ellxfo9lbee7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftoiiehe2ellxfo9lbee7.png" alt="VSCode 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set a breakpoint in our program's &lt;code&gt;hello()&lt;/code&gt; handler function by clicking on the margin to the left of the line number.&lt;/p&gt;

&lt;p&gt;Finally, &lt;code&gt;curl&lt;/code&gt; the server with the command provided earlier, and observe the debugger halting execution!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa4r2nt7c4pco3ezyr2tr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa4r2nt7c4pco3ezyr2tr.png" alt="VSCode 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With our program now running in a debugging session we've gained valuable visibility into runtime internals.  This greatly speeds up the feedback loop when trying to understand why our program isn't behaving the intended way.  Setting breakpoints and stepping through execution with a debugger is pretty seamless.  By contrast adding print statements, building, running, then calling the application is a much slower process.&lt;/p&gt;

&lt;p&gt;From here you're free to play around with the many debugger features VSCode offers:  Setting breakpoints, stepping line-by-line through execution with Debug Actions, Inspecting variables' values, and so on.&lt;/p&gt;

&lt;p&gt;Here are some references to check out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/docs/editor/debugging" rel="noopener noreferrer"&gt;Debugging with VSCode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;My &lt;a href="https://github.com/bruc3mackenzi3/go-microservice-template" rel="noopener noreferrer"&gt;Go Microservice App&lt;/a&gt; as a working example of this exercise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Comments and feedback about this tutorial are welcome.  If you worked through the example please share your experience with it.  Happy debugging!&lt;/p&gt;

</description>
      <category>go</category>
      <category>vscode</category>
      <category>docker</category>
      <category>delve</category>
    </item>
  </channel>
</rss>
