<?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: Jonathan Boudreau</title>
    <description>The latest articles on DEV Community by Jonathan Boudreau (@aghost7).</description>
    <link>https://dev.to/aghost7</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%2F1027%2F6957411.gif</url>
      <title>DEV Community: Jonathan Boudreau</title>
      <link>https://dev.to/aghost7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aghost7"/>
    <language>en</language>
    <item>
      <title>Differences Between MacOS and Linux Scripting</title>
      <dc:creator>Jonathan Boudreau</dc:creator>
      <pubDate>Thu, 22 Oct 2020 00:00:33 +0000</pubDate>
      <link>https://dev.to/aghost7/differences-between-macos-and-linux-scripting-74d</link>
      <guid>https://dev.to/aghost7/differences-between-macos-and-linux-scripting-74d</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@sharonmccutcheon?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Sharon McCutcheon&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/document?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I often hear people saying MacOS and Linux are similar. I would like to propose that they are in fact very different.&lt;/p&gt;

&lt;p&gt;But why does this matter? Well, for one, I write a lot of code for CI (Continuous Integration). The differences are big enough to make it challenging to re-use more complex scripts locally and in CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shell
&lt;/h2&gt;

&lt;p&gt;MacOS recently changed its default shell to zsh. Before this, it was using a decade old release of bash.&lt;/p&gt;

&lt;p&gt;Now, nothing is stopping you from installing the latest version of bash. If you're writing scripts for your team it is unlikely you will have much control over that however.&lt;/p&gt;

&lt;h2&gt;
  
  
  Package Manager
&lt;/h2&gt;

&lt;p&gt;This is probably the most significant difference with MacOS and Linux when it comes to scripting automation. Most people on Mac rely on Homebrew, while most servers on Linux use apt. Not only is it different to install packages, but so is adding new software sources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker
&lt;/h2&gt;

&lt;p&gt;Since Docker for Mac runs in a virtual machine (using &lt;a href="https://github.com/linuxkit/linuxkit"&gt;linuxkit&lt;/a&gt;), there are significant differences with running containers on it. &lt;/p&gt;

&lt;p&gt;Volumes (bind mounts) have poorer performance. This may limit how many things you can throw at compose if your project is a large codebase.&lt;/p&gt;

&lt;p&gt;File permissions map differently from the container to the host. Linux may use &lt;a href="https://www.man7.org/linux/man-pages/man5/subuid.5.html"&gt;subordinate uids&lt;/a&gt; and gids, whilst MacOS maps all users to one uid/gid on the host.&lt;/p&gt;

&lt;h2&gt;
  
  
  find
&lt;/h2&gt;

&lt;p&gt;MacOS uses a different implementation of find. Linux has a couple of extra options, and the search path is optional.&lt;/p&gt;

&lt;h2&gt;
  
  
  netstat
&lt;/h2&gt;

&lt;p&gt;Similarly to &lt;code&gt;find&lt;/code&gt;, &lt;code&gt;netstat&lt;/code&gt; on Linux is a different implementation altogether. For certain tasks you will need to use &lt;code&gt;lsof&lt;/code&gt; when on MacOS. The output for &lt;code&gt;lsof&lt;/code&gt; is also different, so you will need to implement different parsing code for each operating system.&lt;/p&gt;

&lt;h2&gt;
  
  
  ifconfig
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ifconfig&lt;/code&gt; is deprecated on Linux. It is recommended to write new scripts with &lt;code&gt;ip&lt;/code&gt; instead. Since MacOS doesn't have &lt;code&gt;ip&lt;/code&gt;, you're stuck with writing an implementation for each operating system.&lt;/p&gt;

&lt;h2&gt;
  
  
  xargs
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;xargs&lt;/code&gt;, which is used for piping arguments to another command, works slightly differently on MacOS. If the previous command has no output, &lt;code&gt;xargs&lt;/code&gt; on MacOS won't run the command.&lt;/p&gt;

&lt;h2&gt;
  
  
  init
&lt;/h2&gt;

&lt;p&gt;MacOS uses launchd, which accepts an xml configuration for the definition of new services. Most modern Linux distributions rely on systemd, which has a INI-like configuration format.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Closing
&lt;/h2&gt;

&lt;p&gt;Did you run into other discrepancies between the two operating systems? What are some of the best practices you follow to write portable scripts?&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>linux</category>
      <category>macos</category>
    </item>
    <item>
      <title>Why is Linux Not More Popular on the Desktop?</title>
      <dc:creator>Jonathan Boudreau</dc:creator>
      <pubDate>Sun, 13 Jan 2019 17:06:24 +0000</pubDate>
      <link>https://dev.to/aghost7/why-is-linux-not-more-popular-on-the-desktop-40ln</link>
      <guid>https://dev.to/aghost7/why-is-linux-not-more-popular-on-the-desktop-40ln</guid>
      <description>&lt;p&gt;&lt;em&gt;Picture taken from &lt;a href="https://commons.wikimedia.org/wiki/File:Penguins_walking_-Moltke_Harbour,_South_Georgia,_British_overseas_territory,_UK-8.jpg"&gt;wikipedia&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are issues when it comes to Linux being more broadly adopted on the desktop. What are the main issues you think and how can they be addressed?&lt;/p&gt;

&lt;p&gt;I think that the big issue with Linux is fragmentation. This has been especially an issue when it comes to developers publishing games on Linux.&lt;/p&gt;

&lt;p&gt;The solution to this issue are cross-distribution installers like &lt;a href="https://snapcraft.io/"&gt;Snap&lt;/a&gt;, &lt;a href="https://appimage.org/"&gt;AppImage&lt;/a&gt; and &lt;a href="https://www.flatpak.org/"&gt;Flatpak&lt;/a&gt;. Every application has its own set of libraries, meaning they do not depend on distribution-specific packages.&lt;/p&gt;

&lt;p&gt;Another issue I believe is momentum. There's some outdated opinion on how well Linux works on the desktop.&lt;/p&gt;

&lt;p&gt;Defeating the momentum will require more effort on the PR front. I don't see this being something that will just fix itself with time.&lt;/p&gt;

&lt;p&gt;Thoughts?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>linux</category>
      <category>opensource</category>
    </item>
    <item>
      <title>My Ubuntu Desktop</title>
      <dc:creator>Jonathan Boudreau</dc:creator>
      <pubDate>Fri, 28 Dec 2018 16:00:58 +0000</pubDate>
      <link>https://dev.to/aghost7/my-ubuntu-desktop-4boa</link>
      <guid>https://dev.to/aghost7/my-ubuntu-desktop-4boa</guid>
      <description>&lt;p&gt;I recently reinstalled Ubuntu on my personal laptop. I found some pleasant surprises in doing so, and I wanted to share what I've got going.&lt;/p&gt;

&lt;p&gt;Note: This is my current setup for Ubuntu 18.10. Your mileage may vary if on LTS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hotkeys
&lt;/h2&gt;

&lt;p&gt;The default hotkeys in GNOME are pretty good out of the box. Here are some that I use on a regular basis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;alt + tab: Switch of program.&lt;/li&gt;
&lt;li&gt;alt + backtick: Switch to a window which belongs to the same program.&lt;/li&gt;
&lt;li&gt;ctrl + alt + arrow: Move to a different workspace. Workspaces in GNOME can
only go up or down.&lt;/li&gt;
&lt;li&gt;ctrl + alt + shift + arrow: Move current window to a different workspace.&lt;/li&gt;
&lt;li&gt;ctrl + alt + t: open gnome terminal&lt;/li&gt;
&lt;li&gt;meta (windows button): Open the global menu, I use it to search for programs
instead of relying on the mouse.&lt;/li&gt;
&lt;li&gt;meta + left or right: move the window left or right.&lt;/li&gt;
&lt;li&gt;meta + up: make the window take up the entire viewport.&lt;/li&gt;
&lt;li&gt;shift + printscr: Select a region to do a screen capture.&lt;/li&gt;
&lt;li&gt;alt + printscr: Do a screen capture of the entire focused window.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's really just two things that bother me with the default hotkeys. First, program switching is for all programs, across workspaces. This isn't an issue if you don't normally have a lot of programs open, but I tend to multitask and prefer keeping things isolated between workspaces. Second, I like to switch of workspaces using using indexes (e.g., &lt;code&gt;super+2&lt;/code&gt; to switch to workspace number 2). This is something I got used to from back when had i3wm as part of my main desktop environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limiting application switching to workspaces
&lt;/h3&gt;

&lt;p&gt;To make this customization we will need the DConf Editor. It can be installed through the Ubuntu Software program. Simply open up "Ubuntu Software", search for "Dconf" and install the "Dconf Editor":&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzfn5q5rnu5ojhnk8a6qc.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzfn5q5rnu5ojhnk8a6qc.png" alt="dconf-editor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After opening the DConf Editor, navigate to the path &lt;code&gt;org -&amp;gt; gnome -&amp;gt; shell -&amp;gt; app-switcher -&amp;gt; current-workspace-only&lt;/code&gt;. Disable the "Use default value" option and set "Custom value" to "true".&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzcuohdcgk32guli4by2o.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzcuohdcgk32guli4by2o.png" alt="workspace-switcher"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Changing of workspace using indexes
&lt;/h4&gt;

&lt;p&gt;This step is easier since its just a regular setting. Open up the "Settings" application, select "Devices", and click the "Keyboard" option. Change the "Switch to workspace" option to the desired keybinding.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fv3zwl8q4k0b7kflppiip.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fv3zwl8q4k0b7kflppiip.png" alt="workspace-indexed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Look and Feel
&lt;/h2&gt;

&lt;p&gt;In Ubuntu 18.10, the &lt;a href="https://github.com/ubuntu/yaru" rel="noopener noreferrer"&gt;default theme&lt;/a&gt; is actually quite good out of the box. I personally didn't change it this time around, but for those looking for alternatives there are quite a few solid options out there such as &lt;a href="https://github.com/horst3180/arc-theme" rel="noopener noreferrer"&gt;arc&lt;/a&gt; and &lt;a href="https://github.com/adapta-project/adapta-gtk-theme" rel="noopener noreferrer"&gt;adapta&lt;/a&gt; themes.&lt;/p&gt;

&lt;p&gt;I have only a few issues with the out of the box look and feel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dock is in the way (if you have a keyboard-driven workflow)&lt;/li&gt;
&lt;li&gt;Some of the animations are too slow&lt;/li&gt;
&lt;li&gt;Terminal menu bar isn't needed (you can get the menu by right clicking)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Removing the dock
&lt;/h3&gt;

&lt;p&gt;Unfortunately, you can't disable the dock from the Tweaks program. Instead, we need to uninstall it entirely. In the terminal type the following:&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;sudo &lt;/span&gt;apt remove gnome-shell-extension-ubuntu-dock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will need to re-log into your machine for the changes to take effect.&lt;/p&gt;

&lt;p&gt;If you want to bring back the dock, simply run:&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;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;gnome-shell-extension-ubuntu-dock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Speeding up animations
&lt;/h3&gt;

&lt;p&gt;To reduce the time of animations, all we need is to grab an extension from the Ubuntu Software program. Simply search for "impatience" and it should pop up.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ft0kkz9cs0bo8hf1jv71v.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ft0kkz9cs0bo8hf1jv71v.png" alt="impatience"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install the extension and open the settings for it. I've personally reduced the animation time in half.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disabling the terminal menu bar
&lt;/h3&gt;

&lt;p&gt;Open the gnome terminal, right click, select preferences. Go to the general section and you should untick the "Show menubar by default in new terminals" checkbox.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fo0u7tfxm4iocnrn7h0k4.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fo0u7tfxm4iocnrn7h0k4.png" alt="terminal-menubar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Software
&lt;/h2&gt;

&lt;p&gt;When installing additional software, it is preferable to do it through software repositories instead of relying on archives (&lt;code&gt;.deb&lt;/code&gt; files). Installing programs through repositories means the operating system will handle upgrading programs for you.&lt;/p&gt;

&lt;p&gt;All of the additional software I need can be simply installed through the "Ubuntu Software" program:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spotify&lt;/li&gt;
&lt;li&gt;Discord&lt;/li&gt;
&lt;li&gt;Steam&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since this is for my personal laptop, there isn't much in terms of office software that I setup. Most of it is browser-based in my case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Development
&lt;/h2&gt;

&lt;p&gt;I've already written an article on how I &lt;a href="https://dev.to/aghost7/developing-from-containers-42fp"&gt;develop from containers&lt;/a&gt;. However, I still need to install custom fonts and configure the terminal profile.&lt;/p&gt;

&lt;p&gt;To install powerline patched fonts:&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 https://github.com/powerline/fonts /tmp/fonts
&lt;span class="nb"&gt;cd&lt;/span&gt; /tmp/fonts
./install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go to the terminal preferences and select the correct profile in use. If you haven't changed the terminal profile this will be the "Unnamed" profile. Select the "Custom font" checkbox and click on the textbox beside it to pick a different font. The font should have "for Powerline" in it, otherwise some glyphs will be missing.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmvrb90u36hiixbrcq7ci.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmvrb90u36hiixbrcq7ci.png" alt="terminal-font"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Setting up a new machine is pretty simple and surprisingly doesn't require me to use the terminal all that much. While I may be extremely comfortable in the terminal (&lt;em&gt;caugh&lt;/em&gt;, NeoVIM user ;)) it is encouraging to see the progress that has been made towards a more approachable desktop. Hopefully one day I'll be able to use Linux at my work.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>ubuntu</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why Hash Maps are Randomized</title>
      <dc:creator>Jonathan Boudreau</dc:creator>
      <pubDate>Fri, 30 Nov 2018 02:09:25 +0000</pubDate>
      <link>https://dev.to/aghost7/why-hash-maps-are-randomized-kln</link>
      <guid>https://dev.to/aghost7/why-hash-maps-are-randomized-kln</guid>
      <description>&lt;p&gt;I implemented a hash map (hash table) on one of my side projects recently just for fun and learned an interesting tidbit about security that I wasn't aware of. Figured I'd share it!&lt;/p&gt;

&lt;h2&gt;
  
  
  How Hash Maps Work
&lt;/h2&gt;

&lt;p&gt;At its core, the idea behind a hash map is that you convert a given key (e.g., a string) into an index value using a &lt;a href="https://en.wikipedia.org/wiki/Hash_function" rel="noopener noreferrer"&gt;hash function&lt;/a&gt;. The index will then determine the location of your data on an array. Insert, delete, and read have a &lt;a href="https://en.wikipedia.org/wiki/Time_complexity#Constant_time" rel="noopener noreferrer"&gt;constant time&lt;/a&gt; complexity (best case 😉). This means that no matter how many elements you have in your hash map the time it takes for your lookups shouldn't really change.&lt;/p&gt;

&lt;p&gt;However, since we are compressing information into a single integer, it is possible to have collisions. The solution is to use another array (a bucket), inside of our hash map's array, to hold all collisions.&lt;/p&gt;

&lt;p&gt;I'll be skipping over some details, but just to get an idea this is what a hash map implementation would roughly look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buckets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// arbitrary&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
                &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
            &lt;span class="p"&gt;}]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&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;h2&gt;
  
  
  Denial of Service
&lt;/h2&gt;

&lt;p&gt;Denial of service broadly refers to an attack where the service is brought down either temporarily or permanently.&lt;/p&gt;

&lt;p&gt;Quite often the way this is done is by triggering a highly expensive operation on the server side repeatedly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Attack
&lt;/h2&gt;

&lt;p&gt;As was mentioned above, when collisions occur more items will be placed into the same bucket. If it happens enough times the performance of your hash map will start to look more like a sequential array of keys and values. In other words the complexity will become &lt;a href="https://en.wikipedia.org/wiki/Time_complexity#Linear_time" rel="noopener noreferrer"&gt;linear&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Depending on how critical the performance of your hash map is, your server resources may be taken up easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;For the attacker to cause collisions in our hash map, he needs to know ahead of time what will cause them. Our solution revolves around making it nearly impossible for the attacker to guess the correct combination of keys to cause enough collisions which would impact the performance of the server.&lt;/p&gt;

&lt;p&gt;Some hash functions allow a seed to be specified for the hash. When the hash map is created we generate the random seed. This means that each hash map instance will convert the same key to a different index. If it is a cryptographically secure random number generator, we know that the attacker will not be able to guess it.&lt;/p&gt;

&lt;p&gt;Here is the rough idea for the solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buckets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// arbitrary&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
                &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
            &lt;span class="p"&gt;}]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&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;



</description>
      <category>security</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Developing from Containers</title>
      <dc:creator>Jonathan Boudreau</dc:creator>
      <pubDate>Thu, 29 Nov 2018 12:50:48 +0000</pubDate>
      <link>https://dev.to/aghost7/developing-from-containers-42fp</link>
      <guid>https://dev.to/aghost7/developing-from-containers-42fp</guid>
      <description>&lt;p&gt;Using containers for development has become a widespread practice. The common use case in development is for running services required by the application. Things such as installing Redis, MongoDB, or even Elasticsearch. Most of the time, developers rely on &lt;code&gt;docker-compose&lt;/code&gt; to define the whole set of services required for the application.&lt;/p&gt;

&lt;p&gt;I've taken things further by creating container images with everything I need to develop in a given language. This includes (but is not limited to):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code editor&lt;/li&gt;
&lt;li&gt;Debugger&lt;/li&gt;
&lt;li&gt;Profiler&lt;/li&gt;
&lt;li&gt;Tracing tools&lt;/li&gt;
&lt;li&gt;Package manager&lt;/li&gt;
&lt;li&gt;Build tools&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  OS Independent
&lt;/h3&gt;

&lt;p&gt;Even if you're using Docker for Mac, you still have a Linux-based environment to develop from. Its really good for getting familiar with Linux, which can then be applied to creating real production container images (among many other things).&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation Speed
&lt;/h3&gt;

&lt;p&gt;Compared to using installer scripts, container images (in particular docker images) are really quick to get going on a new machine. This is because you only need to download the image with pre-compiled binaries. For example, I've had to compile the &lt;code&gt;cquery&lt;/code&gt; server from source for one of my images. If I was using an installer script I'd have to either host the compiled binary myself or compile it on each machine which takes quite some time (since you need to download clang and all that jazz).&lt;/p&gt;

&lt;h3&gt;
  
  
  Portability
&lt;/h3&gt;

&lt;p&gt;If using an installer script, things might not work on a different machine because certain packages were installed in a different manner. For example, someone might've used a &lt;a href="https://askubuntu.com/questions/4983/what-are-ppas-and-how-do-i-use-them" rel="noopener noreferrer"&gt;PPA&lt;/a&gt; to install it one machine, while on another machine it was installed as a &lt;code&gt;.deb&lt;/code&gt; archive or using the standard software sources. In contrast, once a container image is built it will &lt;em&gt;just work&lt;/em&gt; on practically any machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reproducibility
&lt;/h3&gt;

&lt;p&gt;Once the image is built, it won't break out of nowhere. This is unlike installer scripts; I've had many occurrences back when I was just using a git repository to store configurations and scripts where it would break based on when the installer would be run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Not a Common Use Case for Docker
&lt;/h3&gt;

&lt;p&gt;Support from docker for this sort of workflow hasn't been stellar. Some issues with docker have taken years &lt;a href="https://github.com/moby/moby/issues/2259" rel="noopener noreferrer"&gt;to&lt;/a&gt; &lt;a href="https://github.com/moby/moby/issues/8755" rel="noopener noreferrer"&gt;fix&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Still Needs Some Glue Code
&lt;/h3&gt;

&lt;p&gt;There are several things which you want to map from the host into the container. I've written a tool to make this easier called &lt;a href="https://github.com/AGhost-7/slipway" rel="noopener noreferrer"&gt;slipway&lt;/a&gt;. Before I wrote this tool I would use a shell script to initialize the container.&lt;/p&gt;

&lt;p&gt;If you're not using Linux as the host operating system, things can get even more complicated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anatomy of a Containerized Development Environment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  0. Pick a base image
&lt;/h3&gt;

&lt;p&gt;For the uninitiated, building a docker image requires a configuration file (a &lt;a href="https://docs.docker.com/engine/reference/builder/" rel="noopener noreferrer"&gt;Dockerfile&lt;/a&gt;) which defines steps to be executed in a container. After all of these steps are run, the container is "committed" as a new image.&lt;/p&gt;

&lt;p&gt;Most images are based off another image. I recommend starting out with an Ubuntu base since it is very popular.&lt;/p&gt;

&lt;p&gt;Add a file named &lt;code&gt;Dockerfile&lt;/code&gt; in an empty directory:&lt;br&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; ubuntu:bionic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. Set Up Your User
&lt;/h3&gt;

&lt;p&gt;The image only comes with a root user. We'll need to create a user with appropriate permissions to run inside of the container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Feel free to change this to whatever your want&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; DOCKER_USER developer&lt;/span&gt;

&lt;span class="c"&gt;# Create user with passwordless sudo. This is only acceptable as it is a&lt;/span&gt;
&lt;span class="c"&gt;# private development environment not exposed to the outside world. Do &lt;/span&gt;
&lt;span class="c"&gt;# NOT do this on your host machine or otherwise.&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    adduser &lt;span class="nt"&gt;--disabled-password&lt;/span&gt; &lt;span class="nt"&gt;--gecos&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DOCKER_USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    adduser &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DOCKER_USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'%sudo ALL=(ALL) NOPASSWD:ALL'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/sudoers &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;touch&lt;/span&gt; /home/&lt;span class="nv"&gt;$DOCKER_USER&lt;/span&gt;/.sudo_as_admin_successful &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; "$DOCKER_USER"&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; "/home/$DOCKER_USER"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Basic Tools
&lt;/h3&gt;

&lt;p&gt;Ubuntu core (which is what our image is based on) does not include much since it is built for "ready to ship" applications. Lets add some basic packages for development:&lt;br&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;RUN &lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; | &lt;span class="nb"&gt;sudo &lt;/span&gt;unminimize &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; man-db bash-completion build-essential curl openssh-client &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Multiplexing (Optional)
&lt;/h3&gt;

&lt;p&gt;If you aren't using a GUI editor like VSCode or Webstorm, you'll probably want a program which can take a single shell session and split it into multiple ones. This is called a &lt;a href="https://en.wikipedia.org/wiki/Terminal_multiplexer" rel="noopener noreferrer"&gt;terminal multiplexer&lt;/a&gt;. I prefer &lt;a href="https://github.com/tmux/tmux" rel="noopener noreferrer"&gt;tmux&lt;/a&gt;.&lt;br&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;RUN &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; tmux &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's plenty of customization options which I could discuss here, but to keep the tutorial short I will be skipping over this step. &lt;a href="https://github.com/AGhost-7/docker-dev" rel="noopener noreferrer"&gt;Feel free to check out my project&lt;/a&gt; for riced up development environment ideas.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Install Your Editor of Choice
&lt;/h3&gt;

&lt;p&gt;Now we need something to edit source code. I can recommend Neovim, but any editor will do.&lt;br&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;RUN &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; neovim &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As above, I am skipping customization options.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Install Your Runtime
&lt;/h3&gt;

&lt;p&gt;In this example, we'll be installing NodeJs since most developers on the site use it. If you're using Python or some other language at this step you can install it instead.&lt;br&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;RUN &lt;/span&gt;curl &lt;span class="nt"&gt;-o-&lt;/span&gt; https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NVM_DIR /home/$DOCKER_USER/.nvm&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM_DIR&lt;/span&gt;&lt;span class="s2"&gt;/nvm.sh"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    nvm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--lts&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    nvm &lt;span class="nb"&gt;alias &lt;/span&gt;default stable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install any additional tools for your language of choice at this step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building, then running
&lt;/h3&gt;

&lt;p&gt;All you need is to build the image before you can run it.&lt;/p&gt;

&lt;p&gt;In your terminal, run:&lt;br&gt;
&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="nt"&gt;-t&lt;/span&gt; development-environment &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final command to run your environment can vary based on what you want to transfer over. Here is an example command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-ti&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/workspace:/home/developer/workspace &lt;span class="se"&gt;\&lt;/span&gt;
    development-environment bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a more detailed version of this tutorial, see my repository's &lt;a href="https://github.com/AGhost-7/docker-dev/tree/master/tutorial" rel="noopener noreferrer"&gt;tutorial&lt;/a&gt; section.&lt;/p&gt;

</description>
      <category>containers</category>
      <category>docker</category>
      <category>linux</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Hi, I'm Jonathan Boudreau</title>
      <dc:creator>Jonathan Boudreau</dc:creator>
      <pubDate>Mon, 02 Jan 2017 05:51:59 +0000</pubDate>
      <link>https://dev.to/aghost7/hi-im-jonathan-boudreau</link>
      <guid>https://dev.to/aghost7/hi-im-jonathan-boudreau</guid>
      <description>&lt;p&gt;I have been coding for 3 years.&lt;/p&gt;

&lt;p&gt;You can find me on GitHub as &lt;a href="https://github.com/AGhost-7" rel="noopener noreferrer"&gt;AGhost-7&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I mostly program in these languages: Javascript, Scala, Rust.&lt;/p&gt;

&lt;p&gt;I am currently learning more about DevOps.&lt;/p&gt;

&lt;p&gt;Nice to meet you.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
