TL;DR

How to install and configure Docker on OSX and Ubuntu.
What are the basic Docker commands,
then more useful example of how to build Docker images.
This howto also includes many handy Docker tips and
in addition some suggestions for what to use Docker with
and how to host your containers.

Why Docker

Docker is a great invention. Both for operations of deploying and hosting of systems and also for developers.

Docker is a virtual operating system container.
It allows you develop and run one or several systems on your computer or server isolated from your actual OS.
This protects your host system, but also easy to clone, extend, scale and share containers.

Virtualisation is nothing new.
Mainframes has split virtually into many systems per real server for decades.
VMWare have created a huge enterprise selling many solutions for virtualising servers and desktops.
Sun then Oracle developed the popular open source software VirtualBox.
Xen powers Amazon's AWS EC2 cloud servers that host a huge portion of the worlds internet servers.
Every other IAAS and PAAS provider use virtualisation extensively.

VMWare Workstation with Ubuntu for many years was my way to overcome companies' standardised Windows environments.
Frequently teams use VirtualBox to share images of company essential tools,
E.g. Windows preconfigured with DB2 or SQL Server, or just to test with Microsoft Internet Explorer and Outlook etc.

A colleague introduced me to Vagrant a few years ago,
and I have since used it extensively.
It is basically Virtualbox without any GUI, just command line.
It allows you to run many virtual servers locally and usually for just one purpose.
E.g. to develop one application. And to quickly scratch and rebuild these environments.
I also use Vagrant to test server images locally
with e.g. Puppet provisioning, before pushing it to a data center or IAAS.

Docker's great distinguisher is that it shares the hosts memory and disk space so you no longer need to reserve memory per VM.
Docker also only stores files that are different from the host base.
This makes Docker great for single purpose (often single thread) applications.
In fact Docker containers often shut down when application thread is no longer running.
But they resume really quickly.

This sets the provisioner as Docker,
so Docker is installed and ready to use.
The Docker IP address will be displayed when logging in.
Vagrant will also resume all Docker containers when the VM restarts.

It sets a recognisable hostname.
Disabling guest additions updates for this specific instance is advisable.
It also includes examples for syncing folders
and increasing the allocated memory.

anyhost$ vagrant up;anyhost$ vagrant ssh

This boots it up and logs you in.

Vagrant + CoreOS

CoreOS is another Linux distribution that is designed to run and scale across multiple servers from the start.
CoreOS' philosophy views Docker as a core part of their offering.

I would suggest once you are comfortable with Ubuntu as Docker host to try out CoreOS as well. Use Vagrant with CoreOS locally.

Note: CoreOS is ideal as host only, you would probably still use Ubuntu as Docker base image
.

Docker + Ubuntu

Your Docker applications will mostly be based of one base image.
In my case mostly Ubuntu, though sometimes Debian.

Recursive Ubuntu

This could in theory be your second or third level of Ubuntu within Ubuntu. Ubuntu Host + Vagrant with Ubuntu + Docker with Ubuntu.

Docker's Ubuntu

This downloads Docker's Ubuntu image
and stores it locally.
Docker has a range of ready made images in their registry.
Later you can easily upload your images to this register.

Phusion's Ubuntu

Phusion has adapted Ubuntu to be more
compatible with Docker.
This is because Docker images simply
are not a full blown server with a normal lifecycle.
Instead it is limited to how many threads
can run and also when it suspends/shuts down.
A majority of Docker examples and code you find online assumes this is the base image used.

dockerhost$ docker pull phusion/baseimage

Debian

Ubuntu is based on Debian, and the base Debian image is smaller than Ubuntu,
which might make a difference.

dockerhost$ docker pull debian:wheezy

Basic Docker

dockerhost$ docker ps

Lists all Docker processes running.

dockerhost$ docker ps -la

Lists the latest Docker processes including the ones that has finished.

CONTAINER ID

IMAGE

COMMAND

CREATED

STATUS

PORTS

NAMES

Nothing has been run yet so these will initially be empty.

dockerhost$ docker run ubuntu /bin/bash

Starts a docker image using the Ubuntu image
and runs a bash process. And immediately stops it as nothing else is specified.

dockerhost$ docker ps

As the bash process finished quickly it won't still be running.

dockerhost$ docker ps -a

CONTAINER ID

IMAGE

COMMAND

CREATED

STATUS

PORTS

NAMES

98765defgh

ubuntu:14.04

"/bin/bash"

11 seconds ago

Exited (0) 11 seconds

stoic_pike

But it will be listed as having finished.
Note the container id column.

dockerhost$ docker run -t -i ubuntu /usr/bin/top

This starts and keeps a process running.
In another shell list processes.
(log into the vagrant instance if applicable)

This diff lists files changed by your process.
Should list /example.txt and /.bash_history.

dockerhost$ docker commit 12345abcdmycoolimages/example-image:0.1

This creates an image we can recreate, base other images on etc.

dockerhost$ docker images | head

REPOSITORY

TAG

IMAGE ID

CREATED

VIRTUAL SIZE

mycoolimages/example-image

0.1

0123abcd00

10 seconds ago

194.2 MB

ubuntu

14.14

112233445566

10 days ago

194.2 MB

...

Lists images created by you, and all the downloaded images as well.Helpfully lists their relative size difference from their base image.
As you can see mycoolimages/example-image:0.1 is listed at the top.

Useful Docker

Now you know how to launch docker images
and how to make docker images.
Lets now create some more useful images.

A Dockerfile is used in a similar fashion
to a Vagrantfile.
It describes what an image is based on,
what to do with it, e.g. what to provision,
and which processes to run on it.

Lets create one that install and runs an Apache web server inside Docker.
And shows a specific index.html file.

Handy Docker

Folder volumes

This shares the local folders with the Docker container
as a volume.
/vagrant/www is shared as /var/www
in a read only mode.
/vagrant/logs is shared as /var/logs/apache2
in a read and write mode.

Note for the image we created earlier (mycoolimages/apache)
this will cause a conflict as
we already added the
index.html file to /var/www.
So create a different image first.

The example includes the path /vagrant which is if your Docker host is a Vagrant VM.
The /vagrant folder is the automatically shared folder from your
real host's folder containing the Vagrantfile.
If you want to share other folders between your host and Vagrant add
lines like these to the Vagrantfile.

config.vm.synced_folder "/opt/mysite", "/var/www"

This makes the host's /opt/mysite folder
available as /var/www inside Vagrant.

Obviously if you use Docker natively you
can share any path directly as a volume.

Every week I find new amazing tools for Docker and containers in general.

Private registry

You may not want to upload all your images to the public Docker registry.
You may have experimental builds, builds containing sensitive data, etc.

For that Docker provides a registry you can run locally.
As it just runs as another Docker container, please remember to export and backup your images.

Commercial offerings are available via Quay.io.
Eventually there will be a sea of alternatives similar to today's multiple options for hosting Git repositories.

What to Docker

Building on what you would often use virtual machines
and Vagrant for already.

Development

Whether it is a complex application or simple web site,
having a Docker container per application is a nice separation.
Multiple containers for different versions, branches, target environments etc is also useful.
With source code folders added as volumes locally.

You can use linking as explained earlier to
run a complex system of multiple containers locally.
Also using the previously mentioned idea of adding Docker IPs host files
can make the separation clearer and assist
in virtual hosting and session cookie etc.

Continuous Delivery

One good aspect of Docker container images,
is that not just your application binary
is part of the delivery but the entire fully provisioned container image.
So no risk of wrong Java version being installed,
no risk that staging and production environments are different,
etc.

You could achieve this already
by e.g. baking AWS AMIs containing your binary or creating .deb packages.
But a Docker image is a lot smaller,
so quicker to continuously build, ready to ship and scale.

Testing and Demonstrations

By packaging the entire environment
you can quickly share and spin up any application environment.
This means testing can quickly be switched and shared.
Demos can run without risk of environment suddenly going down and switch quickly to different versions.

Databases

No need for every machine to install every specific flavour and versions
of a database.
Just share a container image instead of bloating all the laptops etc.
Especially useful for testing multiple nodes locally.

This is the same for any other stand alone application,
e.g. an ESB, a MQ solution,
a black box third party application, etc.

Clustering / horizontal scaling

As images can be spun up at any time, similar to other virtual machines,
you can scale your applications or databases horizontally easily.
But with Docker this will be a much more lightweight burden
on the CPU and memory requirements.

Exploration

If just testing out some new technology,
or installing an application you don't trust
on your host computer,
then just create a Docker image of it.
Although I probably would investigate it with Vagrant initially.

Docker Hosting

Docker opens up some exciting possibilities for rolling your own dynamic virtualised hosting,
also known as a private cloud and as IAAS and PAAS.
However the major public cloud / IAAS providers do also support Docker.