Deploying play-with-docker.com on my machine
If you don't know what play-with-docker is, GO CHECK IT OUT NOW!
It is one of the Moby cool hacks winners! (The other one is FaaS by @alexellisuk - check my post about it here)
play-with-docker - PWD
So, what is Play With Docker?
Hacked by two Docker captains, Marcos Nils(@marcosnils) and Jonathan Leibiusky(@xetorthio), basically, Play with Docker is a Docker playground which you can run directly in your browser. With this, you have no excuse anymore to, well, not play with docker...
In the below screenshot I've deployed a local PWD, and in it you see a swarm of 5, (1 manager, 4 workers) running locally on my machine, with a stack deployed.
But I wanted mine too
If for whatever reason you want to deploy this on your hardware or VMs, you can (Give access to people via the browser on premises without AWS cost or whatnot), just follow along this quick and dirty post.
What I wanted to do is some Docker-inception. Have a PWD running in my local Swarm and in it a Swarm running LinuxKit :)
git clone https://github.com/franela/play-with-docker
cd play-with-docker/
docker pull franela/dind
sudo apt install golang-go
export GOPATH=$HOME/.go
go get -v -d -t ./...
docker-compose up
that's it!
Head over to http://localhost and you can start clicking "Add New Instance"
Let's try to deploy a stack onto it now:
Create an instance, you'll get a shell, then on it run:
docker swarm init --advertise-addr eth0
You'll get something like the below output:
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-31ovfkdk8wrna2y3igjzdfqhdm0e72ghksb7m441j1hxr1wtwh-81smoz5hu4mrdqzblrydjh86i \
10.0.0.7:2377
You can join other workers in if you'd like. To do so, click "Add New Instance" again and paste the command in the shell to join your workers.
Then, let's deploy our monitoring stack, which basically has portainer.io and manomarks/visualizer:
curl -o docker-compose-stack-monitoring.yml \
https://raw.githubusercontent.com/jmkhael/compose-samples/master/docker-compose-stack-monitoring.yml
docker stack deploy -c docker-compose-stack-monitoring.yml monitoring
docker stack ps monitoring
and here you'll see that the services are up and running!
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
qjqciab49qqa monitoring_viz.1 manomarks/visualizer:latest node5 Running Running 30 minutes ago
ske7lcocg8v6 monitoring_portainer.1 portainer/portainer:latest node5 Running Running 32 minutes ago
[node5] (local) root@10.0.0.7 ~
Sweet! It took me much more time to write this blog than to have play-for-docker deployed locally!
Bonus
Basically, I want to build the redis os from the keynote in PWD from the Moby cool hack!
Beyond this point, you are left alone in the Docker inception world...
Prepare LinuxKit
apk update
apk upgrade
apk add --no-cache go
export GOPATH=~/.go
go get -v -d -t ./...
git clone https://github.com/linuxkit/linuxkit
cd linuxkit
make
Snipped output below:
mkdir -p bin
tar cf - vendor src/initrd src/pad4 -C src/cmd/moby . | docker run --rm --net=none --log-driver=none -i linuxkit/go-compile:4513068d9a7e919e4ec42e2d7ee879ff5b95b7f5@sha256:bdfadbe3e4ec699ca45b67453662321ec270f2d1a1dbdbf09625776d3ebd68c5 --package github.com/linuxkit/linuxkit --ldflags "-X main.GitCommit=22514db912b9bec73e2a3c3ffd1611633c25b9db -X main.Version="0.0" " -o bin/moby > tmp_moby_bin.tar
Unable to find image 'linuxkit/go-compile:4513068d9a7e919e4ec42e2d7ee879ff5b95b7f5@sha256:bdfadbe3e4ec699ca45b67453662321ec270f2d1a1dbdbf09625776d3ebd68c5' locally
sha256:bdfadbe3e4ec699ca45b67453662321ec270f2d1a1dbdbf09625776d3ebd68c5: Pulling from linuxkit/go-compile
627beaf3eaaf: Pulling fs layer
...
49418cbb2668: Pull complete
Digest: sha256:bdfadbe3e4ec699ca45b67453662321ec270f2d1a1dbdbf09625776d3ebd68c5
Status: Downloaded newer image for linuxkit/go-compile@sha256:bdfadbe3e4ec699ca45b67453662321ec270f2d1a1dbdbf09625776d3ebd68c5
gofmt...
govet...
golint...
ineffassign...
go build...
...
gofmt...
govet...
golint...
ineffassign...
go build...
tar xf tmp_linuxkit_bin.tar > bin/linuxkit
rm tmp_linuxkit_bin.tar
touch bin/linuxkit
If all goes well, you'll have two binaries created under bin directory: moby and linuxkit. As per this pr:
- moby: just does the simple build case,
- linuxkit: is useful to push and run the constructed image
jmkhael@jmkhael-lx:~/workspace/linuxkit
$ ls bin/
linuxkit moby
I've had to patch the Makefile so it works in PWD (It worked without modifications on my local machine directly. as per the previous post)
I've cheated a bit. I've added-v /root/.go:/go
to the Docker run command for GO_COMPILE to have the dependencies.
Building the Redis OS sample project
So, let's make our OS:
make
./bin/moby build projects/demo/redis-os/redis-os
output of the command:
Extract kernel image: linuxkit/kernel:4.9.x
Add init containers:
Process init image: linuxkit/init:63eed9ca7a09d2ce4c0c5e7238ac005fa44f564b
Process init image: linuxkit/runc:b0fb122e10dbb7e4e45115177a61a3f8d68c19a9
Process init image: linuxkit/containerd:18eaf72f3f4f9a9f29ca1951f66df701f873060b
Add onboot containers:
Add service containers:
Create OCI config for linuxkit/dhcpcd:0d4012269cb142972fed8542fbdc3ff5a7b695cd
Create OCI config for redis:3.0.7-alpine
Add files:
Create outputs:
redis-os-bzImage redis-os-initrd.img redis-os-cmdline
Testing the Redis OS
For that, just execute linuxkit run
with the image. This will leverage qemu (on Linux) to run your OS in a VM! On Mac, all this given by moby/HyperKit. - note that as of the time of writing, Hyperkit only supports Mac.
"HyperKit is a toolkit for embedding hypervisor capabilities in your application. Supported backends are:
gcp
hyperkit [macOS]
qemu [linux]
vmware
packet"
Note that if you want to access the machine from outside, make sure to set the ip for the VM:
bin/linuxkit run redis-os
After a very short wait, you'll see a shell!
Let's abuse netcat to test redis-server from the image itself:
(printf "PING\r\n"; sleep 1) | nc localhost 6379
+PONG
(echo PING; sleep 1) | nc localhost 6379
+PONG
If you want to connect from the host machine,(where you built the os-redis image), you need to pass additional parameters for linuxkit/qemu runner (introduced by this pull request)
linuxkit run qemu -publish 6379:6379/tcp redis-os
You can then run on the host:
(printf "PING\r\n"; sleep 1) | nc localhost 6379
+PONG
(echo PING; sleep 1) | nc localhost 6379
+PONG
Enjoy your redis-os built by LinuxKit in PWD in Docker!
Diagnostics
If you need to diagnose why stuff are not working, netshoot docker image can save your day!
docker run -it --net host nicolaka/netshoot
and in it, run for instance tcpdump:
tcpdump -s 65535 tcp port 6379 -i any
and see the magic happens:
13:34:20.880434 IP localhost.38050 > localhost.6379: Flags [S], seq 3409053076, win 43690, options [mss 65495,sackOK,TS val 239977870 ecr 0,nop,wscale 7], length 0
13:34:20.880447 IP localhost.6379 > localhost.38050: Flags [S.], seq 195769136, ack 3409053077, win 43690, options [mss 65495,sackOK,TS val 239977870 ecr 239977870,nop,wscale 7], length 0
13:34:20.880458 IP localhost.38050 > localhost.6379: Flags [.], ack 1, win 342, options [nop,nop,TS val 239977870 ecr 239977870], length 0
13:34:20.880487 IP localhost.38050 > localhost.6379: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 239977870 ecr 239977870], length 5: RESP "PING"
13:34:20.880493 IP localhost.6379 > localhost.38050: Flags [.], ack 6, win 342, options [nop,nop,TS val 239977870 ecr 239977870], length 0
13:34:20.881104 IP localhost.6379 > localhost.38050: Flags [P.], seq 1:8, ack 6, win 342, options [nop,nop,TS val 239977870 ecr 239977870], length 7: RESP "PONG"
13:34:20.881112 IP localhost.38050 > localhost.6379: Flags [.], ack 8, win 342, options [nop,nop,TS val 239977870 ecr 239977870], length 0
13:34:21.880774 IP localhost.38050 > localhost.6379: Flags [F.], seq 6, ack 8, win 342, options [nop,nop,TS val 239978120 ecr 239977870], length 0
13:34:21.881299 IP localhost.6379 > localhost.38050: Flags [F.], seq 8, ack 7, win 342, options [nop,nop,TS val 239978121 ecr 239978120], length 0
13:34:21.881319 IP localhost.38050 > localhost.6379: Flags [.], ack 9, win 342, options [nop,nop,TS val 239978121 ecr 239978121], length 0
Cleaning up
When ready, and you want to stop this Redis OS, type halt
in the VM shell. Notice that it takes more time to shutdown than to boot!
You can also kill linuxkit ;)
You should also remove the PWD running containers...
Next
Now, how can I put SwarmKit to handle a hierarchical Swarms built in PWD built on Docker? My head hurt now... and I have a flight to catch!
Au revoir Austin! Keep Austin weird!