{"id":711,"date":"2022-10-29T12:20:18","date_gmt":"2022-10-29T20:20:18","guid":{"rendered":"https:\/\/www.nathanbak.com\/?p=711"},"modified":"2026-01-02T19:59:39","modified_gmt":"2026-01-03T03:59:39","slug":"getting-local-address-in-go","status":"publish","type":"post","link":"https:\/\/nathanbak.com\/?p=711","title":{"rendered":"Getting local address in Go"},"content":{"rendered":"\n<p>Awhile ago I had some tests that would spin up a server and then hit some &#8220;localhost:8080&#8221; endpoints and verify the responses.  The tests worked great in my IDE, but when the tests were invoked as a step during a Docker build, they could not find the server.  This post is about how I got my tests to run within a Docker container.<\/p>\n\n\n\n<p>There are a variety of ways to get the local address in a Docker container, but many of the solutions I found online involved running one or more command line utilities and I wanted something that &#8220;just worked&#8221; in Go.  After various kicking and swearing (and searching), this is what I came up with:<\/p>\n\n\n\n<pre class=\"wp-block-code\">\n\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;width:435px;height:300px;\"><div class=\"text codecolorer\">package main<br \/>\n<br \/>\nimport (<br \/>\n&nbsp; &nbsp; &quot;fmt&quot;<br \/>\n&nbsp; &nbsp; &quot;net&quot;<br \/>\n&nbsp; &nbsp; &quot;os&quot;<br \/>\n)<br \/>\n<br \/>\nfunc main() {<br \/>\n&nbsp; &nbsp; fmt.Println(getLocalAddress())<br \/>\n}<br \/>\n<br \/>\nfunc getLocalAddress() (string, error) {<br \/>\n&nbsp; &nbsp; var address string<br \/>\n&nbsp; &nbsp; _, err := os.Stat(&quot;\/.dockerenv&quot;) \/\/ 1<br \/>\n&nbsp; &nbsp; if err == nil {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; conn, err := net.Dial(&quot;udp&quot;, &quot;8.8.8.8:80&quot;) \/\/ 2<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return address, err<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; }<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; defer conn.Close()<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; address = conn.LocalAddr().(*net.UDPAddr).IP.String() \/\/ 3<br \/>\n&nbsp; &nbsp; } else {<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; address = &quot;localhost&quot; \/\/ 4<br \/>\n&nbsp; &nbsp; }<br \/>\n&nbsp; &nbsp; return address, nil<br \/>\n}<\/div><\/div>\n\n<\/pre>\n\n\n\n<p>The above is a complete main.go which can be compiled and ran, but the most important piece is the getLocalAddress() function which returns the local address (or an error if something goes wrong, but I haven&#8217;t had problems).  Here are some of the key points of the code:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Checking if the &#8220;\/.dockerenv&#8221; file exists is an easy way to check if the code is running in a Docker container.<\/li><li>We create a net.Conn instance<\/li><li>I first tried using\n\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;width:435px;\"><div class=\"text codecolorer\">address = conn.LocalAddr().String()<\/div><\/div>\n\nto get the local IP address, but it included a port that I didn&#8217;t want.  Instead of doing string manipulation, I found  the returned LocalAddr was a pointer to a net.UDPAddr and so a simple casting provided easy access to the IP.<\/li><li>If not running in Docker, &#8220;localhost&#8221; is good enough.<\/li><\/ol>\n\n\n\n<p>And that&#8217;s about it.  When I have checked, the local IP address of the container has been in the 172.17.0.x range which I believe is a Docker default.  Since doing this, there haven&#8217;t been any problems running the test, but I&#8217;m not sure if this is an industrial strength solution suitable for production environments.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Awhile ago I had some tests that would spin up a server and then hit some &#8220;localhost:8080&#8221; endpoints and verify the responses. The tests worked great in my IDE, but when the tests were invoked as a step during a Docker build, they could not find the server. This post is about how I got &hellip; <a href=\"https:\/\/nathanbak.com\/?p=711\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Getting local address in Go&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[8,19],"class_list":["post-711","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-docker","tag-golang"],"_links":{"self":[{"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/posts\/711","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nathanbak.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=711"}],"version-history":[{"count":1,"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/posts\/711\/revisions"}],"predecessor-version":[{"id":713,"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/posts\/711\/revisions\/713"}],"wp:attachment":[{"href":"https:\/\/nathanbak.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=711"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nathanbak.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=711"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nathanbak.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=711"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}