{"id":2006,"date":"2022-02-11T14:26:26","date_gmt":"2022-02-11T18:26:26","guid":{"rendered":"https:\/\/lowtek.ca\/roo\/?p=2006"},"modified":"2022-02-19T09:59:41","modified_gmt":"2022-02-19T13:59:41","slug":"using-docker-to-isolate-development-environments","status":"publish","type":"post","link":"https:\/\/lowtek.ca\/roo\/2022\/using-docker-to-isolate-development-environments\/","title":{"rendered":"Using Docker to isolate development environments"},"content":{"rendered":"<p><a href=\"https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2022\/02\/contain-golang.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-2007\" src=\"https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2022\/02\/contain-golang-500x348.jpg\" alt=\"\" width=\"500\" height=\"348\" srcset=\"https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2022\/02\/contain-golang-500x348.jpg 500w, https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2022\/02\/contain-golang-1024x712.jpg 1024w, https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2022\/02\/contain-golang-768x534.jpg 768w, https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2022\/02\/contain-golang-1536x1068.jpg 1536w, https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2022\/02\/contain-golang-1200x835.jpg 1200w, https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2022\/02\/contain-golang.jpg 1567w\" sizes=\"auto, (max-width: 500px) 85vw, 500px\" \/><\/a>In terms of modern programming languages, I would pick <a href=\"https:\/\/go.dev\/\">golang<\/a> as a great language to use. To me, it feels a little bit like a modernized C and has a nice approach to building single file binaries. It has a module system, type safety and garbage collection.<\/p>\n<p>I really dislike the way that you install golang onto your system and the way you end up managing that install with environment variables and the like. It&#8217;s not a terrible install story, but I don&#8217;t like polluting my development laptop with cruft. <a href=\"https:\/\/go.dev\/doc\/manage-install\">Multiple versions<\/a> make this more annoying.<\/p>\n<p>Docker on the other hand, despite it&#8217;s <a href=\"https:\/\/www.cyberark.com\/resources\/threat-research-blog\/how-docker-made-me-more-capable-and-the-host-less-secure\">flaws<\/a>, is worth having installed. It allows you to run lots of different stuff without needing to make a big commitment about the install. So instead of re-imaging my machine to start fresh, I just purge the containers and start again. Another benefit is that it&#8217;s relatively easy for me to point someone else at my configuration and for them to re-use it nearly directly.<\/p>\n<p>Getting a docker image that will persist state and make it trivial to compile golang programs turns out to be very easy<\/p>\n<pre class=\"lang:default decode:true \"># First we create the image\r\ndocker create -it --name gobuild -v $PWD:\/data golang:1.17-bullseye bash\r\n\r\n# Now we will run\/attach to it by name\r\ndocker start -ai gobuild<\/pre>\n<p>A couple of things to note. I&#8217;m using a <a href=\"https:\/\/docs.docker.com\/storage\/volumes\/\">host mounted volume<\/a> &#8211; specifically the current directory that I issue the docker create in. From inside the container it is mapped to <code>\/data<\/code>. I&#8217;ve also named the container, making it easy for me to re-run\/attach to it for future compiles.<\/p>\n<p><strong>Edit<\/strong> &#8211; running with -u is a good idea to make docker run as the right user (you). This will mean that files created by that container on the mounted host volume are owned by you.<\/p>\n<pre class=\"lang:default decode:true \">docker create -it --name gobuild \\\r\n   -v $PWD:\/data -u $UID:`id -g` \\\r\n   golang:1.17-bullseye  bash<\/pre>\n<p>As an example, here is how I&#8217;d go about compiling a github project that is in golang.<\/p>\n<pre class=\"lang:default decode:true \">$ git clone https:\/\/github.com\/die-net\/http-tarpit\r\nCloning into 'http-tarpit'...\r\nremote: Enumerating objects: 122, done.\r\nremote: Counting objects: 100% (13\/13), done.\r\nremote: Compressing objects: 100% (12\/12), done.\r\nremote: Total 122 (delta 0), reused 10 (delta 0), pack-reused 109\r\nReceiving objects: 100% (122\/122), 35.08 KiB | 394.00 KiB\/s, done.\r\nResolving deltas: 100% (52\/52), done.\r\n$ cd http-tarpit\r\n$ docker create -it --name gobuild -v $PWD:\/data golang:1.17-bullseye bash\r\n7ba9d1a8e367e4cadbc77bfbe69244c1ceca30a96134cc817e54ac3b4a8f39c2\r\n$ docker start -ai gobuild\r\nroot@7ba9d1a8e367:\/go# cd \/data\r\nroot@7ba9d1a8e367:\/data# go build\r\nroot@7ba9d1a8e367:\/data# exit\r\nexit\r\n$ ls -l http-tarpit \r\n-rwxr-xr-x 1 root root 6224123 Feb 11 13:14 http-tarpit\r\n<\/pre>\n<p>How slick is that? My development machine needs docker and git installed. The rest of this environment is entirely inside the docker container.<\/p>\n<p>Let me now demonstrate persistence of the container from run to run.<\/p>\n<pre class=\"lang:default decode:true \">$ docker start -ai gobuild\r\nroot@7ba9d1a8e367:\/go# nmap\r\nbash: nmap: command not found\r\nroot@7ba9d1a8e367:\/go# apt update; apt install nmap\r\n\r\n[...install noise...]\r\n\r\nroot@7ba9d1a8e367:\/go# which nmap\r\n\/usr\/bin\/nmap\r\nroot@7ba9d1a8e367:\/go# exit\r\nexit\r\n$ docker start -ai gobuild\r\nroot@7ba9d1a8e367:\/go# which nmap\r\n\/usr\/bin\/nmap\r\nroot@7ba9d1a8e367:\/go# \r\nexit\r\n<\/pre>\n<p>Thus if I happen to need a utility which isn&#8217;t installed in the base golang bullseye image, it&#8217;s easy for me to install. Also, from run to run &#8211; I have persistence of the changes I&#8217;ve made to my named image.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In terms of modern programming languages, I would pick golang as a great language to use. To me, it feels a little bit like a modernized C and has a nice approach to building single file binaries. It has a module system, type safety and garbage collection. I really dislike the way that you install &hellip; <a href=\"https:\/\/lowtek.ca\/roo\/2022\/using-docker-to-isolate-development-environments\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Using Docker to isolate development environments&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,12],"tags":[],"class_list":["post-2006","post","type-post","status-publish","format-standard","hentry","category-computing","category-how-to"],"_links":{"self":[{"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/posts\/2006","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/comments?post=2006"}],"version-history":[{"count":4,"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/posts\/2006\/revisions"}],"predecessor-version":[{"id":2012,"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/posts\/2006\/revisions\/2012"}],"wp:attachment":[{"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/media?parent=2006"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/categories?post=2006"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/tags?post=2006"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}