<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[developMENTALmadness]]></title><description><![CDATA[The musings, frustrations and epiphanies of a common web programmer.]]></description><link>http://www.developmentalmadness.com/</link><generator>Ghost 0.7</generator><lastBuildDate>Thu, 18 Aug 2016 20:01:12 GMT</lastBuildDate><atom:link href="http://www.developmentalmadness.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Docker: running npm install]]></title><description><![CDATA[<p>Just spent most of the day trying to get <code>npm install</code> to work within a shared volume (<code>-v</code>). I've installed Docker Toolbox on Windows and I'm building a Docker image that will be shared with team members running on both Windows and OSX. This image is for development, not deployment.</p>]]></description><link>http://www.developmentalmadness.com/2016/06/13/docker-running-npm-install/</link><guid isPermaLink="false">78c6e8e4-da4e-4506-9f67-4003720247e7</guid><category><![CDATA[Docker]]></category><category><![CDATA[nodejs]]></category><category><![CDATA[npm]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Mon, 13 Jun 2016 21:30:28 GMT</pubDate><content:encoded><![CDATA[<p>Just spent most of the day trying to get <code>npm install</code> to work within a shared volume (<code>-v</code>). I've installed Docker Toolbox on Windows and I'm building a Docker image that will be shared with team members running on both Windows and OSX. This image is for development, not deployment. </p>

<p>I really like the idea that a project should include a <code>compose.yml</code>. New team members should be able to simply <code>git clone ...</code>, <code>docker compose up</code> and then fire up their preferred IDE and then they're off to the races!</p>

<p>Anyway, long story short if all the npm modules you're depending on cooperate you should be able to run npm as follows:</p>

<pre><code>npm install --no-bin-links
</code></pre>

<p>And that should work for now. I read a thread that the Bash for Windows team is being consulted on this by the Docker for Windows Beta team - hopefully this won't be a problem for long!</p>]]></content:encoded></item><item><title><![CDATA[Docker: Run Azure Command-Line Client Container]]></title><description><![CDATA[<p>I've been using AWS, but I'm starting to look into Apache Spark for an up-coming project and Amazon EMR doesn't qualify under the AWS Free Tier so I decided to head on over to the world of Microsoft Azure to use my MSDN credits to do some experimentation without it</p>]]></description><link>http://www.developmentalmadness.com/2016/05/17/docker-run-azure-command-line-client-container/</link><guid isPermaLink="false">dc87d984-e3d9-476d-be5a-6e4ed79247e5</guid><category><![CDATA[Docker]]></category><category><![CDATA[Azure]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Tue, 17 May 2016 17:47:55 GMT</pubDate><content:encoded><![CDATA[<p>I've been using AWS, but I'm starting to look into Apache Spark for an up-coming project and Amazon EMR doesn't qualify under the AWS Free Tier so I decided to head on over to the world of Microsoft Azure to use my MSDN credits to do some experimentation without it costing my anything.</p>

<p>Microsoft has created a <a href="https://azure.microsoft.com/en-us/documentation/articles/xplat-cli-install/#use-a-docker-container">Docker image for their Azure command-line client</a>. Here's my setup:</p>

<pre><code>$ docker create --name azure-profile -v /root/.azure microsoft/azure-cli
</code></pre>

<p>The Azure cli stores configuration and access tokens in <code>~/</code>. Unless you want to authenticate each time to you fire up a new session I recommend creating a data volume container for your profile data. Then you can use it to make sure your profile data is persistent like this:</p>

<pre><code>$ docker run -it --rm --volumes-from azure-profile microsoft/azure-cli
</code></pre>

<p>This will create an interactive tty session <code>-it</code> in a new container which will be deleted <code>--rm</code> as soon as you exit. But as long as you use <code>--volumes-from</code> your profile data will be persistent. </p>

<p>First let's look at the contents of the <code>~/.azure</code> directory before we log in:</p>

<pre><code>$ ls ~/.azure

config.json  telemetry.json
</code></pre>

<p>Next before we go through the login steps, let's make sure we've correctly setup our volume. Open a second terminal session (make sure to run <code>eval "$(docker-machine env [name])"</code>). Now run <code>inspect</code> to make sure we have the volume right:</p>

<pre><code>$ docker inspect --format='{{json .Mounts}}' [container_id]

[{"Name":"668d3cf8050abe1a87c29f4c1bd2023ecc9c27bec6bbd26d17e0fd24729e8c35","Source":"/var/lib/docker/volumes/668d3cf8050abe1a87c29f4c1bd2023ecc9c27bec6bbd26d17e0fd24729e8c35/_data","Destination":"/root/.azure","Driver":"local","Mode":"","RW":true,"Propagation":""}]
</code></pre>

<p>You should see something like the above output. The important part is the <code>Destination</code> should be <code>/root/.azure</code>. If it is you did it right. Otherwise, go back and look for typos.</p>

<p>Back in our interactive container session: We need to login. You may want to <a href="https://azure.microsoft.com/en-us/documentation/articles/xplat-cli-connect/">review authentication options</a>. As for me I have MFA enabled on my Microsoft account so I use the interactive login once I'm inside my interactive container session:</p>

<pre><code>$ azure login
</code></pre>

<p>Follow the directions and you'll be logged in.</p>

<p>Let's inspect our profile directory again:</p>

<pre><code>$ ls ~/.azure

accessTokens.json  azureProfile.json  config.json  telemetry.json
</code></pre>

<p>Now if your volumes are correct you can exit your container session (which will remove your container because of the <code>--rm</code> option we specified):</p>

<pre><code>$ exit
</code></pre>

<p>Now fire up a new session again:</p>

<pre><code>$ docker run -it --rm --volumes-from azure-profile microsoft/azure-cli
</code></pre>

<p>Look inside your <code>~/.azure</code> directory and it should still have all 4 <code>.json</code> files. Now you're all set. Good luck!</p>]]></content:encoded></item><item><title><![CDATA[Play2: Debugging With IntelliJ Community Edition]]></title><description><![CDATA[<h2 id="configurebuildsbt">Configure build.sbt</h2>

<p>Comment out or remove </p>

<pre><code>fork in run := true
</code></pre>

<h2 id="configureintellij">Configure IntelliJ</h2>

<p>Create a remote debug configuration:</p>

<pre><code>Run &gt; Edit Configurations &gt; Add New Configuration &gt; Remote
</code></pre>

<p>Set <code>Host</code> to <code>localhost</code> and <code>Port</code> to <code>9999</code>, name your configuration. I called mine "Debug Activator" then click "Apply", the "OK".</p>

<h2 id="runactivator">Run</h2>]]></description><link>http://www.developmentalmadness.com/2016/05/03/play2-debugging-with-intellij-community-edition/</link><guid isPermaLink="false">0c9a0fc8-945d-4f36-9af8-9c92f3cb29b6</guid><category><![CDATA[Play2]]></category><category><![CDATA[IntelliJ]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Tue, 03 May 2016 22:21:08 GMT</pubDate><content:encoded><![CDATA[<h2 id="configurebuildsbt">Configure build.sbt</h2>

<p>Comment out or remove </p>

<pre><code>fork in run := true
</code></pre>

<h2 id="configureintellij">Configure IntelliJ</h2>

<p>Create a remote debug configuration:</p>

<pre><code>Run &gt; Edit Configurations &gt; Add New Configuration &gt; Remote
</code></pre>

<p>Set <code>Host</code> to <code>localhost</code> and <code>Port</code> to <code>9999</code>, name your configuration. I called mine "Debug Activator" then click "Apply", the "OK".</p>

<h2 id="runactivator">Run Activator</h2>

<p>From the command line:</p>

<pre><code>$ activator -jvm-debug 9999
</code></pre>

<p>Once that starts go back to IntelliJ and start your debug configuration. Then return to the command line prompt and execute:</p>

<pre><code>$ run
</code></pre>

<p>You don't have to do the command line in two steps. That's just if you want to debug the application startup. Otherwise this will work just fine:</p>

<pre><code>$ activator run -jvm-debug 9999
</code></pre>

<p>Then just set a breakpoint and make a request.</p>]]></content:encoded></item><item><title><![CDATA[Recovery iPhone Recovery Password From Backup]]></title><description><![CDATA[<p>My wife forgot her restrictions pin on her iPhone and wouldn't let me reset the phone because she didn't want to loose <strong>anything</strong>. I found multiple tools that would help with this but they wanted $$ and I knew this was something I could figure out. </p>

<p>Well all hail open source!</p>]]></description><link>http://www.developmentalmadness.com/2016/04/28/recovery-iphone-recovery-password-from-backup/</link><guid isPermaLink="false">3a056a93-68f6-4c53-9a93-f6bf29b5cad6</guid><category><![CDATA[Iphone]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Thu, 28 Apr 2016 15:25:19 GMT</pubDate><content:encoded><![CDATA[<p>My wife forgot her restrictions pin on her iPhone and wouldn't let me reset the phone because she didn't want to loose <strong>anything</strong>. I found multiple tools that would help with this but they wanted $$ and I knew this was something I could figure out. </p>

<p>Well all hail open source! Because I found <a href="https://github.com/gwatts/pinfinder">pinfinder</a> on Github. A nifty little go program that will scan your unencrypted backups and pull your pin. </p>

<p>If you've encrypted all your backups, just run a new non-encrypted one and then delete it afterwards.</p>

<p>Just download the <a href="https://github.com/gwatts/pinfinder/releases">latest release</a> for your platform, extract the archive and run it from the terminal:</p>

<pre><code>$ pinfinder
</code></pre>

<p>That's it!</p>]]></content:encoded></item><item><title><![CDATA[The Zen of Akka (Lambda Days 2016) Cliff Notes]]></title><description><![CDATA[<iframe width="560" height="315" src="https://www.youtube.com/embed/tC-joPMPJLs" frameborder="0" allowfullscreen></iframe>

<p>Below are all the points, what time to find them in the video and what I found were the important talking points. I left most stuff actually on the slide out.</p>

<h1 id="1oneactorisnoactor">1. One Actor Is No Actor</h1>

<p>(about 3:17)</p>

<p>Semantically, a system with a single actor is not a</p>]]></description><link>http://www.developmentalmadness.com/2016/04/22/the-zen-of-akka-lambda-days-2016-notes/</link><guid isPermaLink="false">d7f0ea64-c9d7-487e-8c19-13dae699da08</guid><category><![CDATA[Akka]]></category><category><![CDATA[Cliff Notes]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Fri, 22 Apr 2016 19:45:25 GMT</pubDate><content:encoded><![CDATA[<iframe width="560" height="315" src="https://www.youtube.com/embed/tC-joPMPJLs" frameborder="0" allowfullscreen></iframe>

<p>Below are all the points, what time to find them in the video and what I found were the important talking points. I left most stuff actually on the slide out.</p>

<h1 id="1oneactorisnoactor">1. One Actor Is No Actor</h1>

<p>(about 3:17)</p>

<p>Semantically, a system with a single actor is not a concurrent system.</p>

<p>Use <code>ActorRef</code> over actor selection</p>

<h1 id="2structureyouractors">2. Structure Your Actors</h1>

<p>(about 6:13)</p>

<p>Prefer <code>context.actorOf</code> over <code>system.actorOf</code>. This will create a parent/child relationship which allows for actor supervision. <code>system.actorOf</code> creates all new actors on the same 'level' instead of within a hierarchy. </p>

<h1 id="3nameyouractors">3. Name Your Actors</h1>

<p>(about 7:22)</p>

<p>Allows actor names to have meaning within the domain:</p>

<ul>
<li>Default naming: bad - no context when logging/debugging</li>
<li><code>[name]-[counter]</code>: better - but still lacks important meaning. Example: <code>fetch-worker-1</code>, <code>fetch-worker-2</code></li>
<li><code>[name]-[contextual-id]</code>: best - combines meaningful name with the execution context. Example for actor which fetches videos from web sites: <code>fetch-yt-[youtube-identifier]</code>, <code>fetch-vm-[vimeo-identifier]</code></li>
</ul>

<p><strong>Note:</strong> Don't use scala string interpolation for logging:</p>

<pre><code>//BAD - the string is always built/evaluated
log.debug(s"Something heavy $generateId from $physicalAddress")

//GOOD - string built only when DEBUG level is ON
log.debug("Something heavy {} from {}", generateId, physicalAddress)
</code></pre>

<h1 id="4matrixofmutabilitypain">4. Matrix Of Mutability (Pain)</h1>

<p>(about 11:49)</p>

<p>(Lower number is better):</p>

<ol>
<li>Immutable Val - great, but you can't do anything with it  </li>
<li>Immutable Var - most of the time, you can mutate it but if it gets "leaked" (sent to another actor) it can't be modified (thread-safe).  </li>
<li>Mutable Val - shouldn't do this. Not thread-safe.  </li>
<li>Mutable Var - never do this</li>
</ol>

<h1 id="5blockingneedscarefulmanagement">5. Blocking Needs Careful Management</h1>

<p>(about 14:25)</p>

<p>When you block - isolate it - use a non-defualt dispatcher on it's own thread pool. Aka "Bulkhead Pattern"</p>

<p>When configured in your config file like this:</p>

<pre><code>// application.conf

my-blocking-dispatcher {
  type = Dispatcher
  executor = "thread-pool-executor"

  thread-pool-executor {
    //in akka previous to 2.4.2
    core-pool-size-min = 16
    core-pool-size-max = 16
    max-pool-size-min = 16
    max-pool-size-max = 16

    // or in Akka 2.4.2+
    fixed-pool-size = 16
  }

  throughput = 100
}
</code></pre>

<p>Then you can do this:</p>

<pre><code>implicit val blockingDispatcher = system.dispatchers.lookup("my-blocking-dispatcher")

val routes: Route = post {
  complete {
    Future {
      Thread.sleep(5000)
      System.currentTimeMillis().toString
    }
  }
}
</code></pre>

<p>This is good because you're blocking only on a dedicated dispatcher instead of the default dispatcher.</p>

<h1 id="6neverawaitforflatmapinstead">6. Never Await, for/FlatMap instead</h1>

<p>(about 19:20)</p>

<p>Use Monadic composition of futures (<code>for</code> block) or <code>akka.pattern.after</code> with <code>Future.firstCompletedOf</code> (best)</p>

<h1 id="7avoidjavaserialization">7. Avoid Java Serialization</h1>

<p>(about 22:38)</p>

<p>Java serialization is the default because it made for easy "Hello World" default case for those learning. Problem is people don't change the defaults going into production and decide "Akka is slow".</p>

<p>Good suggestions are ProtoBuf or Kryo. Both have pros/cons. Kryo is easier to setup, but poor schema evolution. ProtoBuf requires more setup but better evolution. Other suggestions are SBE, Thrift, and JSON.</p>

<p>Even XML is smaller/faster than default Java serialization.</p>

<h1 id="75trustnoonebenchmarkeverything">7.5. Trust no-one, benchmark everything</h1>

<p>(about 29:54)</p>

<p>[all info is on the slide]</p>

<h1 id="8letitcrashsupervisionfailureserrors">8. Let it Crash! Supervision, Failures, &amp; Errors</h1>

<p>(about 30:48)</p>

<p>Error - is expected and handled. Report to end user</p>

<p>Failure - an unexpected event. Report to supervisor</p>

<p>Ask who can do something about a problem?</p>

<h1 id="9backoffsupervision">9. Backoff Supervision</h1>

<p>(about 35:00)</p>

<p>Exponential Backoff</p>

<p>Persistent actor -> Datbase</p>

<p>If fail/restart is immediate you're basically DDOS your database/system</p>

<p>Instead use Backoff Supervisor, something outside the hierarchy and is provided by Akka if you configure it. </p>

<h1 id="10designusingstatemachines">10. Design using State Machines</h1>

<p>(about 38:27)</p>

<p><strong>Bad</strong>: Long list of <code>case</code> matches for 15 or more messages in an actor's receive looks like "pyramid of doom" found in async programming frameworks like javascript.</p>

<p><strong>Good</strong>: You may end up using the FSM (Finite State Machine) DSL to help you achieve this goal.</p>

<h1 id="11clusterconvergenceandjoining">11. Cluster Convergence and Joining</h1>

<p>(about 40:25)</p>

<p>Cluster Gossip Convergence: Everybody knows something, then we make a decision on it.</p>

<p><code>allow-weakly-up-members</code>: allow "up" (join) state before all nodes can see it. Allows nodes to join even when there is a network partition.</p>

<h1 id="12clusterpartitionsanddown">12. Cluster Partitions and "Down"</h1>

<p>(about 43:04)</p>

<p>Opposite of last point.</p>

<p>When a node gets marked as unreachable it gets marked as "down". When it comes back everyone refuses to talk to it. If you don't want this behavior you can turn it off, but then make sure you don't use features that follow "single writer principle" (eg. Akka Persistance). Instead use CRDT based like Akka Distributed Data.</p>

<h1 id="13afishingrodisatoolakkaisatoolkit">13. A fishing rod is a Tool. Akka is a Toolkit</h1>

<p>(about 44:54)</p>

<p>Use the least powerful abstraction that gets the job for you. Sometimes a <code>Future</code> is enough but not distributed. <code>Actors</code> are distributed, but require more work - so it's a tradeoff.</p>

<h1 id="qa">Q&amp;A</h1>

<p>(about 47:20)</p>

<p>Distributed Akka Streams? Try Intel GearPump:</p>

<ul>
<li><a href="https://www.lightbend.com/resources/case-studies-and-stories/intels-gearpump-real-time-streaming-engine-using-akka">https://www.lightbend.com/resources/case-studies-and-stories/intels-gearpump-real-time-streaming-engine-using-akka</a></li>
<li><a href="https://software.intel.com/en-us/blogs/2015/08/14/all-about-gearpump-the-real-time-big-data-streaming-engine-behind-intel-s-latest">https://software.intel.com/en-us/blogs/2015/08/14/all-about-gearpump-the-real-time-big-data-streaming-engine-behind-intel-s-latest</a></li>
</ul>

<p>Backpressure using Backoff Supervisor strategy? No</p>]]></content:encoded></item><item><title><![CDATA[Docker: Troubleshooting 500 Error From Registry 2]]></title><description><![CDATA[<p>Been fighting an <a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_Server_Error">HTTP 500 Internal Server Error</a> from Docker Registry. We have several instances running on Amazon EC2 Container Service (ECS) behind Elastic Load Balancer (ELB). Whenever we tried to push a new image up we'd get:</p>

<blockquote>
  <p>received unexpected HTTP status: 500 Internal Server Error</p>
</blockquote>

<h1 id="enabledebugmode">Enable Debug Mode</h1>

<p>Docker</p>]]></description><link>http://www.developmentalmadness.com/2016/04/21/docker-troubleshooting-500-error-from-registry-2/</link><guid isPermaLink="false">1c6ce07d-029d-4971-8ec2-5fc80f1f1232</guid><category><![CDATA[Docker]]></category><category><![CDATA[Troubleshooting]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Thu, 21 Apr 2016 22:44:45 GMT</pubDate><content:encoded><![CDATA[<p>Been fighting an <a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_Server_Error">HTTP 500 Internal Server Error</a> from Docker Registry. We have several instances running on Amazon EC2 Container Service (ECS) behind Elastic Load Balancer (ELB). Whenever we tried to push a new image up we'd get:</p>

<blockquote>
  <p>received unexpected HTTP status: 500 Internal Server Error</p>
</blockquote>

<h1 id="enabledebugmode">Enable Debug Mode</h1>

<p>Docker logs wasn't telling me anything. But searching around I read you can enable debug mode <code>-D</code> for Docker. After locating in the ECS documentation <a href="http://docs.aws.amazon.com/AmazonECS/latest/developerguide/troubleshooting.html#docker-debug-mode">how to enable debug mode</a> I did the following on each EC2 instance:</p>

<pre><code>sudo vi /etc/sysconfig/docker
</code></pre>

<p>And changed this line:</p>

<pre><code>OPTIONS="--default-ulimit nofile=1024:4096"
</code></pre>

<p>To this:</p>

<pre><code>OPTIONS="-D --default-ulimit nofile=1024:4096"
</code></pre>

<p>Then saved the file and restarted the Docker daemon:</p>

<pre><code>sudo service docker restart
</code></pre>

<p>And restarted both the ECS Agent and my Docker registry container:</p>

<pre><code>sudo docker start [ecs_container_id]
sudo docker start [registry_container_id]
</code></pre>

<h1 id="solution">Solution</h1>

<p>Then after trying to push an image again I found this in our logs:'</p>

<pre><code>time="2016-04-21T22:18:48Z" level=error msg="response completed with error" err.code=unknown err.detail="s3aws: AccessDenied: Access Denied\n\tstatus code: 403, request id: XXXXXXXXXXXXXXXX" err.message="unknown error" go.version=go1.6.1 http.request.host=[hostname] http.request.id=[UUID value] http.request.method=PATCH http.request.remoteaddr=[IP Address] http.request.uri="/v2/[image_name]/blobs/uploads/[digest]?_state=[data]" http.request.useragent="docker/1.11.0 go/go1.5.4 git-commit/[hash] kernel/4.1.19-boot2docker os/linux arch/amd64 UpstreamClient(Docker-Client/1.11.0 \\(windows\\))" http.response.contenttype="application/json; charset=utf-8" http.response.duration=137.964693ms http.response.status=500 http.response.written=117 instance.id=[UUID value] vars.name=[image_name] vars.uuid=[UUID value] version=v2.4.0
</code></pre>

<p>The most helpful bit of the message was: </p>

<blockquote>
  <p>err.detail="s3aws: AccessDenied: Access Denied\n\tstatus code: 403, request id: XXXXXXXXXXXXXXXX"</p>
</blockquote>

<p>Telling me that the container was missing the correct S3 permissions.</p>]]></content:encoded></item><item><title><![CDATA[Docker: Open a Bash Shell in a Docker Container Without SSH]]></title><description><![CDATA[<p><a href="http://blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker/">You don't need to install SSHd on your Docker containers.</a>. However, the method you use has changed. Now Docker has the <code>exec</code> command to do this for you. </p>

<p>If you have a container named <code>my-app-container</code> then you would run:</p>

<pre><code>$ docker exec -it my-app-container bash
</code></pre>

<p>To open a bash shell in</p>]]></description><link>http://www.developmentalmadness.com/2016/04/20/docker-open-a-bash-shell-in-a-docker-container-without-ssh/</link><guid isPermaLink="false">892e4a25-b98b-4678-a179-d6405a8df980</guid><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Wed, 20 Apr 2016 22:29:03 GMT</pubDate><content:encoded><![CDATA[<p><a href="http://blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker/">You don't need to install SSHd on your Docker containers.</a>. However, the method you use has changed. Now Docker has the <code>exec</code> command to do this for you. </p>

<p>If you have a container named <code>my-app-container</code> then you would run:</p>

<pre><code>$ docker exec -it my-app-container bash
</code></pre>

<p>To open a bash shell in your container.</p>

<p>As an added bonus, if you're in development and you want to get into your Docker VM then the easiest way is to run:</p>

<pre><code>$ docker-machine ssh [docker_vm_name]
</code></pre>

<p>For most of us using the <code>default</code> VM it would look like this:</p>

<pre><code>$ docker-machine ssh default
</code></pre>

<p>Once you've opened <code>ssh</code> into your VM, then you can run the <code>docker exec</code> command at the top.</p>

<h1 id="references">References:</h1>

<ul>
<li><a href="https://docs.docker.com/engine/reference/commandline/exec/">Docker exec command</a> </li>
</ul>]]></content:encoded></item><item><title><![CDATA[Docker: Copy Arbitrary Files Between Docker Containers]]></title><description><![CDATA[<p>Do you need to copy an arbitrary file from within a <a href="https://en.wikipedia.org/wiki/Docker_(software)">Docker</a> container to your host file system? The <code>docker cp</code> command has got your back!</p>

<pre><code>$ docker cp [container_id]:[container_path] [localpath]
</code></pre>

<p>So to copy a file named <code>output.log</code> to the current working directory from a container named</p>]]></description><link>http://www.developmentalmadness.com/2016/03/28/docker-copy-command-2/</link><guid isPermaLink="false">0294c619-e952-487a-8f65-27dbec1161f6</guid><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Mon, 28 Mar 2016 23:34:18 GMT</pubDate><content:encoded><![CDATA[<p>Do you need to copy an arbitrary file from within a <a href="https://en.wikipedia.org/wiki/Docker_(software)">Docker</a> container to your host file system? The <code>docker cp</code> command has got your back!</p>

<pre><code>$ docker cp [container_id]:[container_path] [localpath]
</code></pre>

<p>So to copy a file named <code>output.log</code> to the current working directory from a container named <code>mycontainer</code> you would run:</p>

<pre><code>$ docker cp mycontainer:/my-app-logs/output.log output.log
</code></pre>

<p>The command works the other direction as well:</p>

<pre><code>$ docker cp output.log mycontainer:/my-app-logs/output.log
</code></pre>

<p>Full details on the command can be found in the <a href="https://docs.docker.com/v1.8/reference/commandline/cp/">Docker cp documentation</a>.</p>]]></content:encoded></item><item><title><![CDATA[Linux: Scheduled Jobs With crontab]]></title><description><![CDATA[<p>Today I learned about <code>crontab</code>, which for those of us coming from the <a href="https://en.wikipedia.org/wiki/Microsoft_Windows">Windows</a> world is the equivalent of the <a href="https://en.wikipedia.org/wiki/Windows_Task_Scheduler">Windows Task Scheduler</a>. If I had known how easy it was to use I would have started using it a long time ago.</p>

<p><a href="http://www.howtogeek.com/101288/how-to-schedule-tasks-on-linux-an-introduction-to-crontab-files/">HowToGeek has a great detailed write-up</a> on</p>]]></description><link>http://www.developmentalmadness.com/2016/03/10/linux-crontab/</link><guid isPermaLink="false">aad0bb4b-7a59-4bcf-bfc8-0fa9d0f879f7</guid><category><![CDATA[Linux]]></category><category><![CDATA[bash]]></category><category><![CDATA[crontab]]></category><category><![CDATA[Amazon Web Services (AWS)]]></category><category><![CDATA[Elastic Cloud Compute (EC2)]]></category><category><![CDATA[Simple Storage Service (S3)]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Thu, 10 Mar 2016 17:05:32 GMT</pubDate><content:encoded><![CDATA[<p>Today I learned about <code>crontab</code>, which for those of us coming from the <a href="https://en.wikipedia.org/wiki/Microsoft_Windows">Windows</a> world is the equivalent of the <a href="https://en.wikipedia.org/wiki/Windows_Task_Scheduler">Windows Task Scheduler</a>. If I had known how easy it was to use I would have started using it a long time ago.</p>

<p><a href="http://www.howtogeek.com/101288/how-to-schedule-tasks-on-linux-an-introduction-to-crontab-files/">HowToGeek has a great detailed write-up</a> on it including plenty of examples of using the <a href="https://en.wikipedia.org/wiki/Cron">cron</a> pattern. What I wanted to share was how to use <a href="https://en.wikipedia.org/wiki/Redirection_(computing)">I/O Redirection</a> to update the file instead of using the crontab editor (<code>crontab -e</code>) as described in the HowToGeek article.</p>

<p>I wanted to setup a really simple file backup to <a href="https://en.wikipedia.org/wiki/Amazon_S3">Amazon S3</a> on an <a href="https://en.wikipedia.org/wiki/Amazon_Elastic_Compute_Cloud">Amazon EC2</a> instance. I also wanted to make sure I didn't have to set it up more than once. So I needed something that would work well as an <a href="http://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_container_instance.html#instance-launch-user-data-step">EC2 User Data script</a>:</p>

<p>First, copy crontab to a temp file named 'cron-temp' (arbitrary name):</p>

<pre><code>$ crontab -l &gt; cron-temp
</code></pre>

<p>Next, use the append output-redirector <code>&gt;&gt;</code> to write a string to the temp file named 'cron-temp'. If I wanted to overwrite the file completely I could use <code>&gt;</code> instead:</p>

<pre><code>$ echo '[minutes] [hours] [days] [months] [day-of-week] [bash command or script file]' &gt;&gt; cron-temp
</code></pre>

<p>In my case I wanted to run the script at the top of every hour so the script actually looked like this see the HowToGeek article for details on cron patterns:</p>

<pre><code>$ echo '0 * * * * aws s3 cp [local file path] s3://[s3-bucket-path]' &gt;&gt; cron-temp
</code></pre>

<p>Now that we've updated the temp file replace crontab file with contents of the temp file:</p>

<pre><code>$ crontab cron-temp
</code></pre>

<p>Finally, delete the temp file:</p>

<pre><code>$ rm cron-temp
</code></pre>]]></content:encoded></item><item><title><![CDATA[Docker: Configure Insecure Registry for systemd]]></title><description><![CDATA[<p>If you're running a flavor of Linux that uses systemd Docker recommends using it to <a href="https://docs.docker.com/engine/admin/systemd/">configure and control your Docker daemon</a>. I needed to connect my Docker daemon running on my Jenkins build server to my Docker Registry running in AWS (that's a post for another day). They connect through</p>]]></description><link>http://www.developmentalmadness.com/2016/03/09/docker-configure-insecure-registry-for-systemd/</link><guid isPermaLink="false">8e1601f2-0b63-476f-bcdc-36167a4ccd6d</guid><category><![CDATA[Docker]]></category><category><![CDATA[systemd]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Wed, 09 Mar 2016 21:16:42 GMT</pubDate><content:encoded><![CDATA[<p>If you're running a flavor of Linux that uses systemd Docker recommends using it to <a href="https://docs.docker.com/engine/admin/systemd/">configure and control your Docker daemon</a>. I needed to connect my Docker daemon running on my Jenkins build server to my Docker Registry running in AWS (that's a post for another day). They connect through a private network so I'm not using SSL which means I need to configure the daemon with the <a href="https://docs.docker.com/engine/reference/commandline/daemon/#insecure-registries">--insecure-registry</a> option. Here's how to do that:</p>

<p><strong>NOTE:</strong> Some posts recommend just changing the <code>/lib/systemd/system/docker.service</code> file. This works but the <a href="https://docs.docker.com/engine/admin/systemd/">documentation advises against it</a>:</p>

<blockquote>
  <p>The files located in /usr/lib/systemd/system or /lib/systemd/system contain the default options and should not be edited.</p>
</blockquote>

<p>If you'd rather save a few steps you can skip the "create" section below and move ahead to the "configure" section. Other than the paths of the files you'll be editing everything else should be the same.</p>

<h1 id="createsystemdoverridefiles">Create systemd Override Files</h1>

<p>If the path <code>/etc/systemd/system/docker.service.d/docker.conf</code> already exists just open the <code>docker.conf</code> file and skip to the next section. If it doesn’t exist, create the directory <code>/etc/systemd/system/docker.service.d</code> directory and <code>docker.conf</code> file:</p>

<pre><code>$ sudo mkdir /etc/systemd/system/docker.service.d
$ sudo touch /etc/systemd/system/docker.service.d/docker.conf
$ sudo vi /etc/systemd/system/docker.service.d/docker.conf
</code></pre>

<p>Then add the following contents to <code>docker.conf</code>:</p>

<pre><code>$ sudo vi /etc/systemd/system/docker.service.d/docker.conf
[Service]
ExecStart=
ExecStart=/usr/bin/docker daemon -H fd://
</code></pre>

<h1 id="configureinsecureregistry">Configure insecure-registry</h1>

<p>Append the <code>--insecure-registry</code> option to the end of the <code>ExecStart</code> options so it looks something like this: (multiple entries follow array convention. <a href="https://docs.docker.com/engine/reference/commandline/daemon/">See docs</a>) </p>

<pre><code>ExecStart=/usr/bin/docker daemon -H fd:// --insecure-registry myregistry.mydomain.com
</code></pre>

<p>Just make sure you replace <code>myregistry.mydoamin.com</code> with the url (and optionally the port if you're not using port 80) for your registry.</p>

<p>Save the file, then flush changes and restart:</p>

<pre><code>$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
</code></pre>

<p>Verify docker daemon is running</p>

<pre><code>$ ps aux | grep docker | grep -v grep
</code></pre>

<h1 id="oruseetcdefaultdocker">Or Use /etc/default/docker</h1>

<p>It may be because using <code>systemd</code> is new or it may be personal preference. But if you want to use the <code>/etc/default/docker</code> file to configure your docker daemon then you just need to change a couple things. First change your <code>/etc/systemd/system/docker.service.d/docker.conf</code> file to look like this:</p>

<pre><code>ExecStart=/usr/bin/docker daemon -H fd:// $DOCKER_OPTS
EnvironmentFile=-/etc/default/docker
</code></pre>

<p>Now you can add the following to your <code>/etc/default/docker</code> file (create it if it doesn't exist) and replace <code>myregistry.mydomain.com</code> with the url (and optionally the port number if it isn't over port 80):</p>

<pre><code>DOCKER_OPTS="--insecure-registry myregistry.mydomain.com"
</code></pre>

<p>Again save the file, flush changes and restart just like above.</p>]]></content:encoded></item><item><title><![CDATA[Docker: Configure Insecure Registry in Boot2Docker]]></title><description><![CDATA[<p>I gotta say there's some confusing naming that goes on. <code>Boot2Docker</code> was originally a docker client that ran on OSX and Windows. That has been replaced by <code>docker-machine</code>. However, there is also a VirtualBox image (the default one) called <code>Boot2Docker</code>. In this post I'm talking about the latter.</p>

<p>I have</p>]]></description><link>http://www.developmentalmadness.com/2016/03/09/docker-configure-insecure-registry-in-boot2docker/</link><guid isPermaLink="false">f13ac245-30d5-4441-af91-092249c30328</guid><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Wed, 09 Mar 2016 18:00:46 GMT</pubDate><content:encoded><![CDATA[<p>I gotta say there's some confusing naming that goes on. <code>Boot2Docker</code> was originally a docker client that ran on OSX and Windows. That has been replaced by <code>docker-machine</code>. However, there is also a VirtualBox image (the default one) called <code>Boot2Docker</code>. In this post I'm talking about the latter.</p>

<p>I have a Docker Registry instance I just configured to run in AWS and is backed by S3 for storage. It's running as a farm of ECS containers behind an ELB. It is running in a private network so I have skipped setting up SSL. Which means I need to configure my docker daemon with the <code>--insecure-registry</code> option so I can pull images to my development machine. And as I mentioned above, I'm currently using the default <code>Boot2Docker</code> image so the configuration is very specific.</p>

<p>You should have a file in your Docker VM: <code>/var/lib/boot2docker/profile</code>. If you open it, it should look something like this:</p>

<pre><code>$ cat /var/lib/boot2docker/profile

EXTRA_ARGS='
--label provider=virtualbox
'
CACERT=/var/lib/boot2docker/ca.pem
DOCKER_HOST='-H tcp://0.0.0.0:2376'
DOCKER_STORAGE=aufs
DOCKER_TLS=auto
SERVERKEY=/var/lib/boot2docker/server-key.pem
SERVERCERT=/var/lib/boot2docker/server.pem
</code></pre>

<p>To tell Docker to allow you to access an insecure registry you need to add the option to <code>EXTRA_ARGS</code> like so <code>--insecure-registry=[url]</code> like this:</p>

<pre><code>$ sudo vi /var/lib/boot2docker/profile

EXTRA_ARGS='
--label provider=virtualbox
--insecure-registry=myregistry.mydomain.com
'
CACERT=/var/lib/boot2docker/ca.pem
DOCKER_HOST='-H tcp://0.0.0.0:2376'
DOCKER_STORAGE=aufs
DOCKER_TLS=auto
SERVERKEY=/var/lib/boot2docker/server-key.pem
SERVERCERT=/var/lib/boot2docker/server.pem
</code></pre>

<p>Then just restart the docker daemon:</p>

<pre><code>$ sudo /etc/init.d/docker restart
</code></pre>

<p>You should now be able to <code>push</code> and <code>pull</code> using your registry. </p>]]></content:encoded></item><item><title><![CDATA[Nesting Docker Containers? Stop!]]></title><description><![CDATA[<p>In a recent blog post <a href="http://www.developmentalmadness.com/2016/02/27/working-with-docker/">I pointed out Docker is about microservices</a>, and you should compose your containers instead of building monolithic ones. I was referring to adding tools and utilities for troubleshooting and whatnot. But today I have an even better example: building Docker images from within a container!</p>]]></description><link>http://www.developmentalmadness.com/2016/03/05/nesting-docker-containers-stop/</link><guid isPermaLink="false">d14aae65-1d53-4557-9991-7f1723c2bcea</guid><category><![CDATA[Docker]]></category><category><![CDATA[Scala Build Tool (sbt)]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Sat, 05 Mar 2016 19:30:04 GMT</pubDate><content:encoded><![CDATA[<p>In a recent blog post <a href="http://www.developmentalmadness.com/2016/02/27/working-with-docker/">I pointed out Docker is about microservices</a>, and you should compose your containers instead of building monolithic ones. I was referring to adding tools and utilities for troubleshooting and whatnot. But today I have an even better example: building Docker images from within a container!</p>

<p><code>sbt</code> (<a href="http://www.scala-sbt.org/index.html">Scala interactive built tool</a>) has a plugin called <code>sbt-native-packager</code> which allows you to configure your project to be built and then packaged as a Docker container. Which means all I have to do is this:</p>

<pre><code>$ sbt docker:publish
</code></pre>

<p>And once my build finishes it will create the image and <code>push</code> it to whichever repository I've configured in my <code>build.sbt</code> file.</p>

<p>Except that most everyone on my team uses Windows. Which means that Java and sbt need to be installed on the Docker VM. But every time you restart your VM it gets wiped clean! </p>

<p>Because of this, instead of just using the small, default boot2docker vm that comes packaged so nicely for you with the Docker install everyone goes through the process of installing a full Ubuntu VM and then configuring and installing Docker, Java and sbt. </p>

<p>I'm against the whole give the new guy a Word document with setup instructions. It's part of why I like Docker so much. And this whole setup smells like we're going right back down that path. So today I found a much better way.</p>

<h1 id="siblingsinsteadofnesting">Siblings Instead of Nesting</h1>

<p>I can't claim credit for this, other than reading the documentation on the <a href="https://hub.docker.com/_/docker/">Docker-in-Docker (dind)</a> page on Docker Hub. Here's links to the two relevant posts:</p>

<ul>
<li><a href="https://docs.docker.com/engine/reference/run/#runtime-privilege-linux-capabilities-and-lxc-configuration">Using the <code>--privileged</code> flag</a> - Docker Run reference</li>
<li><a href="https://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/">Using Docker-in-Docker for your CI or testing environment? Think twice</a> - jpetazzo </li>
</ul>

<p>After reading those two posts I decided there was a much better way, and after learning <a href="http://www.developmentalmadness.com/2016/03/05/docker-permanently-mount-a-virtualbox-shared-folder/">how to make my VirtualBox shared folders permanent mounts</a> I went looking for a Docker image which already had Java and sbt installed for me.</p>

<p><strong>UPDATE (3/17/16):</strong> It was been pointed out that using shared folders is a security concern. This is correct. So let me add a disclaimer: the shared folders aspect of this post was included because I have been helping developers who thought they needed to install/configure all their build tools inside their Docker host in addition to their host OS so they could build their docker images. I'm not advocating shared folders in any other context.</p>

<h1 id="sharingdockerbinaries">Sharing Docker Binaries</h1>

<p>I settled on the excellent <a href="https://hub.docker.com/r/1science/sbt/">1science/sbt</a> image which is a mere 176 mb (not bad for an image with the Java SDK installed). There were three things I had to figure out to get all this to work together:</p>

<p>First, how to share the Docker binaries with the 1science/sbt container:</p>

<pre><code>$ docker run -it --rm -v "$HOME/.ivy2":/root/.ivy2 -v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/bin/docker 1science/sbt sbt sbt-version
</code></pre>

<p>Let's break this down a little:</p>

<ul>
<li><p><code>-it</code> allows us to run the container like <code>tty</code> to an <a href="https://docs.docker.com/engine/reference/run/#foreground">interactive shell</a>. If you left off <code>sbt-version</code> you'd be in the <code>sbt</code> interactive console.  </p></li>
<li><p><code>--rm</code> <a href="https://docs.docker.com/engine/reference/run/#clean-up-rm">removes the container</a> as soon as the command is over. This is helpful since we just want to run the command in the foreground and then exit.</p></li>
<li><p><code>-v "$HOME/.ivy2":/root/.ivy2</code> maps the Ivy cache to a host volume so the cache will persist between runs and allow our builds to run faster after the first time.</p></li>
<li><p><code>-v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/bin/docker</code> creates two more host mounted volumes that share the Docker binaries with the container. This is the most important piece since it's what allows <code>sbt</code> to build our container instead of just creating a <code>Dockerfile</code> for us to build ourselves.</p></li>
<li><p><code>$(which docker)</code> is an evaluated statement. In Linux <code>which</code> shows the full path of shell commands - so the output is the path to the docker command. We could look it up, but this makes the <code>run</code> command shorter.</p></li>
</ul>

<p>The next step took me the longest to figure out because the <code>README</code> for the <code>1science/sbt</code> image indicated I needed to something different. So either I was doing it wrong or the docs are wrong. Feel free to correct me we're in this journey together.</p>

<pre><code>$ docker run -it --rm -v "$HOME/.ivy2":/root/.ivy2 -v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/bin/docker -v $(pwd):/app 1science/sbt ls
</code></pre>

<p>This command doesn't do much more than the last (notice we're only calling <code>ls</code>). But we've added a volume for the root of our project: <code>-v $(pwd):/app</code>. If it worked correctly you should see your project root files listed in the output. This of course only works if your current working directory for the <code>run</code> command is the root of your source project. If not, replace <code>$(pwd)</code> with the path to your project root. It should be the path as seen by Docker, which means it's from the context of your Docker VM.</p>

<p>The reason we needed to map the volume here is because the <code>1science/sbt</code> image sets <code>/app</code> as the <code>WORKINGDIR</code> for the image. Any commands will be executed from the context of <code>/app</code> which is empty, so we just map our project root to <code>/app</code> and <code>sbt</code> will find everything it needs (almost).</p>

<p>Most of you should be able to run the following now from your project root:</p>

<pre><code>$ docker run -it --rm -v "$HOME/.ivy2":/root/.ivy2 -v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/bin/docker -v $(pwd):/app 1science/sbt sbt docker:publish
</code></pre>

<p>Or if you're not setup with a central registry yet use <code>publishLocal</code>:</p>

<pre><code>$ docker run -it --rm -v "$HOME/.ivy2":/root/.ivy2 -v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/bin/docker -v $(pwd):/app 1science/sbt sbt docker:publishLocal
</code></pre>

<p>If your <code>build.sbt</code> file is configured correctly your project will build as a Docker image and publish to your configured registry (Docker Hub is the default). However, if your project is a Play application created using <code>activator</code> then you probably are getting the following error:</p>

<blockquote>
  <p>sbt.ResolveException: unresolved dependency: com.typesafe.sbtrc#client-2-11;0.3.1: not found
  unresolved dependency: com.typesafe.sbtrc#actor-client-2-11;0.3.1: not found</p>
</blockquote>

<p>This is an <a href="https://github.com/playframework/playframework/issues/4839">open issue</a> due to some funkyness with <code>activator</code> that doesn't work out of the box with <code>sbt</code>. But it's easily fixed. Just add the following to your <code>build.sbt</code> file:</p>

<pre><code>resolvers += Resolver.url("Typesafe Ivy releases", url("https://repo.typesafe.com/typesafe/ivy-releases"))(Resolver.ivyStylePatterns)
</code></pre>

<p>And your build will be fixed. Repeat the above <code>run</code> command and this time it should work.</p>

<p>This post is certainly laking in any actual <code>sbt</code> details, but I didn't want it to be too long. I'll work through a very simple example using Scala and post it soon.</p>]]></content:encoded></item><item><title><![CDATA[Docker: Permanently Mount a VirtualBox Shared Folder]]></title><description><![CDATA[<p>While this technique works for both Windows and OSX, most Windows developers I know don't keep their source code in the <code>Users</code> folder on the system drive. Historically there have been too many problems:</p>

<ul>
<li>The path used to start with <code>C:\Documents and Settings\[USER_NAME]\</code></li>
<li><code>msbuild</code> blows up when</li></ul>]]></description><link>http://www.developmentalmadness.com/2016/03/05/docker-permanently-mount-a-virtualbox-shared-folder/</link><guid isPermaLink="false">61fcda79-c118-4e29-8745-4a67568220a9</guid><category><![CDATA[Docker]]></category><category><![CDATA[VirtualBox]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Sat, 05 Mar 2016 17:54:29 GMT</pubDate><content:encoded><![CDATA[<p>While this technique works for both Windows and OSX, most Windows developers I know don't keep their source code in the <code>Users</code> folder on the system drive. Historically there have been too many problems:</p>

<ul>
<li>The path used to start with <code>C:\Documents and Settings\[USER_NAME]\</code></li>
<li><code>msbuild</code> blows up when your path is longer than 256 characters</li>
<li>There's no convenient <code>~/</code> command-line shortcut when typing the path on the command-line.</li>
</ul>

<p>However, that's the only default path you get when you create a <code>boot2docker</code> image for VirtualBox. </p>

<p>In my <a href="http://www.developmentalmadness.com/2016/02/27/working-with-docker/">last post</a> I showed how to mount a VirtualBox shared folder but as soon as you restart (<em>that</em> never happens on a Windows box) you've lost it and have to create the mount all over again. </p>

<h1 id="mountasharedfolder">Mount a shared folder</h1>

<p>Just to review, so you don't have to read the last post: </p>

<ol>  
  <li>
    <p>Create a shared folder in VirtualBox:</p>
    <p><img src="https://s3-us-west-2.amazonaws.com/dvm-public-assets/images/2016/03_05/virtual-box-shared-folders.png"></p>
  </li>
  <li>
    <p><code>ssh</code> into your Guest OS (Docker VM):</p>
    

<pre>
$ docker-machine ssh defualt</pre>
  </li>
  <li>
    <p>Create a new folder for your mount:</p>
    

<pre>$ sudo mkdir -p /mnt/src</pre>
    <p>The <code>-p</code> is just in case <code>/mnt</code> doesn't already exist.</p>
  </li>
  <li>
    <p>Add your new mount:</p>
    

<pre>$ sudo mount -t vboxsf -o defaults,uid=`id -u docker`,gid=`id -g docker` src /mnt/src</pre>
    <p><code>id -u docker</code> and <code>id -g docker</code> will use the user id and group id respectively. You could just enter <code>1000</code> and <code>50</code> respectively and you'd be fine. I think the longer version is more clear and safe. 
</p><p>  
You should now be able to view the contents of your directory within your Docker VM:</p>  
    

<pre>$ ls /mnt/src</pre>
  </li>
</ol>

<h1 id="makeitpermanent">Make It Permanent</h1>

<p>The problem is everything gets erased whenever you restart your VM. What we need is a setup script that won't be erased and will run on startup. It turns out it's pretty easy. Create a file named <code>bootlocal.sh</code> at the following location:</p>

<pre><code>$ sudo touch /mnt/sda1/var/lib/boot2docker/bootlocal.sh
</code></pre>

<p>Now add the following to the file (no <code>sudo</code> needed):</p>

<pre><code>mkdir -p /mnt/src
mount -t vboxsf -o defaults,uid=`id -u docker`,gid=`id -g docker` src /mnt/src
</code></pre>

<p>Make sure you save and close the file. That's it! If you <code>exit</code> your <code>ssh</code> session, then restart your VM:</p>

<pre><code>$ docker-machine restart default
</code></pre>

<p>Once it's finished, log back in and verify it's there:</p>

<pre><code>$ docker-machine ssh default
$ ls /mnt/src
</code></pre>

<p>You should see the contents of your shared folder.</p>]]></content:encoded></item><item><title><![CDATA[Working with Docker]]></title><description><![CDATA[<p>Every developer has a workflow: how their environment is configured and how they access tools and resources. Personally, I have come to prefer lightweight tools and minimal setup.</p>

<p>I thought as I started working with Docker I would need to setup either a separate Linux box and remote into it</p>]]></description><link>http://www.developmentalmadness.com/2016/02/27/working-with-docker/</link><guid isPermaLink="false">f2dd8e43-d174-47db-acf6-57e7b148ac6d</guid><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Sat, 27 Feb 2016 00:02:11 GMT</pubDate><content:encoded><![CDATA[<p>Every developer has a workflow: how their environment is configured and how they access tools and resources. Personally, I have come to prefer lightweight tools and minimal setup.</p>

<p>I thought as I started working with Docker I would need to setup either a separate Linux box and remote into it or install a full-size VM which would steal RAM and disk space and reserve CPU cores. Since I've always worked mostly on a laptop I was concerned about how I would have enough hardware to run everything I needed without always having to free up disk space and memory.</p>

<p>Now that I've been using it I realize how unfounded my fears were. Even though changing to a bare metal Linux install would mean I could get rid of VirtualBox and <code>docker-machine</code> I find once I get started they disappear into the background. I still have to use VirtualBox but the default Docker VM is only using 1GB of memory and a single CPU. Because of this change of perspective I thought it would be nice to share my workflow. It may help someone else and I may get some tips to improve my own.</p>

<p>I am assuming at this point you have already installed Docker by following their <a href="http://docs.docker.com/mac/started/">quickstart</a>.</p>

<h1 id="thetools">The Tools</h1>

<p>We're going to use only two command-line utilities here in this walk-through:</p>

<ul>
<li><strong>docker:</strong> This is the docker client. This is your main tool and what you will use for all things that relate to using and creating Docker images and containers.</li>
<li><strong>docker-machine:</strong> This is for managing the host machines where the Docker daemon is running. </li>
</ul>

<p>Just running either utility from the command line with no arguments will give you a list of commands and idea what each tool is for. I suggest you take a minute and just read through the output for each of the two and then come back here - I'll wait.</p>

<h1 id="loadingthedockerenvironment">Loading the Docker Environment</h1>

<p>When you fire up a fresh bash shell on Windows or OSX before you can start using commands to the docker interface you need to connect it do the docker daemon. Otherwise you'll get the following error:</p>

<blockquote>
  <p>Cannot connect to the Docker daemon. Is the docker daemon running on this host?</p>
</blockquote>

<p>As long as you've installed everything this means you forgot to initialize your session. You can check by running:</p>

<pre><code>$ docker-machine ls
NAME      ACTIVE   URL          STATE     URL                         SWARM   DOCKER    ERRORS
default   -        virtualbox   Running   tcp://192.168.99.100:2376           v1.10.0
</code></pre>

<p>If you notice the <code>-</code> under <code>ACTIVE</code> that means your terminal/console environment isn't configured to connect to the docker daemon. If you're running in terminal on OSX or Git Bash you can fix this by running:</p>

<pre><code>$ eval "$(docker-machine env default)"
</code></pre>

<p>Assuming the default installation then you probably have a machine named <code>default</code> (the value under <code>NAME</code> when you run <code>docker-machine ls</code>). Otherwise for the instructions that follow replace <code>default</code> with the name of whatever machine you may have setup in VirtualBox.</p>

<p>If you're using Windows I recommend using Git Bash which is installed along with Docker. Not only is it useful for things like SSH in Windows but as you follow Docker tutorials there will be fewer differences than using Powershell or Command Prompt. For example, I find the default color scheme unreadable when I need to list the contents of a directory in my Docker host (more on that later). I could change it but since I prefer Git Bash I haven't bothered. Also, <code>eval</code> won't work. You'll need to run the following command from either command line:</p>

<pre><code>&gt; docker-machine env default 
</code></pre>

<p>And the result will tell you the command you need to run. Here's what that ends up looking like</p>

<p><strong>Powershell</strong></p>

<pre><code>&gt; docker-machine env default
$Env:DOCKER_TLS_VERIFY = "1"
$Env:DOCKER_HOST = "tcp://192.168.99.100:2376"
$Env:DOCKER_CERT_PATH = "C:\Users\[USER_NAME]\.docker\machine\machines\default"
$Env:DOCKER_MACHINE_NAME = "default"
# Run this command to configure your shell:
# &amp; "C:\Program Files\Docker Toolbox\docker-machine.exe" env default | Invoke-Expression
</code></pre>

<p>Based on that output you would run:</p>

<pre><code>&gt; docker-machine env default | Invoke-Expression
</code></pre>

<p><strong>Windows Command Prompt</strong></p>

<pre><code>&gt; docker-machine env default
SET DOCKER_TLS_VERIFY=1
SET DOCKER_HOST=tcp://192.168.99.100:2376
SET DOCKER_CERT_PATH=C:\Users\[USER_NAME]\.docker\machine\machines\default
SET DOCKER_MACHINE_NAME=default
REM Run this command to configure your shell:
REM     FOR /f "tokens=*" %i IN ('docker-machine env default') DO %i
</code></pre>

<p>And here you would run: </p>

<pre><code>FOR /f "tokens=*" %i IN ('docker-machine env default') DO %i
</code></pre>

<p>Once you've done that you can run <code>docker-machine ls</code> again and you should now see the following:</p>

<pre><code>NAME      ACTIVE   URL          STATE     URL                         SWARM   DOCKER    ERRORS
default   *        virtualbox   Running   tcp://192.168.99.100:2376           v1.10.0
</code></pre>

<p>Or you can run <code>docker-machine active</code> and it will simply print either the name of the active machine or <code>No active host found</code>.</p>

<p>Notice that you should now see <code>*</code> under <code>ACTIVE</code>. Now you're connected and should be able to run commands against the docker daemon. The good news is that all docker clients should use the same commands with a couple caveats that I'll point out as we go along.</p>

<h1 id="whichcontext">Which Context?</h1>

<p>I'm not sure if "context" is the right term here, but I'm hoping it conveys my meaning.</p>

<p>When your native environment is Windows or OSX you have a different context than if it's Linux. Where it bit me first was my first experience with <a href="https://docs.docker.com/engine/userguide/dockervolumes/">volumes</a>. When you are trying to map files between your host environment and a container's environment the tutorials I've seen always seem to be assuming how it will work in your production environment - which is running in a native Linux environment. But this trips up the uninitiated.</p>

<p>In Windows the <code>C:\Users</code> directory for your host file system is mounted into the Docker VM at <code>/c/Users</code>. In OSX the <code>/Users</code> path is mounted at <code>/Users</code> making the translation easy. You can confirm this in the VirtualBox Shared Folder settings for your virtual machine. In each case it requires you to be aware of something different.</p>

<ul>
<li>Windows: you have to translate paths from <code>C:\Users\</code> to '/c/Users/' (lowercase <code>c</code>).</li>
<li>OXS: No translation of paths, but if you want to share files outside of <code>/Users/</code> you need to share them using VirtualBox, ensure they're mounted and use the path as the Docker VM sees it.</li>
</ul>

<p>When you're working with your application files this is just something you need to understand and work with. You need to just remember that Docker is running inside a Linux VM, so it can't see your Windows or OSX file system. This can trip you up sometimes, but what find helps a lot is to work in the context of the Docker host (the VM). Here's how you do it:  </p>

<pre>
    $ docker-machine ssh default
                        ##         .
                      ## ## ##        ==
                   ## ## ## ## ##    ===
               /"""""""""""""""""\___/ ===
          ~<del> {</del> ~~<del> </del>~ ~~<del> </del>~ ~ /  ===- ~~~
               \&#95;&#95;&#95;&#95;&#95;&#95; o           __/
                 \    \         __/
                  \&#95;&#95;&#95;&#95;\&#95;&#95;&#95;&#95;&#95;&#95;&#95;/
     _                 _   &#95;&#95;&#95;&#95;     _            _
    | |__   ___   ___ | |_|___ \ __| | ___   ___| | &#95;&#95;&#95;&#95;&#95; _ __
    | '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
    | |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
    |_.__/ \___/ \___/ \__|&#95;&#95;&#95;&#95;&#95;\__,_|\___/ \___|_|\_\___|_|
    Boot2Docker version 1.10.0, build master : b09ed60 - Thu Feb  4 20:16:08 UTC 2016
    Docker version 1.10.0, build 590d5108

</pre>

<p>Now except for the files hosted in your native environment it's really not different than if you were running natively on Linux. </p>

<h1 id="runningcontainers">Running Containers</h1>

<p>This is pretty well documented, but this wouldn't be a proper walk-through unless we started up a container and pointed out a few things.</p>

<p>First, lets just fire up a container:</p>

<pre><code>$ docker run -d -P nginx
</code></pre>

<p>The <code>-d</code> runs the container in the background - which is what you want most of the time. If you leave it off the output of the <code>docker logs</code> command will tail to your console. That's not what we want at the moment so we'll leave it at that.</p>

<p>Once it's done the output to your console will look something like this:</p>

<pre><code>Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
5c9a73b9c4ad: Pull complete 
152440d1ba68: Pull complete 
cd0794b5fd94: Pull complete 
18de280c0e54: Pull complete 
bf58831fd41c: Pull complete 
ae8e1e9c54b3: Pull complete 
Digest: sha256:83be29bb91fc47f3a7453fc51db66816c9c637131f302a83dfd136e4b1901fbe
Status: Downloaded newer image for nginx:latest
468a6404cfcc1240750866608b51cd41a8465315767605634b272f0eddca1b2d
</code></pre>

<p>That last long string of numbers is the container's hash, or id. But don't worry, you don't ever need to type out the whole thing - just enough of the numbers to uniquely identify it. Which means if there's only one container running, or none of the other containers start with the same character, then you can identify it by a single character like this:</p>

<pre><code>$ docker logs 4
</code></pre>

<p>Where <code>4</code> is the first character of the container id.</p>

<p>But there are other, more friendly ways to reference a container. For example:</p>

<pre><code>$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                           NAMES
468a6404cfcc        nginx               "nginx -g 'daemon off"   48 seconds ago      Up 47 seconds       0.0.0.0:32769-&gt;80/tcp, 0.0.0.0:32768-&gt;443/tcp   berserk_kalam
</code></pre>

<p>See that shortened <code>CONTAINER ID</code>? You can look it up anytime you need to like we just did. But there's some other interesting information here as well. Under name can you see <code>berserk_kalam</code>? Yours will most likely be something else. That's the random name assigned to every container unless you specify the <code>--name</code> option. So you can follow along it will be easier if we can use the exact same commands. So you can run this:</p>

<pre><code>$ docker run -d -P --name www nginx
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                           NAMES
7ecb60689494        nginx               "nginx -g 'daemon off"   4 seconds ago       Up 3 seconds        0.0.0.0:32771-&gt;80/tcp, 0.0.0.0:32770-&gt;443/tcp   www
468a6404cfcc        nginx               "nginx -g 'daemon off"   20 minutes ago      Up 20 minutes       0.0.0.0:32769-&gt;80/tcp, 0.0.0.0:32768-&gt;443/tcp   berserk_kalam
</code></pre>

<p>You'll see a second container and under the name you'll see <code>www</code>. </p>

<p>You may have also noticed under <code>PORTS</code> that a couple of high ports are pointing to ports <code>80</code> and <code>443</code>. Well those high ports are the ports that your Docker host is listening on, then those ports are mapped to <code>80</code> and <code>443</code> which are exposed by the container. So if we want to actually talk to our container we need to use the high ports. But at which IP? If you open your web browser right now and put in <a href="http://localhost:32771">http://localhost:32771</a> you'll see this:</p>

<p><img src="https://s3-us-west-2.amazonaws.com/dvm-public-assets/images/2016/02_28/www-not-available.png" alt="www-not-available"></p>

<p>What we need is the IP of the Docker VM running in VirtualBox. So we want to run this:</p>

<pre><code>$ docker-machine ip default
192.168.99.100
</code></pre>

<p>Which returns the IP we want. Now if we put that IP into our browser like before at <a href="http://192.168.99.100:32771">http://192.168.99.100:32771</a> we should see this:</p>

<p><img src="https://s3-us-west-2.amazonaws.com/dvm-public-assets/images/2016/02_28/www-welcome-to-nginx.png" alt="www-welcome-to-nginx"></p>

<p>Those port mappings we're using were assigned randomly by Docker because we used the <code>-P</code> option. If we had omitted it, we couldn't access our nginx at all. But what if we wanted to use a specific port? We could use 80, or any other port. But since this is the only web service running on our container we'll go ahead and use 80. There is a way to change the port of a running container, but it's easier to just create a new one:</p>

<pre><code>$ docker stop www
$ docker rm -v www
$ docker run -d -p 80:80 -p 443:443 --name www nginx
</code></pre>

<p>You should now be able to access nginx from your web browser using the default port <code>80</code>:</p>

<p><img src="https://s3-us-west-2.amazonaws.com/dvm-public-assets/images/2016/02_28/www-nginx-port-80.png" alt="www-nginx-port-80"></p>

<h1 id="sharedfolders">Shared Folders</h1>

<p><strong>Update 3/05/16:</strong> I've written an <a href="http://www.developmentalmadness.com/2016/03/05/docker-permanently-mount-a-virtualbox-shared-folder/">addition post</a> that reviews shared folders and shows you how to make them permanent.</p>

<p>I mentioned before that by default the OSX <code>/Users</code> directory and the Windows <code>C:\Users</code> directory are mapped by default so your default means of synchronizing files between your Host OS and your VM is to use some subdirectory under the appropriate path. However, not everybody uses those path hierarchies for their development files. As a long-time Windows developer I always needed to conserve every possible path character to stay below the dreaded 256 character limit for paths accessed by <code>msbuild</code>. So I developed a habit of putting all my source code under <code>C:\dev\src</code> instead of <code>C:\Documents and Settings\[USER_NAME]</code> or even <code>C:\Users\[USER_NAME]</code> was too much. Now that my primary system is OSX it matters less but here's how to map shared folders: </p>

<ol>  
  <li>
   Open your 'Shared Folders' settings in VirtualBox for your Docker VM:

<img src="https://s3-us-west-2.amazonaws.com/dvm-public-assets/images/2016/02_28/virtual-box-shared-folders.png" alt="virtual-box-shared-folders">
  </li>
  <li>
    <p>
    Select the path that you would like to share with your Docker VM and accept the default name or change it as you see I've done above.
    </p>
  </li>
  <li>
    Next you'll want to <code>ssh</code> into your Docker VM like I mentioned earlier:
    

<pre>
    $ docker-machine ssh default    </pre>
  </li>
  <li>
    <p>
    Now you want to create a mount point for your shared folder:

    

<pre>$ sudo mkdir /mnt/src
</pre>

    I named mine <code>src</code> just like I did in the VirtualBox Shared Folder settings, but the names don't have to match here, just in the next step. I placed it in the <code>mnt</code> directory which is a convention to follow but you could put it at the root of the file system <code>/</code> if you like - just don't clash with any other directory names.
    </p>
  </li>
  <li>
    <p>
    Now we mount the folder using the name from the Shared Folder settings and then the mount point we just created with the <code>mkdir</code> command:

    

<pre>$ mount -t vboxsf -o uid=1000,gid=50 src /mnt/src</pre>

    The first <code>src</code> is the name I used in the VirtualBox Shared Folder settings and the <code>/mnt/src</code> is the directory I created with <code>mkdir</code> for the mount point. 
    </p>
  </li>
  <li>
    You should now be able to verify that your share is mounted by viewing the contents of the mount like this:

    

<pre>$ ls /mnt/src
dvMENTALmadness/ scratchpad/
</pre>
  <p>
    Which shows the two folders I have underneath my shared folder. When you edit files in either the Host OS or the Docker VM the file will stay in sync - just be aware that Windows and Linux use different line endings so if you edit Windows files inside your Docker VM you may get some issues with line endings.
  </p>
  <p>
    You'll also want to make sure that the permissions on your Host OS allow the VirtualBox VM to access the directory. For example, in OSX if you want to create a directory at your file system root called <code>my-dev</code> you'd have to do this:

    

<pre>$ sudo mkdir /my-dev</pre>

    In order to grant write access from within your Docker VM you'd have to run the following two commands from your OSX terminal:

    

<pre>$ sudo chown [your-user-name] /my-dev
$ sudo chown :staff /my-def</pre>

    Which would make the directory permissions match those in your <code>/Users/[your-user-name]</code>
  </p></li>
</ol>

<h1 id="packagemanager">Package Manager</h1>

<p>I love package managers. They make setting up software clean and repeatable. So when I started using Docker I started trying to install tools in my Docker VM and then opening up a bash shell into my containers as well and trying to install tools there as well. But it was supremely frustrating because even though I can easily use a package manager (usually <code>apt-get</code>) inside any <code>Dockerfile</code> to install tools for my container it isn't available from inside my running host or container! Instead the only package manager is <code>tce-load</code> and I found I couldn't just translate my <code>apt-get</code> knowledge directly to use it - plus not all the packages are even there!</p>

<p>I wondered if I could use a different ISO image for VirtualBox? (<a href="https://docs.docker.com/machine/drivers/os-base/">Yes, you can</a>). But before I got around to it I came to a realization: You don't want to use the package manager inside containers. You either need a new image with the tools already installed, or you need a separate, linked container with the tools installed instead of muddying your container. <strong>Docker is about microservices - Don't create monolithic containers</strong></p>

<p>So I don't use the package manager. Docker provides tools like <code>--volumes-from</code> and <code>--link</code> (still available, but deprecated) and <a href="https://docs.docker.com/engine/reference/run/#network-settings">network settings</a> to allow containers to interact with each other in defined ways - including adhoc administration and troubleshooting. </p>

<p>For example, if your container doesn't have a text editer like <code>vi</code> installed, don't install it in your container! You should have a separate image with <code>vi</code> installed, when you need to edit files in your container, <code>run</code> the image with <code>vi</code> and use the <code>--volumes-from</code> option to link the files in the two containers. Then you can use <code>docker exec</code> to access the container with <code>vi</code> installed and edit the files. <strong>NOTE:</strong> I'm not really advocating the direct editing of files in production (I would NEVER do that! :P ), this is just a simple and easy to understand example.</p>

<p>I'll write a post later demonstrating these principles. This one is already long enough, but I had to make the point.</p>

<h1 id="gettinginsideacontainer">Getting Inside a Container</h1>

<p>Even taking into account the previous section, you often need to get into a container to see what's going on in there. When I first started everything I googled seemed to point to <code>NSENTER</code>. So I started by using that and completely missed <code>docker exec</code>, which is the now recommended way to access a container. </p>

<p>If I wanted to open up a bash shell directly inside a running container I would do it like this:</p>

<pre><code>$ docker exec -it [container_name_or_id] bash
</code></pre>

<p>Where <code>container_name_or_id</code> would be either the name of the container (usually the <code>--name</code> option in the <code>run</code> command) or the unique portion of the container's hash id.</p>

<p>So if I were running a container for my postgres database that was created from the following command:</p>

<pre><code>docker run --name pg-scratchpad -e POSTGRES_PASSWORD=$DB_PG_PWD -p 5432:5432 -v /var/lib/postgresql/data -d postgres
</code></pre>

<p><strong>NOTE:</strong> For an explaination of the use of <code>$DB_PG_PWD</code> see: <a href="http://www.developmentalmadness.com/2016/02/18/security-theres-a-password-in-my-repository/">There's a password in my repository</a>.</p>

<p>Then I could open a command prompt inside the container like this:</p>

<pre><code>$ docker exec -it pg-scratchpad bash
</code></pre>

<p>Or to briefly demonstrate using a linked container, you could open up the <code>psql</code> command-line client like this:</p>

<pre><code>docker run -it --link pg-scratchpad:postgres --rm postgres sh -c 'exec psql -h "$POSTGRES_PORT_5432_TCP_ADDR" -p "$POSTGRES_PORT_5432_TCP_PORT" -U postgres'
</code></pre>

<p>Which will create a second container, and open a shell prompt for you which is already connected to your postgres database in the <code>pg-scratchpad</code> container!</p>

<h2 id="persistentdata">Persistent Data</h2>

<p>If I don't tell you, you may find one day that after you restart your container (or your whole computer) that your data is gone! Well that's because by default data doesn't survive restarting the container. I'll try to be quick here and save the details for later, but there are a couple solutions:</p>

<h3 id="betweenrestarts">Between restarts</h3>

<p><a href="https://docs.docker.com/engine/userguide/containers/dockervolumes/">Volumes</a> provide the solution to persistence. At least that's part of what they do. You just saw an example of it when we created our postgres container above. </p>

<pre><code>docker run --name pg-scratchpad -e POSTGRES_PASSWORD=$DB_PG_PWD -p 5432:5432 -v /var/lib/postgresql/data -d postgres
</code></pre>

<p>See that <code>-v /var/lib/postgresql/data</code>? That tells Docker to create a persistent volume for that container. If you create data in your database, then restart your container, that data will still be there. Without <code>-v</code> your data will disappear!</p>

<h3 id="betweenredeploys">Between re-deploys</h3>

<p>Except that once that container is removed nothing else can reference that data volume and it's gone! But there's a solution: <a href="https://docs.docker.com/engine/userguide/containers/dockervolumes/#creating-and-mounting-a-data-volume-container">Data Volume Containers</a>. They work under the principle that as long as a container is referencing a volume it can still be accessed. Another interesting tidbit is that a container doesn't have to be running for another container to use it's volumes!</p>

<p>So we can create a data volume container like this:</p>

<pre><code>$ docker create -v /var/lib/postgresql/data --name pg-data postgres
</code></pre>

<p>Then we can use it like this:</p>

<pre><code>$ docker run -d --volumes-from pg-data --name pg-db -e POSTGRES_PASSWORD=$DB_PG_PWD -p 5432:5432 postgres
</code></pre>

<p>If we connect like this:</p>

<pre><code>$ docker run -it --link pg-db:postgres --rm postgres sh -c 'exec psql -h "$POSTGRES_PORT_5432_TCP_ADDR" -p "$POSTGRES_PORT_5432_TCP_PORT" -U postgres'
</code></pre>

<p>Then we can create some data:</p>

<pre><code># CREATE TABLE my_table (my_column VARCHAR(64) NOT NULL);
# INSERT INTO my_table (my_column) VALUES ('Docker');
</code></pre>

<p>Make sure it's there:</p>

<pre><code># SELECT * FROM my_table;
 my_column 
-----------
 Docker
(1 row)
</code></pre>

<p>Then destroy everything but the data volume container:</p>

<pre><code># \q
$ docker stop pg-db
$ docker rm -v pg-db
</code></pre>

<p>And then create a new container - we'll call it <code>pg-db-2</code> just to be explicit this is a new container:</p>

<pre><code>$ docker run -d --volumes-from pg-data --name pg-db-2 -e POSTGRES_PASSWORD=$DB_PG_PWD -p 5432:5432 postgres
</code></pre>

<p>And then verify the data is there:</p>

<pre><code>$ docker run -it --link pg-db-2:postgres --rm postgres sh -c 'exec psql -h "$POSTGRES_PORT_5432_TCP_ADDR" -p "$POSTGRES_PORT_5432_TCP_PORT" -U postgres'

# SELECT * FROM my_table;
 my_column 
-----------
 Docker
(1 row)
</code></pre>

<h1 id="conclusion">Conclusion</h1>

<p>I'm sure you never thought we'd get here. There's much more to Docker - we didn't even create our own custom container. But that should be enough to get you started on solid footing if you understand everything we just covered. For a broader coverage of Docker checkout this <a href="https://github.com/wsargent/docker-cheat-sheet">Docker cheat sheet on Github</a>.</p>]]></content:encoded></item><item><title><![CDATA[scala: Connecting to Postgres via Slick 3]]></title><description><![CDATA[<p>Got <a href="http://slick.typesafe.com/">Slick</a> working with <a href="http://www.postgresql.org/">Postgres</a> this morning and I thought I'd just write it up before I forget. I'm assuming you already know how to create a new <a href="http://www.scala-lang.org/">scala</a> project that uses <a href="http://www.scala-sbt.org/">sbt</a> for build and dependencies.</p>

<h2 id="environmentvariables">Environment Variables</h2>

<p>For this post you'll need the following environment variables setup:</p>

<pre><code>DB_</code></pre>]]></description><link>http://www.developmentalmadness.com/2016/02/23/scala-connecting-to-postgres-via-slick-3/</link><guid isPermaLink="false">b33b0925-5f9f-4b87-a4ef-cab02ae41a58</guid><category><![CDATA[Postgresql]]></category><category><![CDATA[scala]]></category><category><![CDATA[Typesafe Slick]]></category><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Mark J Miller]]></dc:creator><pubDate>Tue, 23 Feb 2016 20:16:05 GMT</pubDate><content:encoded><![CDATA[<p>Got <a href="http://slick.typesafe.com/">Slick</a> working with <a href="http://www.postgresql.org/">Postgres</a> this morning and I thought I'd just write it up before I forget. I'm assuming you already know how to create a new <a href="http://www.scala-lang.org/">scala</a> project that uses <a href="http://www.scala-sbt.org/">sbt</a> for build and dependencies.</p>

<h2 id="environmentvariables">Environment Variables</h2>

<p>For this post you'll need the following environment variables setup:</p>

<pre><code>DB_PG_URL="jdbc:postgresql://192.168.99.100:5432"
DB_PG_USER=postgres
DB_PG_PWD=12345
</code></pre>

<p><a href="http://www.developmentalmadness.com/2016/02/18/security-theres-a-password-in-my-repository/">I've explained why here</a>. And here's more information about <a href="https://docs.docker.com/engine/reference/run/#env-environment-variables">Docker and environment variables</a>.</p>

<p>The above IP address <code>192.168.99.100</code> will depend on your setup. If you're running an installation of postgres (localhost or remote) you'll use the IP or hostname you use to reach that instance. If you're following along, using <a href="https://www.docker.com/">Docker</a> you'll need the IP address returned from <code>docker-machine</code> (assuming either OSX or Windows):</p>

<pre><code>$ docker-machine ls

NAME      ACTIVE   DRIVER       STATE     URL                         SWARM
default   *        virtualbox   Running   tcp://192.168.99.100:2376   
</code></pre>

<p>Whatever the IP returned for URL is what you'll use in the environment var <code>DB_PG_URL</code>.</p>

<p>The remaining Docker commands assume you have a VM named <code>default</code>. If not you'll need to substitute <code>default</code> with the name of your VM - or create a VM named <code>default</code>.</p>

<p>Also, to avoid the need to include separate instructions based on your VM host OS the remaining commands assume you are running a terminal session inside your Docker host, like this:</p>

<pre><code>$ docker-machine ssh default
</code></pre>

<p>Once you run that command your terminal/console window context will be <em>inside</em> your Docker host.</p>

<h2 id="postgressetup">Postgres setup</h2>

<p>If you don't have postgres installed already, then go do that. Or if you have Docker installed, then you can just execute the following Docker <code>run</code> command and you're already done! Here's the official page for the <a href="https://hub.docker.com/_/postgres/">Docker postgres image</a>.</p>

<pre><code>$ docker run --name pg-scratchpad -e POSTGRES_PASSWORD=$DB_PG_PWD -p 5432:5432 -v /var/lib/postgresql/data -d postgres
</code></pre>

<p>If you're still new to Docker the short explanation is that the command will start an installation of postgres in a new container (<code>run</code>) over port 5432 (<code>-p</code>) with a persistent volume (<code>-v</code>) running in the background (<code>-d</code>).</p>

<p>That <code>-e POSTGRES_PASSWORD=$DB_PG_PWD</code> is a password I've stored as an environment variable. </p>

<h2 id="creatingsomedata">Creating some data</h2>

<p>You'll need to connect to postgres somehow. If you're using a local install of postgres then you'll want to run <code>psql</code> from the command line. For those of us running Docker try this:</p>

<pre><code>docker run -it --link pg-scratchpad:postgres --rm postgres sh -c 'exec psql -h "$POSTGRES_PORT_5432_TCP_ADDR" -p "$POSTGRES_PORT_5432_TCP_PORT" -U postgres'
</code></pre>

<p>We're creating a second container here and linking it to our <code>pg-scratchpad</code> container where our database instance is running. <code>-it</code> sets up an interactive shell that is using the link between containers and running the <code>psql</code> command. This will give us a client where we can setup our database. The above command came from the documentation for the <a href="https://hub.docker.com/_/postgres/">Docker postgres image</a>.</p>

<p>Like any ORM, Slick let's you define your model in code or config and it will create it for you. But for my purposes I wanted to work under the assumption I had an existing database. So we'll create a simple schema, put some data in it and use Slick to query the table.</p>

<p>So run the following commands in your psql session (<code>#</code> is just the command prompt - don't type it, but do make sure to terminate each command with a semi-colon (<code>;</code>)):</p>

<pre><code># CREATE TABLE records (
  id INT NOT NULL,
  value VARCHAR(64) NOT NULL
);

# INSERT INTO records (id, value) VALUES (1, 'booyah!');
</code></pre>

<p>If you run a query you should get some data back. As long as you do you're set:</p>

<pre><code># SELECT * FROM records;
</code></pre>

<p>Your results should look like this:</p>

<pre><code> id |     value      
----+----------------
  1 | booyah!
(1 row)
</code></pre>

<h1 id="sbtsetup">sbt setup</h1>

<p>Your <code>build.sbt</code> file should include the following dependencies:</p>

<pre><code>libraryDependencies ++= List(
// ... your other dependencies
  "com.typesafe.slick" %% "slick" % "3.0.0",
  "org.postgresql" % "postgresql" % "9.4-1201-jdbc41",
  "com.zaxxer" % "HikariCP" % "2.4.1"
)
</code></pre>

<p><strong>NOTE:</strong> HikariCP is a "non-optional" dependency for Slick.</p>

<p>I'm not sure what <code>HikariCP</code> is for but I get a runtime error if it isn't there. As for <code>slick</code> and <code>postgresql</code>, the former is a Functional ORM which supports streaming and back-pressure and the latter is the postgresql client library and drivers Slick needs to connect to your database instance.</p>

<h2 id="configuration">Configuration</h2>

<p>Create an <code>application.conf</code> file under <code>src/main/resources</code> in your source tree. Here's how you'll configure it:</p>

<pre><code>pg-postgres = {
  url = ${DB_PG_URL}/postgres
  user = ${DB_PG_USER}
  password = ${DB_PG_PWD}
  driver = org.postgresql.Driver
}
</code></pre>

<h2 id="caseclassmapping">Case class mapping</h2>

<p>Add a new scala class to your project and call it <code>Tables.scala</code>. The name is arbitrary although it does follow the convention used by the Slick Code Generator. </p>

<pre><code>import slick.driver.PostgresDriver.api._

case class record(id: Int, value: String)

class Records(tag: Tag) extends Table[record](tag, "records") {
  def id = column[Int]("id")
  def value = column[String]("value")
  def * = (id, value) &lt;&gt; (record.tupled, record.unapply)
}
</code></pre>

<p>Here we've mapped a case class and class structure to match our database table. Most of this is pretty self-explanatory except for the <code>def * = ...</code>. That function allows Slick to map back and forth between our case class <code>record</code> and the database.</p>

<h2 id="runningaquery">Running a query</h2>

<p>Now add a new scala class to your project and call it <code>MyApp.scala</code>. Enter the following <code>object</code> definition:</p>

<pre><code>import slick.driver.PostgresDriver.api._
import scala.concurrent.Await
import scala.concurrent.duration.Duration

object MyApp extends App {
  val query = TableQuery[Records]
  val db = Database.forConfig("pg-postgres")
  try{
    Await.result(db.run(DBIO.seq(
      query.result.map(println)
    )), Duration.Inf)
  } finally db.close
}
</code></pre>

<p>Now run MyApp and you should see something like the following:</p>

<pre><code>Vector(record(1,booyah!))
</code></pre>

<p>This doesn't cover querying or anything else of the sort, but now that you're started you've finished the hard part ;).</p>

<h2 id="slickcodegenerator">Slick Code Generator</h2>

<p>As an bonus, it could be valuable to see what gets generated by different table structures.  Add the following dependency to your <code>build.sbt</code>:</p>

<pre><code>  "com.typesafe.slick" %% "slick-codegen" % "3.0.2" % "provided"
</code></pre>

<p>Now from the command line execute <code>sbt console</code> to drop into the scala REPL. Then enter the following:</p>

<p>First create a variable for each of your environment variables:</p>

<pre><code>scala&gt; val url = System.getenv("DB_PG_URL") + "/postgres"
url: String = jdbc:postgresql://192.168.99.100:5432/postgres

scala&gt; val user = System.getenv("DB_PG_USER")
user: String = postgres

scala&gt; val pwd = System.getenv("DB_PG_PWD")
pwd: String = 1qaz2wsx
</code></pre>

<p>Then call the Slick Code Generator like this:</p>

<pre><code>scala&gt; slick.codegen.SourceCodeGenerator.main(Array("slick.driver.PostgresDriver", "org.postgresql.Driver", url, "src/main/scala", "com.dvMENTALmadness", user, pwd))
</code></pre>

<p>The first two arguments are the slick and postgres drivers respectively. Next, pass in your <code>url</code> variable to point to your database instance. Then <code>src/main/scala</code> is the relative path from my sources root where I want my <code>Tables.scala</code> file created and <code>com.dvMENTALmadness</code> is my package name. Lastly pass in the <code>user</code> and <code>pwd</code> variables so the code generator can authenticate with postgres.</p>

<p>Once the script runs you should find (assuming you're using the above paramters) a new file: <code>src/main/scala/com/dvMENTALmadness/Tables.scala</code> created and the content should look something like this:</p>

<pre><code>package com.dvMENTALmadness
// AUTO-GENERATED Slick data model
/** Stand-alone Slick data model for immediate use */
object Tables extends {
  val profile = slick.driver.PostgresDriver
} with Tables

/** Slick data model trait for extension, choice of backend or usage in the cake pattern. (Make sure to initialize this late.) */
trait Tables {
  val profile: slick.driver.JdbcProfile
  import profile.api._
  import slick.model.ForeignKeyAction
  // NOTE: GetResult mappers for plain SQL are only generated for tables where Slick knows how to map the types of all columns.
  import slick.jdbc.{GetResult =&gt; GR}

  /** DDL for all tables. Call .create to execute. */
  lazy val schema = Record.schema
  @deprecated("Use .schema instead of .ddl", "3.0")
  def ddl = schema

  /** Entity class storing rows of table Record
   *  @param id Database column id SqlType(int4)
   *  @param value Database column value SqlType(varchar), Length(64,true) */
  case class RecordRow(id: Int, value: String)
  /** GetResult implicit for fetching RecordRow objects using plain SQL queries */
  implicit def GetResultRecordRow(implicit e0: GR[Int], e1: GR[String]): GR[RecordRow] = GR{
    prs =&gt; import prs._
    RecordRow.tupled((&lt;&lt;[Int], &lt;&lt;[String]))
  }
  /** Table description of table record. Objects of this class serve as prototypes for rows in queries. */
  class Record(_tableTag: Tag) extends Table[RecordRow](_tableTag, "record") {
    def * = (id, value) &lt;&gt; (RecordRow.tupled, RecordRow.unapply)
    /** Maps whole row to an option. Useful for outer joins. */
    def ? = (Rep.Some(id), Rep.Some(value)).shaped.&lt;&gt;({r=&gt;import r._; _1.map(_=&gt; RecordRow.tupled((_1.get, _2.get)))}, (_:Any) =&gt;  throw new Exception("Inserting into ? projection not supported."))

    /** Database column id SqlType(int4) */
    val id: Rep[Int] = column[Int]("id")
    /** Database column value SqlType(varchar), Length(64,true) */
    val value: Rep[String] = column[String]("value", O.Length(64,varying=true))
  }
  /** Collection-like TableQuery object for table Record */
  lazy val Record = new TableQuery(tag =&gt; new Record(tag))
}
</code></pre>

<p>Play around with it, create multiple tables, add joins then re-run the generator and see what you get - it should be instructive. Your query will change slightly to look like this instead:</p>

<pre><code>Tables.Record.result.map(println)
</code></pre>

<p>But your result should be the same. Enjoy!</p>]]></content:encoded></item></channel></rss>