Skip to content


Repository files navigation

Docker Immutable Workstation

The concept of an immutable server for production deployment is now fully mainstream, but the same concepts underpinning servers is less applied to the workstations on which the developers work.

We have a tendency to start with a nice clean laptop, a Mac if we are lucky, and slowly but surely stuff creeps on, dependencies we did not know about appear and we stop trusting the platform we stand on.

So I have used Docker to make my own immutable workstation. It means that I get exactly the same stack running on my banged-about-on-commute laptop, my wife's nice big screen iMac and even on my client's Windows box, that I had to use for client's policy reasons. So wherever I was, I was using the same config of emacs -using it on a windows machine or a mac or a Linux host, it was the same emacs, and the same nice set of tools like grep. And it was running XWindows in those places too.

Secondly, I get the ratchet effect of continuously improving security - I can always improve something on the install, and just rerun docker build and I have permanently remembered to fix that security hole wherever I build my workstation.

I have 'improved' the approach (this is many years old now), so that I run a complete desktop on docker, and VNC into it, from my local machine. THis simplifies things like looking at pdfs or html files built on the machine plus simplifies things like keeping my local machine updated - I can live without almost any 'new stuff' on the local laptop.

So, anything that changes I keep in source control (here in this repo) and my secrets are all stored on a USB key that I carry with me and plugin to the host - so my GitHub ssh key is on a USB stick, that when I plug it in, .

Documentation can be found at

`immutableworkstation` can create docker images from config, and
launch those images so that as a developer you can work inside the
container, but using X-applications on the host laptop.

So you can define your workstation in code, but take it with you
from laptop to home to work.

Using X Windows

The essential parts of this approach are hard to dig out from Google searches, but I hope this makes them clearer - the below code will produce a working local docker instance, ssh into it and display an app from docker but on the host desktop.

We build a X11 capable docker image :

FROM ubuntu:18.04

RUN apt-get update && \
    apt-get install -y openssh-server \

RUN mkdir -p /var/run/sshd                     
RUN echo 'root:root' | chpasswd 
RUN sed -ri 's/^#PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config
RUN sed -ri 's/^#AllowTcpForwarding\s+.*/AllowTcpForwarding yes/g' /etc/ssh/sshd_config
RUN sed -ri 's/^#X11Forwarding\s+.*/X11Forwarding yes/g' /etc/ssh/sshd_config
RUN sed -ri 's/^#X11UseLocalhost\s+.*/X11UseLocalhost no/g' /etc/ssh/sshd_config

CMD ["/usr/sbin/sshd", "-D"]

We then build the above image:

# sudo docker build -t devbox:latest .

Now run it, listening on the localhost port of 2222, which is then mapped to 22 on the container:

# docker run -d  --name devbox-live -v /data/projects:/projects -p 2222:22 devbox:latest

we should now have a running container listening on port 2222

So we can ssh tunnel into the container using:

# ssh -X root@localhost -p 2222

There may be some faffing with .XAuthority files. Ignore that for now. But we should then be able to run :

# xeyes 

on the container, and it will appear on the laptop we are running on.

#TODO: screenshot

Using Sound

There is a developer who (I think) works for Docker and has a list of YouTube videos showing how to do things like run Skype on Docker. She developed a snd device parameter for docker run, which seems to work fine. I don't do much with it but should expand on it.

Using Secrets

/etc/fstab on host machine:

# /etc/fstab: static file system information.
UUID=ed74f120-1736-4f59-8752-06098a635c16 /home/pbrian/secrets/usb   ext4  user,rw,auto,nofail  0   0   

I used `sudo blkid` to get the UUID for that specific USB key.

It is then automounted to my home dir, where docker will make it
visible in the docker instance, and I get to use the ssh keys on
the USB stick to authenticate to, for example, github.

Using Dropbox

I have some files I keep on private GitHub repos, but for most documents (things like Bank statements) it seems easier to just store them on Dropbox. I merely have my Dropbox folder on my home dir, and mount it into Docker. It seems to work with no horrible clashes so I will keep it. At some point it seems sensible to migrate to having the Dropbox client actually running on the docker instance.

Its not terribly secure, but it seems good enough.

Why is this good?

Quite simply, I can easily control the dev environment, rebuild it at will, and run programs "on my laptop" when they are not installed or configured on the laptop.

In fact I think the best part of this is configuration for my whole dev machine is stored on GitHub, and can be re-created anywhere easily.

With the volume mounted, I can then use emacs / console running inside a container, and adjust files that are stored on my local laptop.

I then have a consistent dev environment

Also, I can easily rebuild it

Also I can spin up a microservice on laptop that also points at the same volume, and it will thus be using the code I just developed

This works even if I change underlying OS - which is good for wandering contractors like me.


#TODO:: allow two workstations on same host, so I can play / verify changes
#TODO:: get dropbox installed on docker instance

Building on Mac OS

You will need a XServer running on the Mac. I recommend using XQuartz - this will need to be installed and running before starting the ssh -X process so the ssh session can connect to something

Roadmap See Roadmap