<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

	<title>Alan Cruikshanks</title>
	<link href="http://cruikshanks.co.uk/atom.xml" rel="self"/>
	<link href="http://cruikshanks.co.uk/"/>
	<updated>2021-09-01T18:17:29+00:00</updated>
	<id>http://cruikshanks.co.uk/</id>
	<author>
		<name>Alan Cruikshanks</name>
		<email>alan.cruikshanks@gmail.com</email>
	</author>

	
		<entry>
			<title>Docker for development</title>
			<link href="http://cruikshanks.co.uk/blog/docker-for-development/"/>
			<updated>2017-10-03T00:00:00+00:00</updated>
			<id>http://cruikshanks.co.uk/blog/docker-for-development</id>
			<content type="html">&lt;p&gt;Using &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; for local development is different to actually building images that you expect to be deployed and run as containers elsewhere.&lt;/p&gt;

&lt;p&gt;The aim for local development is to simplify creating the necessary environment for running your app.&lt;/p&gt;

&lt;p&gt;So for example the &lt;a href=&quot;https://docs.docker.com/get-started/&quot;&gt;main docker tutorial&lt;/a&gt; assumes I have Python and PIP installed locally so that I can then grab the project’s dependencies. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dockerfile&lt;/code&gt; focuses on copying the project including dependencies into an image, and specifiying its startup behaviour.&lt;/p&gt;

&lt;p&gt;For local development I’m more interested in starting a container that contains everything I need to build and run my app, whilst still being able to make changes to the project, and have that reflected in the running application (assuming you’re building in a dynamic rather than static language).&lt;/p&gt;

&lt;p&gt;This post details some simple examples; one for &lt;a href=&quot;https://www.ruby-lang.org&quot;&gt;Ruby&lt;/a&gt; development, and the other for &lt;a href=&quot;https://nodejs.org/&quot;&gt;Node.js&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;docker-for-ruby&quot;&gt;Docker for Ruby&lt;/h2&gt;

&lt;p&gt;Here we demonstrate using &lt;strong&gt;Docker&lt;/strong&gt; to provide an environment for developing a basic ruby &lt;a href=&quot;http://www.sinatrarb.com/&quot;&gt;Sinatra&lt;/a&gt; application.&lt;/p&gt;

&lt;p&gt;Specifically we have an app with a simple root &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET&lt;/code&gt;, which returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hello world&lt;/code&gt; as we want to demonstrate a very basic app that&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;has a dependency and so needs a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gemfile&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;has something we can interact with from the host&lt;/li&gt;
  &lt;li&gt;is basic enough that it won’t complicate what we’re trying to show in &lt;strong&gt;Docker&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;the-project-ruby&quot;&gt;The project (ruby)&lt;/h3&gt;

&lt;p&gt;First create the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gemfile&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'http://rubygems.org'&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Sinatra is a DSL for quickly creating web applications in Ruby with minimal&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# effort&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'sinatra'&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Restarts an app when the file system changes&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'rerun'&lt;/span&gt;

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

&lt;p&gt;Then create a file called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server.js&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'sinatra'&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4567&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'0.0.0.0'&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Required to bind to all interfaces&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/'&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'Hello world'&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

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

&lt;p&gt;Finally create the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dockerfile&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-docker highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Sets the base image&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; ruby:2.4.1&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Use an env var to hold what will be the main directory within the container.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# As we need to refer to it a few times it can be easier to set an env var&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# and then refer to it in subsequent commands&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; APP_HOME /app&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# This will execute any commands in a new layer on top of the current image and&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# commit the results. In this case we create the /app directory&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$APP_HOME&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# instructions that follow it&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; $APP_HOME&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Copies new files or directories from &amp;lt;src&amp;gt; and adds them to the filesystem of&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# the container at the path &amp;lt;dest&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; . $APP_HOME&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Here we tell docker to download our projects dependencies in another layer&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# that then gets committed&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;bundle &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Informs Docker that the container should listen on the specified network port&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# at runtime. EXPOSE does not make the ports of the container accessible to the&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# host. To do that, you must use still use the `docker run` -p flag&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;EXPOSE&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; 4567&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# There can only be one CMD instruction in a Dockerfile. If you list more than&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# one CMD then only the last CMD will take effect.&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Purpose of a CMD is to provide defaults for an executing container. In this&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# case it sets the command and arguments to be executed when running the image&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;CMD&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; [&quot;rerun&quot;, &quot;--background&quot;, &quot;server.rb&quot;]&lt;/span&gt;

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

&lt;p&gt;If this is a bit too much hassle, feel free to make use of one &lt;a href=&quot;https://github.com/Cruikshanks/docker-for-dev/tree/master/ruby&quot;&gt;I made earlier&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;build-ruby&quot;&gt;Build (ruby)&lt;/h3&gt;

&lt;p&gt;Now we’ve got our project, we need to create an image from it. Call&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker build &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; docker-for-ruby-dev &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Don’t forget the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt; at the end there! You can call it something other than &lt;em&gt;docker-for-ruby-dev&lt;/em&gt;. This is just what I have called it for this example. If we ran it on a machine clean of other &lt;strong&gt;Docker&lt;/strong&gt; images, running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker images&lt;/code&gt; would display something like this&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
docker-for-ruby-dev   latest              5ec4ed806769        3 minutes ago       713MB
ruby                  2.4.1               3630c02d3d1b        3 weeks ago         679MB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;run-ruby&quot;&gt;Run (ruby)&lt;/h3&gt;

&lt;p&gt;So we’ve built an image, now we need to create and run a container from it&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pwd&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;:/app &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 4567:4567 docker-for-ruby-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Breaking down this command we have&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run&lt;/code&gt; first creates a writeable container layer over the specified image, and then starts it using the specified command&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--rm&lt;/code&gt; automatically removes the container on exit&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-v &quot;$(pwd)&quot;:/app&lt;/code&gt; mounts the local folder to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/app&lt;/code&gt; in the container&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p 4567:4567&lt;/code&gt; bind port 4567 on the host to 4567 in the container &lt;host:container&gt;&lt;/host:container&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-for-ruby-dev&lt;/code&gt; the specified image to create and run a container from&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running in this way ensures we see any output from our app. Add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d&lt;/code&gt; flag if you prefer the container to run as a daemon.&lt;/p&gt;

&lt;h3 id=&quot;develop-ruby&quot;&gt;Develop (ruby)&lt;/h3&gt;

&lt;p&gt;Now we have a container we want to be able to make changes. As we have mounted the project’s root folder to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/app&lt;/code&gt; in the container we can open it in our preferred editor, make changes, and see them reflected in the app.&lt;/p&gt;

&lt;p&gt;To prove this first run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl -XGET http://localhost:4567&lt;/code&gt; from the host. The response should be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hello world&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Edit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server.rb&lt;/code&gt; and change line 7 to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;'Hello docker world'&lt;/code&gt;. Running the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt; command again will result in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hello docker world&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;docker-for-nodejs&quot;&gt;Docker for node.js&lt;/h2&gt;

&lt;p&gt;Now we’ll demonstrate using &lt;strong&gt;Docker&lt;/strong&gt; to provide an environment for developing a basic &lt;a href=&quot;https://expressjs.com/&quot;&gt;Express&lt;/a&gt; app.&lt;/p&gt;

&lt;p&gt;Again we just want an application with a simple root &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET&lt;/code&gt;, which returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hello world&lt;/code&gt;, and covers the following&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;has a dependency and so needs a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;has something we can interact with from the host&lt;/li&gt;
  &lt;li&gt;is basic enough that it won’t complicate what we’re trying to show in &lt;strong&gt;Docker&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;the-project-node&quot;&gt;The project (node)&lt;/h3&gt;

&lt;p&gt;Create the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; first&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;docker-for-node-dev&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0.1.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Example site used to demo Docker for node development&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;homepage&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://github.com/Cruikshanks/docker-for-dev&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;license&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;MIT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;author&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Alan Cruikshanks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://github.com/Cruikshanks&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;private&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nodemon server.js&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;dependencies&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;express&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^4.15.4&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;devDependencies&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;nodemon&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^1.11.0&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next create the app in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server.js&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;express&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Hello world&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Example app listening on port 3000&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

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

&lt;p&gt;Finally we add our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dockerfile&lt;/code&gt;. Take note of the change we’ve had to make to allow for where npm wants to install the dependencies.&lt;/p&gt;

&lt;div class=&quot;language-docker highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Sets the base image&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; node:8.4.0&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Use an env var to hold what will be the main directory within the container.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# As we need to refer to it a few times it can be easier to set an env var&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# and then refer to it in subsequent commands&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; APP_HOME /app&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# This will execute any commands in a new layer on top of the current image and&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# commit the results. In this case we create the /app directory&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$APP_HOME&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# instructions that follow it&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; $APP_HOME&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Copies new files or directories from &amp;lt;src&amp;gt; and adds them to the filesystem of&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# the container at the path &amp;lt;dest&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; ./package.json $APP_HOME&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Here we tell docker to download our projects dependencies, then move that&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# folder to the root (why explained below) in another layer that then gets&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# committed&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;npm &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;mv&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$APP_HOME&lt;/span&gt;/node_modules /node_modules

&lt;span class=&quot;c&quot;&gt;# ##############################################################################&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Npm unlike Bundler defaults to installing dependencies within the local&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# project. That's fine when developing on the host, but as we want to install&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# them as part of the image and have them present in the container when we start&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# developing we face a problem.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# To use the container for development we mount the project folder to /app when&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# calling `docker run`. If the container's app folder still held `node_modules`,&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# the bind would cause it to become hidden as it doesn't exist on the host. We&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# therefore need to move the `node_modules` somewhere else, in this case the&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# root.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# In doing so we take advantage of&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# https://nodejs.org/api/modules.html#modules_loading_from_node_modules_folders&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# and the way Node.js traverses the directory tree to locate dependencies.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ##############################################################################&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Informs Docker that the container should listen on the specified network port&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# at runtime. EXPOSE does not make the ports of the container accessible to the&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# host. To do that, you must use still use the `docker run` -p flag&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;EXPOSE&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; 3000&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# There can only be one CMD instruction in a Dockerfile. If you list more than&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# one CMD then only the last CMD will take effect.&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Purpose of a CMD is to provide defaults for an executing container. In this&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# case it sets the command and arguments to be executed when running the image&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;CMD&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; [&quot;/node_modules/.bin/nodemon&quot;, &quot;server.js&quot;]&lt;/span&gt;

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

&lt;p&gt;Or just use one &lt;a href=&quot;https://github.com/Cruikshanks/docker-for-dev/tree/master/node&quot;&gt;I made earlier&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;build-node&quot;&gt;Build (node)&lt;/h3&gt;

&lt;p&gt;Next step; create the image.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker build &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; docker-dev-node &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This time if we run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker images&lt;/code&gt; we’ll see something like&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
docker-for-node-dev   latest              c7c5150e2d55        2 minutes ago       677MB
node                  8.4.0               5e553613f1d8        17 hours ago        669MB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;run-node&quot;&gt;Run (node)&lt;/h3&gt;

&lt;p&gt;With the image built, we now need a container&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pwd&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;:/app &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; /app &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 3000:3000 docker-for-node-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The breakdown is exactly the same as the ruby app, we’ve just changed the port and name we want to use.&lt;/p&gt;

&lt;h3 id=&quot;develop-node&quot;&gt;Develop (node)&lt;/h3&gt;

&lt;p&gt;And development works in the same way as the ruby app. Open the code on the host in your preferred IDE, make changes, and see them reflected in the app.&lt;/p&gt;

&lt;p&gt;You can test it by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl -XGET http://localhost:3000&lt;/code&gt; from the host. Edit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server.js&lt;/code&gt; and change line 5 to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;res.send('Hello docker world')&lt;/code&gt;. Running the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt; command again should result in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hello docker world&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;all-done&quot;&gt;All done&lt;/h2&gt;

&lt;p&gt;Using &lt;strong&gt;Docker&lt;/strong&gt; for development will help you and your team avoid &lt;em&gt;it works on my machine&lt;/em&gt; issues, and help get new members up and running quickly. The &lt;strong&gt;Dockerfile&lt;/strong&gt; is also great at documenting what you actually need to run the app.&lt;/p&gt;

&lt;p&gt;The examples here are very basic though, and its likely you will also depend on other services and tools. But pretty much every other example of using &lt;strong&gt;Docker&lt;/strong&gt; for development immediately launches into using &lt;a href=&quot;https://docs.docker.com/compose/&quot;&gt;Compose&lt;/a&gt;, so I wanted to provide a stripped back example. I hope it helps those like me who just wanted to get to grips with what you need to conisder just getting ‘your’ app up and running.&lt;/p&gt;

&lt;p&gt;Finally you will have to get used to calling &lt;strong&gt;Docker&lt;/strong&gt; to start your apps, rather than your typical &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ruby server.js&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm start&lt;/code&gt;. And as you’ve seen the command can be complex so bear in mind how you can keep repeating it.&lt;/p&gt;
</content>
		</entry>
	
		<entry>
			<title>The Docker blocker</title>
			<link href="http://cruikshanks.co.uk/blog/the-docker-blocker/"/>
			<updated>2017-07-28T00:00:00+00:00</updated>
			<id>http://cruikshanks.co.uk/blog/the-docker-blocker</id>
			<content type="html">&lt;p&gt;When you get started with &lt;a href=&quot;https://docs.docker.com/get-started/&quot;&gt;Docker&lt;/a&gt;, you’ll come across &lt;a href=&quot;http://www.phrases.org.uk/bulletin_board/62/messages/94.html&quot;&gt;bumpff&lt;/a&gt; telling you that &lt;strong&gt;Docker&lt;/strong&gt; containers are &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; virtual machines, and this will be emphasised by pictures showing containers not requiring a guest O/S.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Container&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt; &lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Virtual machine&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/assets/images/docker_container_layers.png&quot; alt=&quot;Docker container architecture&quot; width=&quot;300&quot; /&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/assets/images/docker_virtual_machine_layers.png&quot; alt=&quot;Virtual machine architecture&quot; width=&quot;300&quot; /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;em&gt;Images taken from &lt;a href=&quot;https://www.docker.com/what-container&quot;&gt;https://www.docker.com/what-container&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Nice.&lt;/p&gt;

&lt;p&gt;For those of us who don’t need to go deep on a subject before we have a play, you’ll accept this and move on. Next step is typically putting together your first &lt;a href=&quot;https://docs.docker.com/engine/reference/builder/&quot;&gt;Docker file&lt;/a&gt;. And the first statement in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dockerfile&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FROM foo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The problem is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt;, will actually be something like &lt;a href=&quot;https://hub.docker.com/_/alpine/&quot;&gt;Alpine&lt;/a&gt;, &lt;a href=&quot;https://hub.docker.com/_/debian/&quot;&gt;Debian&lt;/a&gt;, or &lt;a href=&quot;https://hub.docker.com/_/ubuntu/&quot;&gt;Ubuntu&lt;/a&gt;. So your image will be based on an O/S image.&lt;/p&gt;

&lt;p&gt;Huh?&lt;/p&gt;

&lt;h2 id=&quot;the-blocker&quot;&gt;The blocker&lt;/h2&gt;

&lt;p&gt;I’m guessing others have either done the research first, or just accept this and move on. I can’t explain why, but for some reason this blocked me. I could see the benefits of &lt;strong&gt;Docker&lt;/strong&gt;, but I couldn’t engage with it because of this &lt;a href=&quot;https://www.merriam-webster.com/dictionary/conundrum&quot;&gt;conundrum&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And having spoken to others, I’m not the only one. It seems to be an incongruity that niggles enough at the back of your mind that you can’t focus on progressing.&lt;/p&gt;

&lt;p&gt;So why when the docs talk about containers not needing an O/S, do &lt;a href=&quot;https://docs.docker.com/engine/reference/builder/#dockerfile-examples&quot;&gt;so many examples include one&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So this post is the result of me learning &lt;em&gt;just enough&lt;/em&gt; to answer this question for myself. I’ve put it out there in the hope it can help others.&lt;/p&gt;

&lt;h2 id=&quot;batman-vs-superman&quot;&gt;Batman vs Superman&lt;/h2&gt;

&lt;p&gt;Or in our case containers versus virtual machines. The first thing I found helpful was thinking of &lt;strong&gt;Docker&lt;/strong&gt; as &lt;em&gt;“an abstraction at the application layer”&lt;/em&gt;, and virtual machines as &lt;em&gt;“an abstraction at the hardware layer”&lt;/em&gt; (thanks &lt;a href=&quot;https://www.docker.com/what-container&quot;&gt;Docker docs!&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;A virtual machine will get dedicated resources and run isolated from everything else. The virtual manager and hypervisor will take this isolation down to the metal, and it’s why for all intents and purposes a virtual machine is separate and distinct from the host.&lt;/p&gt;

&lt;p&gt;Containers aim to reuse the resources of the host, whilst still keeping things isolated at the app layer. The main way it does this is by sharing the underlying kernel.&lt;/p&gt;

&lt;h2 id=&quot;a-kernel-of-an-idea&quot;&gt;A kernel of an idea&lt;/h2&gt;

&lt;p&gt;Though we have the &lt;a href=&quot;https://en.wikipedia.org/wiki/Linux_kernel&quot;&gt;Linux kernel&lt;/a&gt; and the &lt;a href=&quot;https://en.wikipedia.org/wiki/Architecture_of_Windows_NT&quot;&gt;Windows kernel&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Kernel_(operating_system)&quot;&gt;kernels&lt;/a&gt; are more a concept than a specific thing.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/kernel_layout.svg&quot; alt=&quot;Docker container architecture&quot; width=&quot;300&quot; /&gt;&lt;br /&gt;
&lt;em&gt;By Bobbo - Own work, CC BY-SA 3.0, &lt;a href=&quot;https://commons.wikimedia.org/w/index.php?curid=4392180&quot;&gt;https://commons.wikimedia.org/w/index.php?curid=4392180&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The kernel is the bit of the operating system that connects the application software to the underlying hardware of the machine. Typically it gets loaded into protected memory when the system starts up, and this is known as &lt;a href=&quot;https://en.wikipedia.org/wiki/User_space&quot;&gt;kernel space&lt;/a&gt;. Everything it does happens here, which is taking system calls from processes for access to resources. Everything else like working with documents, applications, the file and window system happens in &lt;a href=&quot;https://en.wikipedia.org/wiki/User_space&quot;&gt;user space&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The linux family of operating systems use the same linux kernel; what makes them different what they do within the user space.&lt;/p&gt;

&lt;h2 id=&quot;back-to-the-bottom&quot;&gt;Back to the bottom&lt;/h2&gt;

&lt;p&gt;So we’ve gone a little deeper on differences between a container and a virtual machine, and we understand that an operating system is made up of 2 parts; the kernel and everything else!&lt;/p&gt;

&lt;p&gt;So if &lt;strong&gt;Docker&lt;/strong&gt; containers get a kernel, but no O/S what do we do for a file structure and system? How do we pull down the binaries our projects depend on when building the image? How do we get system dependencies we depend on?&lt;/p&gt;

&lt;p&gt;That’s what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FROM ubuntu&lt;/code&gt; is doing. These are container specific images built to provide just the &lt;strong&gt;user space&lt;/strong&gt; stuff you need when deploying and running your project. It’s not a guest O/S in the same way as a virtual machine, its just filling in for the bits you probably need but which the kernel doesn’t cover.&lt;/p&gt;

&lt;h2 id=&quot;doing-it-from-scratch&quot;&gt;Doing it from scratch&lt;/h2&gt;

&lt;p&gt;To prove a point, you really don’t need that O/S layer in your image. All &lt;strong&gt;Docker&lt;/strong&gt; images derive from the &lt;a href=&quot;https://docs.docker.com/engine/userguide/eng-image/baseimages/#creating-a-simple-parent-image-using-scratch&quot;&gt;base image called scratch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can build an image &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FROM scratch&lt;/code&gt; using a pre-compiled &lt;strong&gt;C&lt;/strong&gt; binary&lt;/p&gt;

&lt;div class=&quot;language-dockerfile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; scratch&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ADD&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; my_binary /&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;CMD&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; [&quot;/my_binary&quot;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You could theoretically do the same for a Ruby project, if you were willing to manually create the file system, and load all the binaries you depend on, and your gems depend on etc.&lt;/p&gt;

&lt;p&gt;So yeah, never gonna happen!&lt;/p&gt;

&lt;p&gt;Hence most projects will have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FROM&lt;/code&gt; statement that either directly uses an O/S image, or somewhere down the chain will have.&lt;/p&gt;

&lt;h2 id=&quot;move-along-please-nothing-to-see-here&quot;&gt;Move along please. Nothing to see here&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Docker&lt;/strong&gt; containers don’t have a guest O/S, if we define an O/S as everything plus the kernel. They also don’t have everything we need to work productively with &lt;strong&gt;Docker&lt;/strong&gt; when creating an image, hence we use parent images to bring in the bits that make our lives easier.&lt;/p&gt;

&lt;p&gt;And they’re not the same as virtual machines. So can we move along please?&lt;/p&gt;
</content>
		</entry>
	
		<entry>
			<title>Local gems for local projects</title>
			<link href="http://cruikshanks.co.uk/blog/local-gems-for-local-projects/"/>
			<updated>2017-06-16T00:00:00+00:00</updated>
			<id>http://cruikshanks.co.uk/blog/local-gems-for-local-projects</id>
			<content type="html">&lt;p&gt;When working if I find the same code is needed in other projects, I’ll shift it to a &lt;a href=&quot;http://guides.rubygems.org/what-is-a-gem/&quot;&gt;gem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is all well and good, but I’ll sometimes find I want to make changes to project &lt;strong&gt;&lt;em&gt;foo&lt;/em&gt;&lt;/strong&gt;, that depend on changes to gem &lt;strong&gt;&lt;em&gt;bar&lt;/em&gt;&lt;/strong&gt;. This leaves me with 2 options&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Update the reference in the gem file to add the argument &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;path&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Pro&lt;/strong&gt; I can immediately get on with hacking the solution&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Con&lt;/strong&gt; I’m liable to forget I made the change and so will push a change that breaks the build and other peoples environments&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Make the changes to the gem, push them and then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundle install&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Pro&lt;/strong&gt; the Gemfile is left untouched, removing the risk of pushing a broken version&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Con&lt;/strong&gt; I have to commit the changes, and will find that when used they are not right or are incomplete&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;a-third-way&quot;&gt;A third way&lt;/h2&gt;

&lt;p&gt;In the truest meaning of the “&lt;a href=&quot;https://en.wikipedia.org/wiki/Third_Way&quot;&gt;Third way&lt;/a&gt;”, &lt;a href=&quot;http://bundler.io/&quot;&gt;Bundler&lt;/a&gt; does provide an option that means we don’t have to make changes to the gemfile, whilst still working against a local version of the gem.&lt;/p&gt;

&lt;p&gt;Using the &lt;strong&gt;Bundler&lt;/strong&gt; &lt;a href=&quot;http://bundler.io/v1.3/man/bundle-config.1.html&quot;&gt;config&lt;/a&gt; command you can tell it when looking for gem &lt;strong&gt;bar&lt;/strong&gt;, use my local version.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bundle config &lt;span class=&quot;nt&quot;&gt;--local&lt;/span&gt; local.quke /Users/acruikshanks/projects/defra/quke
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;N.B. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--local&lt;/code&gt; flag scopes it to just this project.&lt;/p&gt;

&lt;h2 id=&quot;strike-1&quot;&gt;Strike 1!&lt;/h2&gt;

&lt;p&gt;The gem might be referencing a repo rather than &lt;a href=&quot;https://rubygems.org/&quot;&gt;rubygems&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gem &lt;span class=&quot;s2&quot;&gt;&quot;quke&quot;&lt;/span&gt;,
  git: &lt;span class=&quot;s2&quot;&gt;&quot;https://github.com/DEFRA/quke&quot;&lt;/span&gt;,
  branch: &lt;span class=&quot;s2&quot;&gt;&quot;master&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you only ran the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundle config&lt;/code&gt; command you’d be likely to hit an error.&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Local override for quke at /Users/acruikshanks/projects/defra/quke is using branch fix/make-the-tea but Gemfile specifies master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Basically the branch specified in the gem file doesn’t match what is currently checked out in your gem project (and why would it!?)&lt;/p&gt;

&lt;p&gt;To resolve this run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundle config disable_local_branch_check true&lt;/code&gt; to silence the error message.&lt;/p&gt;

&lt;h2 id=&quot;strike-2&quot;&gt;Strike 2!&lt;/h2&gt;

&lt;p&gt;So you do this, and think all is well. Then you start making changes to your gem code, but your project doesn’t see them.&lt;/p&gt;

&lt;p&gt;You might even run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundle update my_gem&lt;/code&gt; to try and resolve things to no avail.&lt;/p&gt;

&lt;p&gt;There is a gotcha with using this method. It only sees changes that have been &lt;strong&gt;&lt;em&gt;committed&lt;/em&gt;&lt;/strong&gt;. That’s the one benefit that using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;path&lt;/code&gt; has over this method. But if you remember this and make use of some &lt;em&gt;WIP&lt;/em&gt; commits that you’ll clean up later, its easy to live with.&lt;/p&gt;

&lt;h2 id=&quot;strike-3-youre-outta-here&quot;&gt;Strike 3, you’re outta here!&lt;/h2&gt;

&lt;p&gt;Not sold? Or simply want to switch back to using the proper source for final testing. You can reverse the change using&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bundle config &lt;span class=&quot;nt&quot;&gt;--delete&lt;/span&gt; local.pafs_core
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;thank-you&quot;&gt;Thank you&lt;/h2&gt;

&lt;p&gt;Thank you to &lt;a href=&quot;https://www.linkedin.com/in/tonyheadford/?ppe=1&quot;&gt;Tony Headford&lt;/a&gt; for telling me the right combination of commands and gem file content to use (others had attempted this before but they still seemed to require messing with the gem file).&lt;/p&gt;

&lt;p&gt;Also to &lt;a href=&quot;https://twitter.com/thilorusche&quot;&gt;Thilo Rusche&lt;/a&gt; for his &lt;a href=&quot;https://coderwall.com/p/tqdrhq/work-against-local-gems-without-modifying-your-gemfile&quot;&gt;post&lt;/a&gt;, which confirmed what I was doing and highlighted why my changes couldn’t be seen.&lt;/p&gt;
</content>
		</entry>
	
		<entry>
			<title>With just a few tags you too can have rich links</title>
			<link href="http://cruikshanks.co.uk/blog/with-just-a-few-tags-you-too-can-have-rich-links/"/>
			<updated>2017-05-23T00:00:00+00:00</updated>
			<id>http://cruikshanks.co.uk/blog/with-just-a-few-tags-you-too-can-have-rich-links</id>
			<content type="html">&lt;p&gt;A key collaboration tool at work is &lt;a href=&quot;https://slack.com/&quot;&gt;Slack&lt;/a&gt;, and for those times when left with idle hands (queuing, kettle boiling, hiding in the toilet from the kids) I’m checking &lt;a href=&quot;https://twitter.com/AlanCruikshanks&quot;&gt;Twitter&lt;/a&gt;. What they have in common is when you add a link to your message/tweet they present it in a nice box.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/rich_text_slack_example.png&quot; alt=&quot;Slack example of a rich preview&quot; width=&quot;800&quot; /&gt;&lt;br /&gt;
&lt;em&gt;Example from Slack&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/rich_text_twitter_example.png&quot; alt=&quot;Twitter example of a rich preview&quot; width=&quot;800&quot; /&gt;&lt;br /&gt;
&lt;em&gt;Example from Twitter&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ignorantly (and ashamedly) I just assumed that each of these apps, and any others that do something like this automatically generate them from the link you provide. So when I came to start creating my own stuff there was nothing I needed to do.&lt;/p&gt;

&lt;h2 id=&quot;pity-the-fool&quot;&gt;Pity the fool!&lt;/h2&gt;

&lt;p&gt;Imagine my disappointment when proudly tweeting a link to my first post, I found the link just hung there in its vanilla, naked pale blue ugliness.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://dictionary.cambridge.org/dictionary/english/plonker&quot;&gt;Plonker&lt;/a&gt;, of course I need to do something at my end!&lt;/p&gt;

&lt;p&gt;So just in case you’re as ignorant as me, this post will cover how I added rich preview support to my site.&lt;/p&gt;

&lt;h2 id=&quot;its-meta&quot;&gt;It’s meta&lt;/h2&gt;

&lt;p&gt;Props to &lt;a href=&quot;https://twitter.com/r_oosterhof&quot;&gt;Richard Oosterhof&lt;/a&gt; and his post &lt;a href=&quot;https://medium.com/@richardoosterhof/how-to-optimize-your-site-for-rich-previews-527ed13a6d69&quot;&gt;How to optimize your site for Rich Previews&lt;/a&gt; for putting me on the right track.&lt;/p&gt;

&lt;p&gt;You basically need to add a bunch of &lt;a href=&quot;https://en.wikipedia.org/wiki/Meta_element&quot;&gt;meta&lt;/a&gt; tags to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section of your page. &lt;strong&gt;Richard’s&lt;/strong&gt; post talks about the following tags&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;title&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;description&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;og:title&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;og:description&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;og:image&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;He also states your site should have a &lt;a href=&quot;https://en.wikipedia.org/wiki/Favicon&quot;&gt;Favicon&lt;/a&gt; (so that was actually the first thing I fixed using &lt;a href=&quot;http://realfavicongenerator.net/&quot;&gt;RealFaviconGenerator&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;So what exactly was the syntax? Well I’d seen people post enough &lt;a href=&quot;https://medium.com/&quot;&gt;Medium&lt;/a&gt; articles like &lt;strong&gt;Richard’s&lt;/strong&gt; to know it worked for them, so I just pinched what I found using ‘view source’.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;title&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;How to optimize your site for Rich Previews – Richard Oosterhof – Medium&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;description&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;You probably have seen them already, when you send a website link in chat apps…&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;og:title&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;How to optimize your site for Rich Previews – Richard Oosterhof – Medium&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;og:description&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;You probably have seen them already, when you send a website link in chat apps…&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;og:image&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://cdn-images-1.medium.com/max/1200/1*VDDZ-GgOIHnd4Au4ncYlMg.png&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All this stuff goes into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;head&amp;gt;&lt;/code&gt;, and &lt;strong&gt;Richard&lt;/strong&gt; has even built a handy tool to check you’ve got it setup correctly at &lt;a href=&quot;http://richpreview.com/&quot;&gt;richpreview.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks &lt;strong&gt;Richard&lt;/strong&gt;!&lt;/p&gt;

&lt;h2 id=&quot;but-im-different&quot;&gt;But I’m different&lt;/h2&gt;

&lt;p&gt;That’s great if you’re hand cranking each static page, but no good for me, as I’m using &lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt; to generate my pages from &lt;a href=&quot;https://en.wikipedia.org/wiki/Markdown&quot;&gt;Markdown&lt;/a&gt; documents.&lt;/p&gt;

&lt;p&gt;However the implementation didn’t require major changes. The site uses a default &lt;a href=&quot;http://jekyllrb.com/docs/templates/&quot;&gt;layout&lt;/a&gt; for all pages, so the place to put the tags was &lt;a href=&quot;https://github.com/Cruikshanks/cruikshanks.github.io/blob/master/_layouts/default.html&quot;&gt;it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As my post pages don’t feature unique images I chose instead to go with a single default image I’d use for all pages. With that I could simply hard code the url to the image in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;og:image&lt;/code&gt; tag.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;title&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;description&lt;/code&gt; needed to come from each page though. &lt;strong&gt;Jekyll’s&lt;/strong&gt; concept of &lt;a href=&quot;http://jekyllrb.com/docs/frontmatter/&quot;&gt;front matter&lt;/a&gt; already provided &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;title&lt;/code&gt;, so next I needed to go back through all my pages and add a new property for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;description&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So the final bit was to pull &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;title&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;description&lt;/code&gt; from each page. As &lt;strong&gt;Jekyll&lt;/strong&gt; uses the &lt;a href=&quot;https://shopify.github.io/liquid/&quot;&gt;Liquid&lt;/a&gt; templating language this just meant inserting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{{ page.title }}&lt;/code&gt; into the relevant tags. So the final implementation was&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;title&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ page.title }}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;description&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ page.description }}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;og:title&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ page.title }}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;og:description&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ page.description }}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;og:image&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://cruikshanks.co.uk/assets/images/default_rich_preview.png&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;that-it&quot;&gt;That it?&lt;/h2&gt;

&lt;p&gt;Not quite. I then got curious so Googled what an &lt;strong&gt;og:&lt;/strong&gt; meta tag was and came across &lt;a href=&quot;http://ogp.me/&quot;&gt;http://ogp.me/&lt;/a&gt;. Turns out adding these tags turns your web page into a graph object, and that enables it to &lt;em&gt;become a rich object in a social graph&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I’ll leave you to read further on that, suffice to say what I’d added didn’t meet the minimum requirements for &lt;strong&gt;Open graph&lt;/strong&gt;, plus there were some optional tags that might be relevant.&lt;/p&gt;

&lt;p&gt;So I expanded the tags to include a few more.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;og:type&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;website&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;og:url&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://cruikshanks.co.uk/{{ page.permalink }}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;og:site_name&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;cruikshanks.co.uk&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;property=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;og:locale&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;en_GB&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Again you can see how I used &lt;strong&gt;Liquid&lt;/strong&gt; to grab a front matter property to build the url dynamically for each page.&lt;/p&gt;

&lt;h2 id=&quot;now-are-we-done&quot;&gt;Now are we done?&lt;/h2&gt;

&lt;p&gt;Almost! Seeing as generally I intended to use &lt;a href=&quot;https://twitter.com/AlanCruikshanks&quot;&gt;Twitter&lt;/a&gt; to post about my links I thought it worth while to also do some Googling for rich preview support in &lt;strong&gt;Twitter&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And lo, there be documents and a bit more to do. &lt;strong&gt;Twitter&lt;/strong&gt; calls them &lt;a href=&quot;https://dev.twitter.com/cards/types/summary&quot;&gt;Summary&lt;/a&gt; cards and on initial reading appears to rely on &lt;strong&gt;Twitter&lt;/strong&gt; specific tags, for example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;meta name=&quot;twitter:title&quot; content=&quot;My title&quot; /&amp;gt;&lt;/code&gt;. However further research turned up &lt;a href=&quot;https://dev.twitter.com/cards/markup&quot;&gt;Cards Markup Tag Reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This showed that where a &lt;strong&gt;Twitter&lt;/strong&gt; meta tag did not exist, it would fall back on &lt;strong&gt;Open graph&lt;/strong&gt;. I also found a handy &lt;a href=&quot;https://cards-dev.twitter.com/validator&quot;&gt;card validator&lt;/a&gt; so you can check that your pages meet the requirements for &lt;strong&gt;Twitter&lt;/strong&gt; to display a summary card.&lt;/p&gt;

&lt;p&gt;So the final set of tags I added to my &lt;a href=&quot;https://github.com/Cruikshanks/cruikshanks.github.io/blob/master/_layouts/default.html&quot;&gt;default layout&lt;/a&gt; were&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;twitter:site&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;@alancruikshanks&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;twitter:image:alt&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Avatar for Alan Cruikshanks&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;twitter:site&lt;/code&gt; is required by &lt;strong&gt;Twitter&lt;/strong&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;twitter:image:alt&lt;/code&gt; allows me to provide alt text for my image, something I’ll always take advantage of.&lt;/p&gt;

&lt;h2 id=&quot;mic-drop&quot;&gt;Mic drop&lt;/h2&gt;

&lt;p&gt;That’s it for me and this site at least. It may well be if I was to post links in other apps I wouldn’t get a preview, but I’ll tackle those as I find them. For now, I’m &lt;strong&gt;Open graph&lt;/strong&gt; compliant and &lt;strong&gt;Twitter&lt;/strong&gt; likes me, so I shall leave it there.&lt;/p&gt;
</content>
		</entry>
	
		<entry>
			<title>Who me!? (Being a dev lead)</title>
			<link href="http://cruikshanks.co.uk/blog/who-me-being-a-dev-lead/"/>
			<updated>2017-05-15T00:00:00+00:00</updated>
			<id>http://cruikshanks.co.uk/blog/who-me-being-a-dev-lead</id>
			<content type="html">&lt;p&gt;A recent &lt;a href=&quot;https://www.hanselman.com/&quot;&gt;Scott Hanselman&lt;/a&gt; podcast entitled “&lt;a href=&quot;https://hanselminutes.com/574/the-road-to-lead-developer-with-linda-kamau-of-ushahidi&quot;&gt;road to lead developer&lt;/a&gt;” got me thinking about my own trips along that thoroughfare.&lt;/p&gt;

&lt;p&gt;I’d like to say it’s always been a well planned journey, ending with some wise person anointing me as lead dev. In reality it’s been more a case of groping around in the dark until I eventually tripped and impaled myself on the anointing sword.&lt;/p&gt;

&lt;p&gt;What I have learnt is there is no one sure path, and it will differ depending on your organisation and the people in it. Often you’ll find yourself somewhere such a role isn’t even recognised.&lt;/p&gt;

&lt;p&gt;But I think it’s a required one in a successful delivery team.&lt;/p&gt;

&lt;h2 id=&quot;a-definition&quot;&gt;A definition&lt;/h2&gt;

&lt;p&gt;Before we go further let’s be clear what I’m talking about. I’m referring to the person who takes point on any technical decisions, not the one who approves your holiday or who sets out your &lt;a href=&quot;http://www.performancemagazine.org/what-is-an-individual-performance-plan/&quot;&gt;individual performance plan&lt;/a&gt;. That may be the same person in some places, but I’m interested in just the techie stuff.&lt;/p&gt;

&lt;p&gt;It should also be differentiated from seniority. So being the most senior dev does not automatically make you this. Previously my assumption would have been the person tagged as lead dev (or dev lead, technical lead, &lt;a href=&quot;https://en.wikipedia.org/wiki/Grand_Poobah&quot;&gt;grand poohba&lt;/a&gt;, whatever your preference is) was the most technically gifted and/or experienced developer in the room.&lt;/p&gt;

&lt;p&gt;In practice it’s my experience they’re the person willing to do two things&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;em&gt;make decisions&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;em&gt;own the decisions they make&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everyone has opinions and many are happy to make them known. A lead dev however is the one setting a direction by being willing to make a decision.&lt;/p&gt;

&lt;p&gt;Good ones make them having listened to the people around them. Poor ones either ignore them or just go with the loudest.&lt;/p&gt;

&lt;h2 id=&quot;yes-you&quot;&gt;Yes, you!&lt;/h2&gt;

&lt;p&gt;If you are one, ideally you were selected. I can imagine that would help give you confidence in the decisions you make. However you may be like me, and find yourself often taking on the role because you sense the vacuum and it’s impact on your team.&lt;/p&gt;

&lt;p&gt;Either way I think my two requirements apply. You must be willing to&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;em&gt;make decisions&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;em&gt;own the decisions you make&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clearly there’s more to it than just this, and I don’t claim to be a guru on the matter. But unless you have a hyper-performing, super self-organising team i.e. you’re the exception, I believe you need someone to lead, and that leader has to be willing to do those two things.&lt;/p&gt;

&lt;p&gt;For reference, it’s probably an arrogance in my abilities to make decisions, or an ignorance of the consequences of them (or a bit of both) which explains why I’m happy to keep impaling myself. But I’m hopeful if I do it enough I will finally do a half decent job of it!&lt;/p&gt;
</content>
		</entry>
	
		<entry>
			<title>Boxed in dependencies</title>
			<link href="http://cruikshanks.co.uk/blog/boxed-in-dependencies/"/>
			<updated>2017-05-05T00:00:00+00:00</updated>
			<id>http://cruikshanks.co.uk/blog/boxed-in-dependencies</id>
			<content type="html">&lt;p&gt;&lt;em&gt;First a clarification. I refer to my &lt;a href=&quot;https://www.vagrantup.com/&quot;&gt;Vagrant&lt;/a&gt; images as boxes, but you should be aware &lt;a href=&quot;https://www.vagrantup.com/docs/boxes.html&quot;&gt;box&lt;/a&gt; has a specific meaning in Vagrant land. I’ll highlight when I’m using the Vagrant version.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Sometime back I learnt of Vagrant and having had a play, immediately got stuck in and now use it daily. Initially I had grand plans to base all my development on Vagrant boxes, but in practise this never materialised.&lt;/p&gt;

&lt;p&gt;Version and package managers seem to do all the heavy lifting, so I don’t feel the need to build a box for every project I’ve got going on. I’ve also found a reticence from other dev’s to using them, and like any part of an evolving project Vagrant files need to be fed and watered so there’s an overhead. Plus there’s the elephant in the room, otherwise known as &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;custom-boxes&quot;&gt;Custom boxes&lt;/h2&gt;

&lt;p&gt;So after listing a bunch of reasons for not using them, how &lt;em&gt;do&lt;/em&gt; I use them daily? Well I use them for my general dependencies, databases being the primary example. Rather than install database &lt;strong&gt;&lt;em&gt;x&lt;/em&gt;&lt;/strong&gt; directly on my host machine, I instead stick it in a box.&lt;/p&gt;

&lt;p&gt;You could create a box specific to each project, but I tend to share mine among them. So for example I’ll stick &lt;a href=&quot;https://www.postgresql.org/&quot;&gt;PostgreSQL&lt;/a&gt; in an box, and use it for all my projects that require it.&lt;/p&gt;

&lt;h2 id=&quot;big-fish-little-fish-vagrant-box&quot;&gt;Big fish, little fish, &lt;a href=&quot;https://www.youtube.com/watch?v=SD1ENnVnMXM&quot;&gt;Vagrant box!&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;So what steps are involved?&lt;/p&gt;

&lt;h3 id=&quot;installation&quot;&gt;Installation&lt;/h3&gt;

&lt;p&gt;Obviously start with installing Vagrant. Next you’ll need to decide on your ‘&lt;a href=&quot;https://www.vagrantup.com/docs/providers/&quot;&gt;provider&lt;/a&gt;’ and install it. This is basically the app used to create and run the &lt;a href=&quot;https://en.wikipedia.org/wiki/Virtual_machine&quot;&gt;VM’s&lt;/a&gt; you are going to install your dependencies on.&lt;/p&gt;

&lt;p&gt;Vagrant uses &lt;a href=&quot;https://www.virtualbox.org/&quot;&gt;VirtualBox&lt;/a&gt; as its default, and its what I use as its free and simple.&lt;/p&gt;

&lt;h3 id=&quot;initialise&quot;&gt;Initialise&lt;/h3&gt;

&lt;p&gt;With those two things installed, next create a new folder (named after the thing you intend to install), drop into it and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vagrant init&lt;/code&gt; from your command line.&lt;/p&gt;

&lt;p&gt;This adds to the folder the files you’ll need to get started with Vagrant, the most important one being &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Vagrantfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As I want to make my boxes reusable, I also tend to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git init&lt;/code&gt; and add things like a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt; file, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;README&lt;/code&gt; and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LICENSE&lt;/code&gt;, before pushing it to GitHub.&lt;/p&gt;

&lt;h3 id=&quot;vagrantfile&quot;&gt;Vagrantfile&lt;/h3&gt;

&lt;p&gt;In here you’ll find the bare bones for configuring and setting up your box, which by default will be a VirtualBox. The first decision you need to make is what &lt;a href=&quot;https://www.vagrantup.com/docs/boxes.html&quot;&gt;box&lt;/a&gt; (&lt;em&gt;the Vagrant kind!&lt;/em&gt;) to base your box on. Basically what OS to use. There is a &lt;a href=&quot;https://vagrantcloud.com/boxes/search&quot;&gt;publicly accessible list&lt;/a&gt; to pick from, but if it helps I tend to use &lt;a href=&quot;https://app.vagrantup.com/ubuntu/boxes/trusty64&quot;&gt;ubuntu/trusty64&lt;/a&gt;, and based on the download numbers so does everybody else.&lt;/p&gt;

&lt;p&gt;I’m not going to get into the details, I encourage you to check out the &lt;a href=&quot;https://www.vagrantup.com/docs/index.html&quot;&gt;documentation&lt;/a&gt;. But in essence the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Vagrantfile&lt;/code&gt; is divided into two sections; configuration, and provisioning i.e. how to install your dependency.&lt;/p&gt;

&lt;h2 id=&quot;getting-the-install-right&quot;&gt;Getting the install right&lt;/h2&gt;

&lt;p&gt;When getting started with a new box, I tend to begin with a standard bit of installation&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# General provisioning of the box. Ensure time is set correctly and do an&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# initial apt-get update, plus install packages commonly needed by all boxes&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;provision&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;shell&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;name: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;common&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;inline: &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SHELL&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
  timedatectl set-timezone Europe/London
  apt-get update &amp;gt; /dev/null
  apt-get install -y git build-essential tcl8.5 wget curl make libqt4-dev
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SHELL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’ll then run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vagrant up&lt;/code&gt;, which when complete will give me an empty box. I then access it using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vagrant ssh&lt;/code&gt; and once on, begin following whatever install process I’ve managed to Google.&lt;/p&gt;

&lt;p&gt;I’ll record all the commands I use and update the provisioning details when done. I’ll then exit the box and call&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vagrant halt&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vagrant destroy&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vagrant up&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows me to test that when I create this box in future I know my provisioning commands will work&lt;/p&gt;

&lt;h2 id=&quot;benefits&quot;&gt;Benefits?&lt;/h2&gt;

&lt;p&gt;I see plenty. I now have a reproducible way to get something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PostgreSQL&lt;/code&gt; on the machine I’m using.&lt;/p&gt;

&lt;p&gt;Not only do I have a project that will automate the process, its also documents what’s involved.&lt;/p&gt;

&lt;p&gt;I only need to run these services when using them. It’s easy to halt a box when its not being used.&lt;/p&gt;

&lt;p&gt;I reduce bloat on my dev machine, and the risk of dependencies conflicting.&lt;/p&gt;

&lt;h2 id=&quot;examples&quot;&gt;Examples&lt;/h2&gt;

&lt;p&gt;I have some existing boxes you can check out, copy from, or use.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Cruikshanks/mongo-box&quot;&gt;MongoDb&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Cruikshanks/mysql-box&quot;&gt;MySQL&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Cruikshanks/postgresql94&quot;&gt;PostgreSQL&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Cruikshanks/redis-box&quot;&gt;Redis&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
		</entry>
	
		<entry>
			<title>Hey browser, these guys are with me</title>
			<link href="http://cruikshanks.co.uk/blog/hey-browser-these-guys-are-with-me/"/>
			<updated>2017-04-27T00:00:00+00:00</updated>
			<id>http://cruikshanks.co.uk/blog/hey-browser-these-guys-are-with-me</id>
			<content type="html">&lt;p&gt;This covers something I learnt when, having joined a project late I was asked to pick up some outstanding actions from their recent &lt;a href=&quot;https://en.wikipedia.org/wiki/Penetration_test&quot;&gt;PEN test&lt;/a&gt;. Specifically the test had highlighted that the service was missing a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP&quot;&gt;Content Security Policy (CSP)&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;a-what-now&quot;&gt;A what now?&lt;/h2&gt;

&lt;p&gt;A CSP is delivered via a HTTP response header, and defines approved sources of content that the browser may load. It’s seen as an effective countermeasure to Cross Site Scripting (XSS) attacks, is widely supported and usually easy to deploy.&lt;/p&gt;

&lt;p&gt;When your browser loads a page it also loads a bunch of other assets along with it; images, fonts, styles, and JavaScript. It does this because we’ve told it to do so via things like our script tags.&lt;/p&gt;

&lt;p&gt;The browser however doesn’t differentiate. So if a hacker, via some content they have contributed (a comment is the classic example), manages to inject a properly formed script tag into the page the browser will load it along with everything else.&lt;/p&gt;

&lt;p&gt;So a CSP is designed to prevent this by essentially adopting the idea of a white list. The policy sets out what are the valid sources for the various types of assets your page may load, so the browser &lt;strong&gt;&lt;em&gt;can&lt;/em&gt;&lt;/strong&gt; differentiate.&lt;/p&gt;

&lt;h2 id=&quot;getting-it-in-there&quot;&gt;Getting it in there&lt;/h2&gt;

&lt;p&gt;The project already had code for adding custom headers, specifically to manage caching. This was done within the application controller (oh, and its a &lt;a href=&quot;http://rubyonrails.org/&quot;&gt;Rails&lt;/a&gt; project by the way) using a &lt;a href=&quot;http://guides.rubyonrails.org/action_controller_overview.html#filters&quot;&gt;before_action&lt;/a&gt; filter to call a method that did something like this.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Cache-Control&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;no-cache, no-store, max-age=0, must-revalidate, private&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So the initial implementation simply added something along the lines off&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Content-Security-Policy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;default-src 'self'; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;\&lt;/span&gt;
                                        &lt;span class=&quot;s2&quot;&gt;&quot;script-src 'self' 'unsafe-inline'; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;\&lt;/span&gt;
                                        &lt;span class=&quot;s2&quot;&gt;&quot;font-src 'self' data:; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;\&lt;/span&gt;
                                        &lt;span class=&quot;s2&quot;&gt;&quot;report-uri https://mycustomname.report-uri.io/r/default/csp/enforce&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Specifically we are saying&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;scripts can only come from the service, however we permit &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#Unsafe_inline_script&quot;&gt;unsafe-inline&lt;/a&gt; scripts&lt;/li&gt;
  &lt;li&gt;fonts can only come from the service, or via the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs&quot;&gt;data: scheme&lt;/a&gt; (a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data: uri&lt;/code&gt; is a way to embed small files inline)&lt;/li&gt;
  &lt;li&gt;send any violation reports to a &lt;a href=&quot;https://report-uri.io/&quot;&gt;service we have setup&lt;/a&gt; for this CSP&lt;/li&gt;
  &lt;li&gt;for all other items their source must be the service (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default-src&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;all-done&quot;&gt;All done?&lt;/h2&gt;

&lt;p&gt;Not quite! For &lt;em&gt;reasons&lt;/em&gt; we spotted that this didn’t cover assets we were bringing in to support &lt;a href=&quot;https://analytics.google.com&quot;&gt;Google Analytics&lt;/a&gt;. Also one of those assets was an inline JS script, which our current use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unsafe-inline&lt;/code&gt; covered. But this was intended to only be temporary until an issue in a dependency was resolved and we could switch it off. So ideally we wanted to also be able to support &lt;a href=&quot;https://scotthelme.co.uk/csp-cheat-sheet/#nonces&quot;&gt;nonces&lt;/a&gt;. Basically these are one time values generated on the server and added to the script tag, but also into the CSP. The browser can then cross check them, see they match and therefore permit the specified inline-script to run.&lt;/p&gt;

&lt;p&gt;At this point the temptation is start rolling your own solution but a quick search found one already existed; enter the &lt;a href=&quot;https://github.com/twitter/secureheaders&quot;&gt;Secure Headers gem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Not only did this come with support for nonces, but it also highlighted a bunch of other headers we really should be thinking of using.&lt;/p&gt;

&lt;p&gt;To implement add a file to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config/initializers&lt;/code&gt; (we called it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secure_headers.rb&lt;/code&gt;). Then configure it using something like this&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`secure_headers`&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;SecureHeaders&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Configuration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;csp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;default_src: &lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%w('self')&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;font_src: &lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%w('self' data:)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;img_src: &lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%w('self' www.google-analytics.com)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;object_src: &lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%w('self')&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;script_src: &lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%w('self' 'unsafe-inline' www.googletagmanager.com www.google-analytics.com)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;style_src: &lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%w('self')&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;report_uri: &lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%w(https://mycustomname.report-uri.io/r/default/csp/enforce)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So now we’re saying&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;All external scripts must be sourced from either the service, googletagmanager.com, or google-analytics.com, plus inline scripts are permitted to run&lt;/li&gt;
  &lt;li&gt;All images must be sourced from either the service or google-analytics.com (GA because it sends the data to the Analytics server via a list of parameters attached to a single-pixel image request)&lt;/li&gt;
  &lt;li&gt;All fonts must be sourced either from the service or via a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data: scheme&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Browsers should report any violations of this policy to the &lt;a href=&quot;https://report-uri.io/&quot;&gt;service we have setup&lt;/a&gt; for this CSP&lt;/li&gt;
  &lt;li&gt;For everything else default to requiring the source to be the service itself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(By the way, big thank you to &lt;a href=&quot;https://foundeo.com/&quot;&gt;Foundeo Inc&lt;/a&gt; for putting up an &lt;a href=&quot;https://content-security-policy.com/faq/&quot;&gt;faq post on CSP that covered Google Analytics&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id=&quot;further-reading-and-references&quot;&gt;Further reading and references&lt;/h2&gt;

&lt;p&gt;There are loads of good doc’s on the specifics of how to define a security policy.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I found &lt;strong&gt;Scott Helme’s&lt;/strong&gt; CSP cheat sheet very helpful &lt;a href=&quot;https://scotthelme.co.uk/csp-cheat-sheet/&quot;&gt;https://scotthelme.co.uk/csp-cheat-sheet/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Plus his associated blog post &lt;a href=&quot;https://scotthelme.co.uk/content-security-policy-an-introduction/&quot;&gt;https://scotthelme.co.uk/content-security-policy-an-introduction/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;For an actual reference I used Mozilla’s documents &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To really road test your site I’d also highly recommend &lt;strong&gt;Scott’s&lt;/strong&gt; online tool &lt;a href=&quot;https://securityheaders.io/&quot;&gt;securityheaders.io&lt;/a&gt;. If you’re like me you’ll run this tool and then immediately want to aim for an &lt;strong&gt;A+&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;We also ended up using his CSP violation reporting tool &lt;a href=&quot;https://report-uri.io/&quot;&gt;report-uri.io&lt;/a&gt; as a simple to use, and most importantly &lt;strong&gt;&lt;em&gt;free&lt;/em&gt;&lt;/strong&gt; solution for capturing any violations.&lt;/p&gt;
</content>
		</entry>
	
		<entry>
			<title>Jekyll and GitHub pages oh my!</title>
			<link href="http://cruikshanks.co.uk/blog/jekyll-and-github-pages-oh-my/"/>
			<updated>2017-04-15T00:00:00+00:00</updated>
			<id>http://cruikshanks.co.uk/blog/jekyll-and-github-pages-oh-my</id>
			<content type="html">&lt;p&gt;So it was always on the to-do list to sort out my site, and recently I embarked on a venture (more about that in future posts) which involved me sending someone a link and them ending up on said site.&lt;/p&gt;

&lt;p&gt;Only it wasn’t up, and to be honest if it was there wouldn’t have been anything to see. I’d already been pondering posting my lessons learnt rather than just squirreling them away in &lt;a href=&quot;https://evernote.com/&quot;&gt;Evernote&lt;/a&gt;, so this felt like the time to pull my finger out and fix it.&lt;/p&gt;

&lt;p&gt;I’d played with &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; as part of some work stuff, and knew about &lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt; so figured this would be a good opportunity to get to grips with both. Plus it seemed a low friction way to maintain my personal web site in the future.&lt;/p&gt;

&lt;h2 id=&quot;its-for-newbs-right&quot;&gt;It’s for newbs, right?&lt;/h2&gt;

&lt;p&gt;Or certainly that’s what the GitHub Pages &lt;a href=&quot;https://pages.github.com/&quot;&gt;intro page&lt;/a&gt; made me believe. I started by following the steps provided and yep, I had my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello world&lt;/code&gt; version up and running in no time.&lt;/p&gt;

&lt;p&gt;But I knew I wanted the ability to create and run stuff locally, and like, presumed Jekyll had to feature somewhere so moved onto the next step of &lt;a href=&quot;https://jekyllrb.com/docs/quickstart/&quot;&gt;setting up Jekyll&lt;/a&gt; (this is linked to from the GitHub Pages site).&lt;/p&gt;

&lt;p&gt;So got that all running, pushed it up and now I had an out of the box Jekyll site accessible from &lt;a href=&quot;http://cruikshanks.github.io&quot;&gt;http://cruikshanks.github.io&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;themes&quot;&gt;Themes&lt;/h2&gt;

&lt;p&gt;Well that’s nice, but the first thing I wanted to do was select a different theme. And from what &lt;a href=&quot;https://help.github.com/articles/adding-a-jekyll-theme-to-your-github-pages-site/&quot;&gt;I was reading&lt;/a&gt; that just seemed to require a tweak to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;But whenever I did this it just caused a mass of errors. Plus the docs weren’t quite lining up with how I’d created my site.&lt;/p&gt;

&lt;p&gt;Did I need to do this in my &lt;a href=&quot;https://help.github.com/articles/adding-a-jekyll-theme-to-your-github-pages-site/#adding-a-jekyll-theme-to-your-site&quot;&gt;GitHub settings&lt;/a&gt; as well? Or was I supposed to be &lt;a href=&quot;https://help.github.com/articles/adding-a-jekyll-theme-to-your-github-pages-site/#adding-your-theme-as-a-gem-to-your-gemfile&quot;&gt;adding the theme&lt;/a&gt; as a gem to my Gemfile?&lt;/p&gt;

&lt;p&gt;Whatever I was trying my stuff simply broke the moment I touched it. Clearly I was missing something, but I couldn’t tell if it was my ignorance or existing knowledge that was getting in the way.&lt;/p&gt;

&lt;h2 id=&quot;some-googling-later&quot;&gt;Some googling later&lt;/h2&gt;

&lt;p&gt;After some googling and experimentation I realised the following&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If you want the simplest, out of the box GitHub Pages solution, then create your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my-org-name.github.io&lt;/code&gt; project, go to settings, select your theme, and start adding stuff via the GitHub web UI&lt;/li&gt;
  &lt;li&gt;If you want a supported Jekyll solution, so you can run the site locally to view changes before pushing them then find the theme you’re interested in and fork the project&lt;/li&gt;
  &lt;li&gt;The latest version of Jekyll themes are managed via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gemfile&lt;/code&gt; using gems, but this is &lt;a href=&quot;https://jekyllrb.com/docs/themes/#installing-a-theme&quot;&gt;not supported in GitHub Pages&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;There are some nice themes out there (I started looking into &lt;a href=&quot;https://github.com/mmistakes/minimal-mistakes&quot;&gt;Minimal Mistakes&lt;/a&gt;) but if you have no clue what you are doing, changing anything just seems to lead to lots of errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;ta-da&quot;&gt;Ta-da!&lt;/h2&gt;

&lt;p&gt;Then I came across the &lt;a href=&quot;https://jekyllrb.com/docs/github-pages/&quot;&gt;GitHub Pages page&lt;/a&gt; in the Jekyll docs and it led me to &lt;a href=&quot;http://jmcglone.com/guides/github-pages/&quot;&gt;Creating and Hosting a Personal Site on GitHub&lt;/a&gt;, a &lt;em&gt;marvellous guide&lt;/em&gt; in Jekyll’s own words.&lt;/p&gt;

&lt;p&gt;Rather than generating a project with Jekyll or forking an existing one from GitHub, the guide has you create a project from scratch.&lt;/p&gt;

&lt;p&gt;This helped cement how layouts work and how they link with the actual content, what &lt;a href=&quot;https://jekyllrb.com/docs/frontmatter/&quot;&gt;front matter&lt;/a&gt; does and essentially how a Jekyll site is structured. I could then combine this with lessons learnt during my experimentation to get a desired result. A GitHub pages compatible Jekyll based web site that I could deploy and run locally, which &lt;em&gt;I understand&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;After feeling like a dunce trying to get this up and running that last point was critical.&lt;/p&gt;

&lt;h2 id=&quot;small-steps&quot;&gt;Small steps&lt;/h2&gt;

&lt;p&gt;So &lt;a href=&quot;https://github.com/Cruikshanks/cruikshanks.github.io&quot;&gt;what I’m left with&lt;/a&gt; is a very basic web site which does very little at the moment, and which has a tonne of ways it could be improved. But its simple, easy to maintain and something I can build on going forward.&lt;/p&gt;

&lt;p&gt;I can now get on with recording what I’ve learnt as posts, if only to prove to anyone watching that I do care about my work. If they happen to be of help; all the better!&lt;/p&gt;
</content>
		</entry>
	

</feed>
