Boot2Docker dom0 and more docker orchestration magic.

I’ve modifyed boot2docker to

Auto-start an image named ‘dom0:latest’. This image then orchestrates the remainder of the system.
This personal dom0 image starts sshd and the containers I want this system to auto-run.
I also set up a `home-volume` container, which I -volumes-from mount into all my development containers.

All kicked off by the sd-card boot2docker.

So, some concrete examples for my previous Boot2Docker rules post:dom0boot2docker

I’m modifying boot2docker to

  1. if present, auto-start an image named ‘dom0:latest’. This image then orchestrates the remainder of the system.
  2. my personal dom0 image starts sshd and the containers I want this system to auto-run.
  3. Set up a `home-volume` container, which I -volumes-from mount into all my development containers.

When I do some development, testing or production, it happens in containers, the base OS is pristine, and can be trivially updated (atm, i’m using boot from USB flash and SD Card).

Similarly, the dom0 container is also a bare busybox container, cloned from the filesystem of the boot2docker image itself.. I’m not ready for my end goal of doing this to my notebook and desktop – but then, this setup is only a few days old :).

This setup uses my detect existing /var/lib/docker on HD pull request , and the dom0-rootfs, dom0-base and dom0 images, and then from there, and initial dev image.

2 customisations I’ve made to the boot2docker are persisted on the HD – /var/lib/boot2docker/etc/hostname is set to something useful to me, and the optional /var/lib/boot2docker/bootlocal.sh script starts the dom0 container at boot.

When I need a set of containers started, I can create a tiny orchestration container that can talk to the docker daemon and thus start more containers, controlling how they interact with each other and the outside world.

 

Boot2Docker for orchestration.

Imagine that you have a PXE / USB / boot setup that boots in seconds, and as its last step, starts a docker privileged image labeled ‘dom0:latest’.

Most importantly, each of these servers then would ‘docker pull’ and ‘docker run’ the services and applications it provides – without modifying the base OS, or ‘dom0’

It also gives the server farm admin the opportunity to make a customized ‘dom0:latest’ image – containing the farm’s ‘dom0:latest’ thus orchestrating the inner container configurations further.

 

I’m using boot2docker on my ‘docker-server’ (an old x61 thinkpad), and using the inbuilt harddrive to store the docker images that are run on it. I’m totally avoiding modifying the base OS, and doing all the work in containers – enabling very fast run and teardown for development and testing.

now if only ‘turnbull-net’ wasn’t totally useless for pulling images (gee, thanks Malcolm Turnbull, 1MB ADSL with constant dropouts in the middle of Brisbane is sooooooo conducive to working).

 

Docker container network portability

Rather than hardcoding network links between a service consumer and provider, Docker encourages service portability.

eg, instead of 2 containers talking directly to each other:

(consumer) --> (redis)

requiring you to restart the consumer to attach it to a different redis service, you can add ambassador containers:

(consumer) --> (redis-ambassador) --> (redis)

or

(consumer) --> (redis-ambassador) ---network---> (redis-ambassador) --> (redis)

When you need to rewire your consumer to talk to a different resdis server, you can just restart the redis-ambassador container that the consumer is connected to.

This pattern also allows you to transparently move the redis server to a different docker host from the consumer.

Using the svendowideit/ambassador container, the link wiring is controlled entirely from the dockerrun parameters.

Two host Example

Start actual redis server on one Docker host

big-server $ docker run -d -name redis crosbymichael/redis

Then add an ambassador linked to the redis server, mapping a port to the outside world

big-server $ docker run -d -link redis:redis -name redis_ambassador -p 6379:6379 svendowideit/ambassador

On the other host, you can set up another ambassador setting environment variables for each remote port we want to proxy to the big-server

client-server $ docker run -d -name redis_ambassador -expose 6379 -e REDIS_PORT_6379_TCP=tcp://192.168.1.52:6379 svendowideit/ambassador

Then on the client-server host, you can use a redis client container to talk to the remote redis server, just by linking to the local redis ambassador.

client-server $ docker run -i -t -rm -link redis_ambassador:redis relateiq/redis-cli
redis 172.17.0.160:6379> ping
PONG

How it works

The following example shows what the svendowideit/ambassador container does automatically (with a tiny amount of sed)

On the docker host (192.168.1.52) that redis will run on:

# start actual redis server
$ docker run -d -name redis crosbymichael/redis

# get a redis-cli container for connection testing
$ docker pull relateiq/redis-cli

# test the redis server by talking to it directly
$ docker run -t -i -rm -link redis:redis relateiq/redis-cli
redis 172.17.0.136:6379> ping
PONG
^D

# add redis ambassador
$ docker run -t -i -link redis:redis -name redis_ambassador -p 6379:6379 busybox sh

in the redis_ambassador container, you can see the linked redis containers’s env

$ env
REDIS_PORT=tcp://172.17.0.136:6379
REDIS_PORT_6379_TCP_ADDR=172.17.0.136
REDIS_NAME=/redis_ambassador/redis
HOSTNAME=19d7adf4705e
REDIS_PORT_6379_TCP_PORT=6379
HOME=/
REDIS_PORT_6379_TCP_PROTO=tcp
container=lxc
REDIS_PORT_6379_TCP=tcp://172.17.0.136:6379
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/

This environment is used by the ambassador socat script to expose redis to the world (via the -p 6379:6379 port mapping)

$ docker rm redis_ambassador
$ sudo ./contrib/mkimage-unittest.sh
$ docker run -t -i -link redis:redis -name redis_ambassador -p 6379:6379 docker-ut sh

$ socat TCP4-LISTEN:6379,fork,reuseaddr TCP4:172.17.0.136:6379

then ping the redis server via the ambassador

Now goto a different server

$ sudo ./contrib/mkimage-unittest.sh
$ docker run -t -i  -expose 6379 -name redis_ambassador docker-ut sh

$ socat TCP4-LISTEN:6379,fork,reuseaddr TCP4:192.168.1.52:6379

and get the redis-cli image so we can talk over the ambassador bridge

$ docker pull relateiq/redis-cli
$ docker run -i -t -rm -link redis_ambassador:redis relateiq/redis-cli
redis 172.17.0.160:6379> ping
PONG

The svendowideit/ambassador Dockerfile

The svendowideit/ambassador image is a small busybox image with socat built in. When you start the container, it uses a small sed script to parse out the (possibly multiple) link environment variables to set up the port forwarding. On the remote host, you need to set the variable using the -e command line option.

-expose 1234 -e REDIS_PORT_1234_TCP=tcp://192.168.1.52:6379 will forward the local 1234port to the remote IP and port – in this case 192.168.1.52:6379.

#
#
# first you need to build the docker-ut image using ./contrib/mkimage-unittest.sh
# then
#   docker build -t SvenDowideit/ambassador .
#   docker tag SvenDowideit/ambassador ambassador
# then to run it (on the host that has the real backend on it)
#   docker run -t -i -link redis:redis -name redis_ambassador -p 6379:6379 ambassador
# on the remote host, you can set up another ambassador
#    docker run -t -i -name redis_ambassador -expose 6379 sh

FROM    docker-ut
MAINTAINER      SvenDowideit@home.org.au

CMD     env | grep _TCP= | sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/'  | sh && top

(this is pull request https://github.com/dotcloud/docker/pull/3038 so will eventually find its way into the Docker documentation)

Docker 0.7 is here – welcome RPM distros (and anyone else that lacks AUFS)

The Docker project has continued its mostly-monthly releases with the long anticipated 0.7 release, this time making the storage backend pluggable, so fedora/redhat based users can use it without building a custom kernel.

The Docker project has continued its mostly-monthly releases with the long anticipated 0.7 release, this time making the storage backend pluggable, so fedora/redhat based users can use it without building a custom kernel.

I’m curious to see the performance differences between the 3 storage backends we have now – but I need to assimilate the wonders of Linking containers for adhoc scaling first.

Try it out – I’m even more convinced that Docker containers have an interesting future 🙂

easy install of Docker.io on Debian

UPDATE: for Docker 0.6.5, the ubuntu debian package also installs on Debian. You still need to enable IPv4 forwarding as below – then re-start the docker daemon

I’ve been doing some work on Docker – learning golang, Docker internals, and just some of the command line options that I didn’t know I needed to know about.

Because I was in a hurry, I threw an old unused disk into one of my old laptops and installed ubuntu. That was enough for me to learn that I wanted to know alot more about Docker.

So, I’m back to using the loaner T530 with my 128GB SSD in it – its been running Debian since the day I got the SSD, over 2 years ago.

it turns out that on Debian testing (with the 3.10-3-amd64 kernel), its incredibly easy to run docker:

sudo apt-get install lxc wget bsdtar curl golang git aufs-tools mercurial iptables
wget --output-document=docker https://get.docker.io/builds/Linux/x86_64/docker-latest
chmod +x docker
sudo su -
#enable IPv4 forwarding
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf
# set up and mount the cgroup mountpoint
echo 'none /sys/fs/cgroup cgroup defaults 0 0' | sudo tee -a /etc/fstab
mount /sys/fs/cgroup
#OK, you might need to reboot if it fails to mount?
./docker -d &

done.
from there, you can run the docker cli like normal (except that its not in your path yet).

I’m going to pull over the apt pinning installation documentation I wrote for publican the other week and re-write it (and test) for installing docker on Debian Stable, and we’ll all be much happier.

I wonder if Docker can replace Puppet.

I’m curious to see how hard it would be to push out Docker versioned configuration changesets over ssh to ‘anywhere’, with some kind of idempotency via system ‘tags’.

I’ve finally spent a little time playing with Docker, and to be honest, the really simple

here’s a list of commands that get run to set up the image

feels awesome.

to test it out, I wrote the simplest steps I could think of to create a working foswiki installation into a Dockerfile:

FROM ubuntu
MAINTAINER    Sven Dowideit <svendowideit@home.org.au>

RUN echo deb http://fosiki.com/Foswiki_debian/ stable main contrib > /etc/apt/sources.
list.d/fosiki.list
RUN echo deb http://archive.ubuntu.com/ubuntu precise main restricted universe multive
rse >> /etc/apt/sources.list
RUN gpg –keyserver the.earth.li –recv-keys 379393E0AAEE96F6
RUN apt-key add //.gnupg/pubring.gpg
RUN apt-get update
RUN apt-get install -y foswiki

#create the tmp dir
RUN mkdir /var/lib/foswiki/working/tmp
RUN chmod 777 /var/lib/foswiki/working/tmp
#TODO: randomise the admin pwd..
RUN htpasswd -cb /var/lib/foswiki/data/.htpasswd admin admin
RUN mv /etc/foswiki/LocalSite.cfg /etc/foswiki/LocalSite.cfg.orig
RUN grep –invert-match {Password} /etc/foswiki/LocalSite.cfg.orig > /etc/foswiki/Loca
lSite.cfg
RUN chown www-data:www-data /etc/foswiki/LocalSite.cfg

RUN bash -c ‘echo “/usr/sbin/apachectl start” >> /.bashrc’
RUN bash -c ‘echo “echo foswiki configure admin user password is ‘admin'” >> /.bashrc’

EXPOSE 80

and then I can create the image with a simple:

docker build -t svendowideit/ubuntu-foswiki .

and run that image by calling:

docker run -t -i -p 8888:80 svendowideit/ubuntu-foswiki /bin/bash

Which (assuming that port 8888 is unused on my host computer) means I can do some testing by pointing my web client to http://localhost:8888/foswiki

When I exit the bash shell, which allows me to debug what is happening, everything is shutdown, and all changes are lost. If I make changes, I can commit them, but at this point, I prefer to make a new Dockerfile.

The interesting thing is that Docker seems to create an image tag for every command, so if I make add some RUN lines, or make changes, it doesn’t need to re-do steps that it has done before…. which sounds to me just like Rex, Puppet, Ansible etc – but more re-useable.

And so, I’m curious to see how hard it would be to push out Docker versioned configuration changesets over ssh to ‘anywhere’, with some kind of impotency via system ‘tags’.

 

PS, the docker image is available from https://index.docker.io/u/svendowideit/ubuntu-foswiki/ , and uses my debian packages, so you should install new extensions using apt-get install

Dual screen Chromebox as a remote terminal to SaaS Virtual Machines.

My work desktop runs almost nothing: all my applications are served by an in-house ‘cloud’ of servers and virtual servers that live downstairs.

The GUI applications – email, irc, skype, development environments all get persistently and transparently pushed to which-ever ‘display’ i’m using – on the sofa, I use my x61 tablet, at my desk, I was using a dual screen mac-mini that i detested, and now, I’m beginning to set up a ChromeBox series 5 to do the same thing.

(yes, in developer mode, and with the root file system made read-write)

There are some developer type setup-tweaks I’ve had to make – most notably to edit the /etc/X11/xorg.conf to increase the Virtual desktop size to accommodate the second screen.

Section "Screen"
    Identifier "DefaultScreen"
    Monitor    "DefaultMonitor"
    Device     "DefaultDevice"
    #ADDED by Sven for three headed chromeos
    SubSection "Display"
        Virtual 6000 2000
    EndSubSection
EndSection

and then I have a simple script to use xrandr and then ssh to X-Forward my 4 main xpra sessions to it.

chronos@localhost ~ $ more setup.sh #!/bin/sh
#http://cr-48.wikispaces.com/Disable+Power+Management
sudo initctl stop powerm
xrandr --output HDMI2 --right-of HDMI1 --rotate left ssh -Y sven@quiet ./attach_dev.sh

where attach_dev.sh looks like:

sven@quiet:~$ more attach_dev.sh 
#!/bin/sh

xpra attach :10 &
xpra attach :11 &
xpra attach :12 &
xpra attach :13 &

xfwm4

yup, I run a second X11 Window manager to allow me to re-position the applications that are X-Forwarded.

using xfwm4 means that I can roll up and down the chromeos browser windows – which are separate from the other X apps, and I can move the mouse to the other screen via a tiny hole in the chromeos windowmanager – there’s a gap down where the chromeos toolbar is.

this is really after only a few hours playing, so I’m sure there are many improvements that can be made.

 

Open source Private Cloud SaaS: VDI made simple

I just acquired some ‘new’ computers with 2 Dual Xeons, 32GB and 16GB RAM, and assorted disks.

My first thought was to use the 32GB one as my openstack testbed, and the other as a desktop, but soon after setting them both up with debian testing, I changed my mind.

Dell 690’s are much too noisy to be anywhere near me.

So I tossed my original desktop’s disk into the second one, and then put both of them downstairs, into the ‘server room’, and then set up xpra for rootless persistent X11 sessions. One session per app (browser, irc, email) and one session per project I work on.

Now, I have quiet up here…

Combining this with the rex Box work I was doing last month, and I’m going to have a really nice Software-as-a-Service setup,

for example:

  • rex SaaS:connect –name=”firefox”

would either connect to an existing xpra session by that name, or create a new vm, provision it, and connect to that.

but that code will have to wait, I’m working on the Foswiki 1.2.0 Wiki Applications wizard right now 🙂