Docker rocks. Boot2docker just sucks.

Overview

Updates November 2015

Boot2Docker

To everyone on OSX or Windows: Don’t let Boot2docker leave you with the impression that Docker sucks! It’s really just your antique OS.

  1. Docker is amazing, period.
  2. However it’s rough-around-the-edges, hackey utility, boot2docker - for OS X, Windows and old Linux Kernels - leaves a lot to be desired.

Issues

Boot2docker causes 99/100 headaches compared with using a native docker install locally. I should concede that it wraps several other complicated/flakey technologies: VirtualBox, x-platform Folder Sharing, and also the docker cli command runs in a network-client mode so, file copying, builds etc take a long time vs. running a native docker server. ============= Docker can currently only run natively on a Linux Kernel 3.4+ - and the current boot2docker vm actually runs v4. Bottom Line: Install the Latest Debian (w/ xfce or MATE) on your Mac/Windows box, … c’mon those games aren’t helping your code…

Boot2docker Key Commands

When you get error: ‘FATA[0000]’

  • Full error message:
    • FATA[0000] Get http:///var/run/docker.sock/v1.18/info: dial unix /var/run/docker.sock: no such file or directory. Are you trying to connect to a TLS-enabled daemon without TLS?
  • Solution: You need some info from boot2docker
    • Run this to get the 3 needed shell environment variables:
boot2docker shellinit
# Copy & paste the exports into the current shell, & retry $(docker info)

Get Docker Server IP Address

boot2docker ip

Now your app on port 3000 is available at something like: http://$(boot2docker ip):3000/

Boot2Docker Quick Start for OS X

  1. In a terminal on your brew able Mac:
brew install boot2docker
boot2docker init
boot2docker up
JavaScript Magic

[ Work-in-progress, Includes Future JavaScript Article Ideas ]

This post is geared to modern browsers and Node.JS/iojs.

Imperative vs. Recursive vs. Functional


// Imperative: The Fastest ( + very simple, no new pointers or excess allocs ):
function fib(n) {
  var a = 1, b = 1, c = 0;
  for(var i = 1; i < n-1; ++i) {
    c = a + b;
    a = b;
    b = c;
  }
  return b;
}

// Recursive: (FIREFOX or BABELJS Only) ES6 function definition with
//  parameter defaults used to set initial (internal/recursive) values
function fib(n, current=0, a=1, b=1, c=0) {
  current++;
  c = a + b;
  a = b;
  b = c;
  return current >= n ? b : fib(n, current, a, b, c);
}

// Text-book-Bad Example - poor function scope w/ multiple mutable external values
function fib(n) {
  if (!arr) { var arr = [1,1]; n=n-2; };// Bad
  if (n===-1) {return [arr[0]];}
  if (n===0) {return arr;}
  var proc = function() {
    --n;
    arr.push(arr[arr.length-1] + arr[arr.length-2]);
    return (n===0 ? arr : proc());
    // Bad: inner recursive function not needed, hint: variables used are from parent function scope
  };
  var ans = proc();
  return ans[ans.length-1];
}

Promises: Awesome!


// Example Using bluebird Promises and it's
var Promise = require('bluebird'),
    fs = Promise.promisifyAll(require('fs')),
    less = Promise.promisifyAll(require('less'));

function writeFileData(data) {
  return fs.writeFileAsync('/tmp/output.css', data);
}
// Bluebird makes something like this perhaps uncomfortably simple and succinct:
fs.readFileAsync('./style.less') // Call promisified readFile()
  .then(less.renderAsync)         // Hand off to less.render
  .then(writeFileData);      // Function to recieve the css contents (1st parameter)

  1. While, native ES6 Promises are great, I prefer the robust Bluebird Promise Library.
  2. Library or not, modern browsers have supported Promise for years.
  3. Promises can be utilized without crazy patterns - implicit deferred is preferable.
  4. $q just sucks just use bluebird, see above.
  5. Worth mentioning: Bluebirds Benchmarks are best-case tests, so take note if doing crazy fancy promise chains

Java vs JavaScript

Rate Limiting / Debouncing / Throttling

  1. In JavaScript David Walsh implemented debounce in less than 20 lines!
  2. In Java, JDebounce, an library which is a lot more complicated, at ~500+ lines.
  3. _ Comparing the two: _
  4. The JavaScript is fast & uses first-class functions to achieve brilliant simplicity.
  5. Whereas the Java has many more moving parts, annotations are used to apply behaviour at compile-time, and there’s a ton of XML, just for funsies!

Inversion of Control Techniques

Work-in-progress

Docker Firewall Setup

Setup Docker Host Firewall

  1. Debian/Ubuntu Server is assumed
  2. Designed to run on Docker Host Server

Install Requirements

# Ultimate Firewall Needed
apt-get update && apt-get install -y ufw nmap curl

Get your Internal & External IP Addresses

# Get your IP Addresses, simple output:
hostname --all-ip-addresses

# OR use ip tool, example:
ip addr

Firtewall (UFW) Setup - Example Cmds

ufw logging on # on=low - medium might be better for diagnostics
ufw logging medium
# First, block all the things
ufw default deny incoming

# REQUIRED: CHOOSE *ONE* OF THE FOLLOWING DEFAULT OUTBOUND RULES:
ufw default deny outgoing
ufw default allow outgoing


# Allow and log all new ssh connections,
ufw allow log proto tcp from any to any port 22
## Allow http traffic (w/o explicit logging)
ufw allow out on docker0 53/udp to 172.17.0.1/16
ufw allow out on eth0 to any port 53
ufw allow out on eth0 from 0.0.0.0/0 to any port 80 proto tcp
ufw allow out on eth0 from 0.0.0.0/0 to any port 443 proto tcp

# Verbose: ufw allow proto tcp from any to any port 80
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow log 22/tcp
ufw limit ssh # Basic Rate limit 4 SSH brute force mitigation

# Set your ext IP
export EXTERNAL_IP=123.123.123.123
# Update docker IP if needed
export DOCKER_IP=172.17.42.1
# Forward tcp 8080 traffic to  Dockerized App
ufw allow proto tcp from $EXTERNAL_IP port 8080 to $DOCKER_IP port 3000

Enable / Start Firewall

Be Careful, Don’t Lock out your SSH port (sshd defaults to 22)

ufw --force enable

ufw reset

Test Your Firewall

Important: USE A REMOTE IP ADDR/LOCATION

# Verify dependency
apt-get update && apt-get install -y nmap

# Set scan target
export TARGET_HOST=123.123.123.123

# Example Scan Commands:
# Fast open port check
nmap -p 1-10240,27017 -T5 $TARGET_HOST
# Thorough scan
nmap -p 1-10240,27017 --open -v -APN $TARGET_HOST
# Svc Inspection
nmap -p 1-10240,27017 -O --osscan-guess $TARGET_HOST

DONE! Now you should see ONLY the ports you configured!

Docker server Setup

Docker Host Server Setup

Basic Monitoring Tools

# Debian/BSD Requirements / Updates + monitoring tools: atop & htop
apt-get update && apt-get install -y vim-nox git-core curl atop htop build-essential libssl-dev linux-image-amd64 linux-headers-amd64 sudo

# OSX, Debian & RHEL: Host OS Tuning
sysctl -w vm.max_map_count=262144

# Updates Profile init scripts before appending new scripts below
mkdir ~/backups
cp ~/.bash* ~/backups/

# Debian/BSD:  Append Shell Environment Shortcuts + XTERM Colors
curl -o- https://raw.githubusercontent.com/justsml/system-setup-tools/master/modules/vim-update.sh | bash

curl -sSL https://raw.githubusercontent.com/justsml/system-setup-tools/master/home-scripts/.bashrc >> ~/.bashrc
curl -sSL https://raw.githubusercontent.com/justsml/system-setup-tools/master/home-scripts/.bash_aliases >> ~/.bash_aliases
# Read into current shell (login steps already missed the aliases file)
source ~/.bashrc

# Docker pre reqs
# sudo apt-get install -y linux-image-virtual linux-image-extra-virtual
# Install Docker, straight from the horses mouth
curl -sSL https://get.docker.com/ | sh

Only for SELinux Enabled Systems

# SELinux fixes (optional)
# chcon -Rt svirt_sandbox_file_t /mongodb
# chcon -Rt svirt_sandbox_file_t /elastic

Simple Database Setup/Startup

MongoDB v3 Server

mkdir /mongodb
docker run --name mongo -p 27017:27017 -v /mongodb:/data -d mongo:latest bash -c 'mongod --logpath /data/mongodb.log --logappend --dbpath /data/data --storageEngine=wiredTiger'
mkdir /elastic
docker run --name elastic -d -p 9200:9200 -p 9300:9300 -v /elastic:/data elasticsearch bash -c 'elasticsearch --cluster.name elastic_cluster --node.name elastic01 --path.data /data/elastic-data --path.logs /data/elastic-logs '

You just lit up 2 database docker instances!!! If it were any easier, I’m pretty sure you couldn’t invoice for it.

Package up your NodeJS/Ruby/Python/Web App

  1. Add a blank file named Dockerfile in your project root.
  2. (Optional, Recommended) Add a .dockerignore using .gitignore rules to exclude large non-essential paths. By default all project files are included.

Create a Dockerfile

# Example for NodeJS
FROM node:0.12
EXPOSE [3000]
COPY . /app/
WORKDIR /app
RUN apt-get update \
	&& apt-get dist-upgrade -y
RUN ["npm", "install"]
# Overridable Command
CMD ["npm", "start"]

It’s easier to show how to start using the Dockerfile and demonstrate the results via console (see commands below).

In terminal, cd to your project folder and run the following build command everytime you deploy changes - or want to change/upgrade OS or Env config)

docker build -t app-name-here .

Docker Commands to Learn

Build Docker Image Every Deploy/Change

docker build -t app-name-here .
docker run -d --name webapp01 -p 3000:3000 --link mongo:mongo --link elastic:elastic app-name-here

Run Interactively (non-daemon, in terminal)

docker run -it --name webapp01 -p 3000:3000 --link mongo:mongo --link elastic:elastic app-name-here bash

Delete Container Instance or Image

Important: Any data not stored on the mounted volume path will be lost!!

# Delete Image
docker rmi -f app-name-here
docker rm -f webapp01
# now re-run your `docker run...` from ^^^
# So for example, let's kill your db instances above, run: ( start with something like `docker stop {mongo,elastic}` )
docker rm -f mongo elastic
Winning Design Resource

Solve 2 UI challenges

Your Prototype Apps Suck: So sprinkle some awesome in there

Beautiful Sliding Menus

Side-Menu Demo

Note: Not my code, however I’ve evaluated it and I have to say I rarely find code at this level. Like, never, folks. The author, Mary Lou is just incredibly talented.

Impressive Tooltips

View demo

Wow! … Am I Right?

Misc

I know I said it, but let me emphasize: All the code is extraordinarily well doneI never say that, most devs rarely bother to be this meticulous

Btw, I say ‘prototype apps’ merely because the examples need a few accessability/usability tweaks (which are described in Mary’s articles).

Here’s where I found this stuff: follow codrops at https://twitter.com/codrops

Tag Cloud