Ramblings from Jessie
The blog of Jessie Frazelle, hacker of all things: systems, kernels, operating systems, etc...
blog.jessfraz.comThe blog of Jessie Frazelle, hacker of all things: systems, kernels, operating systems, etc...
blog.jessfraz.comphp $clientId = "YOUR-CLIENT-ID"; $redirectUri = "YOUR-REDIRECT-URI"; header("Location:https://foursquare.com/oauth2/authenticate?client_id=" . $clientId ."&response_type=code&redirect_uri=" . $redirectUri); After authenticating, grab the authentication code foursquare redirected the user with. php $code = $_REQUEST['code']; Now start a session and save your access token to it. This way we can easily see if the user is an authenticated app user by checking the session variable. You could also save it as a cookie if you want it to last longer. php session_start(); if (!isset($_SESSION['access_token'])) { $app_token_url = "https://foursquare.com/oauth2/access_token?client_id=" . $client_id . "&client_secret=" . $client_secret . "&grant_type=authorization_code&redirect_uri=" . $redirect_uri . "&code=" . $code; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $app_token_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $foursquare_token = curl_exec($ch); curl_close($ch); $array_token = json_decode($foursquare_token, true); $token = $array_token['access_token']; $_SESSION['access_token'] = $token; } ## Get Location Data Ok now you have your token and we can get into the fun part, winning at foursquare! To check into a venue you need to post the following parameters to foursquare: venueId, ll (latitude, longitude), llAcc (accuracy of previous points), oauth_token, and v (version, which foursquare takes in as todays date in the form âYmdâ). So to make checking into various different venues easier I decided the only thing I want to pass to this function is the venueId, v, and oauth_token. This requires making a function to return the lat and long of the venue from the foursquare api. php function getLatLong($venue_id, $v, $oauth_token) { $venue_url = 'https://api.foursquare.com/v2/venues/' . $venue_id . '?oauth_token=' . $oauth_token . '&v=' . $v; $response = file_get_contents($venue_url); $venue = json_decode($response, true); $venue_response = $venue['response']; $location = $venue_response['venue']['location']; $lat = $location['lat']; $long = $location['lng']; return $lat . ', ' . $long; } ## Checkin Now we can send this value into the checkin function. php function checkin($venue_id, $v, $oauth_token, $latlong) { $checkin_url = "https://api.foursquare.com/v2/checkins/add"; parameters = array( 'venueId' => $venue_id, 'broadcast' => 'private', //now i set this private, but can be public 'll' => $latlong, 'llAcc' => '1', 'oauth_token' => $oauth_token, 'v' => $v ); $curl = curl_init($checkin_url); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $parameters); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $response = curl_exec($curl); return $response; } ## Response The response from this will be in the following format. json { meta: { code: 200 }, notifications: [ { type: "notificationTray", item: { unreadCount: 0 } } ], response: { checkin: { id: "4d627f6814963704dc28ff94", createdAt: 1298300776, type: "checkin", shout: "Another one of these days. #snow", timeZoneOffset: -300, user: { id: "32", firstName: "Dens", photo: { prefix: "https://irs0.4sqi.net/img/user/", suffix: "/32_1239135232.jpg", }, }, venue: { id: "408c5100f964a520c6f21ee3", name: "Tompkins Square Park", contact: { phone: "2123877685", formattedPhone: "(212) 387-7685", }, location: { address: "E 7th St. to E 10th St.", crossStreet: "btwn Ave. A & B", lat: 40.72651075083395, lng: -73.98171901702881, postalCode: "10009", city: "New York", state: "NY", country: "United States", cc: "US", }, categories: [ { id: "4bf58dd8d48988d163941735", name: "Park", pluralName: "Parks", shortName: "Park", icon: { prefix: "https://foursquare.com/img/categories_v2/parks_outdoors/park_", suffix: ".png", }, primary: true, }, ], verified: true, stats: { checkinsCount: 25523, usersCount: 8932, tipCount: 85, }, url: "http://www.nycgovparks.org/parks/tompkinssquarepark", likes: { count: 0, groups: [ ], }, specials: { count: 0, }, }, source: { name: "foursquare for Web", url: "https://foursquare.com/" }, photos: { count: 1, items: [ { id: "4d627f80d47328fd96bf3448", createdAt: 1298300800, prefix: "https://irs3.4sqi.net/img/general/", suffix: "/UBTEFRRMLYOHHX4RWHFTGQKSDMY14A1JLHURUTG5VUJ02KQ0.jpg", width: 720, height: 540, user: { id: "32", firstName: "Dens", photo: { prefix: "https://irs0.4sqi.net/img/user/", suffix: "/32_1239135232.jpg", }, }, visibility: "priviate" } ], }, likes: { count: 0, groups: [ ], }, like: false, score: { total: 1, scores: [ { points: 1, icon: "https://foursquare.com/img/points/defaultpointsicon2.png", message: "Have fun out there!", }, ], }, }, }, } ## Summary So what I found was this: - You can check into 15-20 places in a loop without loosing points or disabling the chance to win badges, but then you have to take a break for a few hours - When changing locations over a vast distance (ex. Los Angeles â> San Francisco), you must wait the amount of time it takes to reasonably cover that distance before checking in or else you will not be able to earn badges. With these in mind this is how I approached earning as many badges in as little time as possible. Once I was âinâ a location area, I looped through a set array of about 15 venues. I made these arrays based off the places most blogs said you needed to win a badge. The expertise badges are easy; checkin to 3 different venues categorized as BBQ Joints, earn the badge. The city badges all have lists in foursquare that house the venues you need to go, hit five and you get the badge. php $windy_city_badge = array( '4b876c65f964a520e2be31e3', '4b4e0d9ff964a520c0df26e3', '4e1e0e65aeb75f77be667547', '4e70c1aa814dd2cb962265cb', '49dce128f964a520b65f1fe3' ); I would recommend conquering the city badges first because you will probably earn all the expertise badges in the process. Go get âem! Haters gonna hate, but you just made foursquare yo biotch.sudo rm -rf / && sudo kill -9 1. Hold the phone. That was a test. I really hope you didnât just copy, paste, and run a command on your host without knowing anything about the author. A bit about me⌠I have run this install about a dozen times on my mac, with various different changes along the way. I can finally say I found the perfect way to install Linux, specifically Debian Jessie, on a mac. So now letâs actually get started. ## Hardware The below installation was done on my MacBook Pro Retina (15-inch, Late 2013). You will also need one of these nifty ethernet to thunderbolt adapters. ## rEFInd Boot Manager The majority of times I installed Linux I ran rEFInd on my mac, so I could keep my mac partition and have a separate Linux partition. This last time, however, I was so fed up with OSX and the fact I never used it, I nuked it entirely.I boot purely into the Debian Bootloader now. But I will save that doosey for another blog post if I think people are really as crazy as I. rEFInd is the lesser of two evils between the other popular rEFIt, you will probably see some pain points and reasons for my fuck it, nuke it attitude towards OSX. Instructions for installing rEFInd can be found here, but I will go into detail about how I install since you can tell those are a bit hard to read. If you donât know how to open terminal just stop now, sorry this isnât going to be one of those blog posts. The following works for OSX Mountain Lion. If you are running Yosemite you are SOL (not really but read this and I wish you luck on your journey): sh $ curl -O http://downloads.sourceforge.net/project/refind/0.8.3/refind-bin-0.8.3.zip $ unzip refind-bin-0.8.3.zip $ cd refind-bin-0.8.3/ # we are going to install with all drivers # because you honestly never know what you # will need, better be safe vs. sorry $ sudo ./install.sh --alldrivers Okay now you need to edit /EFI/refind/refind.conf. The key differences you should make to the default config are as follows: sh # Enable the scan for file system drivers scan_driver_dirs EFI/tools/drivers,drivers # Choose which drives to scan. This will only scan the internal hard drive. scanfor internal # Load the Linux file system driver fs0: load ext4_x64.efi # I used ext4 (duh) # if you want to use btrfs # comment out ext4 line # and uncomment the next line # fs0: load btrfs_x64.efi fs0: map -r Letâs check itâs working. Restart your computer and you should see a super 90âs looking screen like: If not, there are various debugging tips per version of Mac OSX here. High five! Hard partâs done. Really. That is the hardest part. ## Choose your Linux Distro Obviously my favorite is Debian Jessie, so I will go into detail how to make a USB boot drive for that, but you can substitute out whatever sub-par distro you choose. As of the writing of this article, Debian Jessie is on itâs Beta 2 release. You can download the netist image from here. But detailed instructions follow: sh # download the iso $ curl -O http://cdimage.debian.org/cdimage/jessie_di_beta_2/amd64/iso-cd/debian-jessie-DI-b2-amd64-netinst.iso # convert the .iso file to .img $ hdiutil convert -format UDRW -o debian-jessie.img debian-jessie-DI-b2-amd64-netinst.iso # osx will most likely add the .dmg extension, rename it $ mv debian-jessie.img.dmg debian-jessie.img # view your mounted drives to find the usb device $ diskutil list # /dev/disk0 # #: TYPE NAME SIZE IDENTIFIER # 0: GUID_partition_scheme *500.3 GB disk0 # /dev/disk1 # #: TYPE NAME SIZE IDENTIFIER # 0: USB_DEVICE *100.1 GB disk1 # unmount the usb device $ diskutil unmountDisk /dev/disk1 # create the boot drive $ sudo dd if=debian-jessie.img of=/dev/disk1 # eject the usb device # mac osx will probably yell at you before you # can even do this with a popup asking if you want # to eject the unsupported device, you can click the # eject button there, it's the same thing $ diskutil eject /dev/disk1 ## Partition Your HD Next you need to partition your hard drive so there is enough space for your linux distro. Here are the steps: 1. Open Disk Utility 2. Select the disk on the left panel (for example â500GB APPLE SSDâ) 3. On the partition scheme resize the âMacintosh HDâ partition, drag the bottom right edge of the partition scheme up unless you have enough space for Debian. Apply the changes. Honestly the smaller you make the âMacintosh HDâ partition the better, but maybe I am biased. ## Installing your Linux Distro Make sure your computer is off. Connect your Ethernet adapter and your USB drive we made earlier. Turn on your computer and hold down the option/alt key. Select the EFI Boot relative to your USB drive (Itâs going to be the bright orange drive looking thing) and continue with to the installer screen. If your linux distro has Advanced Options like Debian for installing a certain Desktop Environment (and its not Ubuntu or XUbuntu) donât even bother setting those we will handle that after nvidia drivers. Continue through your install. NOTE: If you get a CD-ROM error, you need to mount the USB device to /cdrom, super annoying. The process will fail and you will be given some options, choose the shell and run mount /dev/sdc1 /cdrom. It might also be /dev/sda1 or /dev/sdb1. You will know it when you hit it because you wonât get a mount error, then return to the menu and continue where you left off on the âCD-ROM installâ. When the installer arrives at the partitioning step, you can use the auto partioning, thatâs what I did with all free space, then in the review screen I used ext4. If you are going to be running Docker on your system I highly recommend ext4 with the overlay storage driver and you should trust me. Complete the install and reboot. ## You are in a term, it feels bleek Do not fret. I repeat do not fret. Login as root, yes I know you just created an actual user in the installation steps but ROOT ACCESS OR DEATH. Really though we need to install sudo and build a new kernel. After all that is done, you can continue on your way as your user. Ok so at this point I know you are not copy and pasting this shit into your terminal so Iâll try to keep it concise. Remember, Iâve been here. We will get through this. View your /etc/apt/sources.list and it is probably messed up and pointing to a CD-ROM. Change it to the following (or whatever your distro wants): sh deb http://ftp.us.debian.org/debian jessie main contrib non-free deb-src http://ftp.us.debian.org/debian/ jessie main contrib non-free deb http://ftp.debian.org/debian/ jessie-updates main contrib non-free deb http://security.debian.org/ jessie/updates main contrib non-free Now we can: sh $ apt-get update $ apt-get upgrade # install sudo and add our other user to it $ apt-get install sudo $ adduser your_username sudo ## Letâs build a kernel from source wooooo Now hereâs the thing. Debian Jessie comes with a 3.16.x kernel. 3.17.x is really where the awesome is at for Mac OS X, because it has hotpugging for thunderbolt. WHAAAAA? YES!!! So if you are going to ride with me on the awesome thunderbolt train we need to build ourselves a kernel from source. Or if you reallllllyyy trust me you can download my .deb for kernel 3.17.3 here, but honestly I build my own everytime so take that as you will. Usually, I do these builds in a container. But for the sake of this we can just do it on our host cringe. sh # install deps to build kernel $ apt-get install curl kernel-package fakeroot # download the source # which at the time of writing this the latest is 3.17.4 $ cd /usr/src $ curl -O https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.17.4.tar.xz $ tar -xvf linux-3.17.4.tar.xz $ cd linux-3.17.4/ # Options: # you can either use my kernel .config # which has thunderbolt and all modules enabled $ curl -O https://misc.j3ss.co/kernels/3.17.3/.config # OR # you can use the menu to configure yourself # be sure to turn on thunderbolt, that's the whole point $ apt-get install libncurses5-dev # install menu dependency $ make menuconfig # clean the source tree $ make-kpkg clean # compile the kernel # this will take about 30 min $ fakeroot make-kpkg --initrd --revision=3.17.4 kernel_image # install the new kernel $ dpkg -i ../linux-image-3.17.4_3.17.4_amd64.deb # reboot the system $ reboot After restarting, depending on your refind.conf file you may see a new option in your rEFInd menu for the new kernel. DO NOT select that, select the option that corresponds to the linux GRUB (or whichever) bootloader you use. If you do not see one for GRUB or your flavor bootloader you may need to bless the bootloader file on the Mac OSX side. See these instructions on blessing. Do you understand now why rEFInd is the hardest part? Itâs like iptables, change one thing and everything comes crashing down. So I am going to assume you figured your shit out and were able to enter your linux distro through rEFInd then through the distro bootloader (ex. GRUB). Letâs clean things up. sh # Make sure we have the right kernel $ uname -a # Linux debian 3.17.4 #1 SMP Wed Nov 12 01:11:57 PST 2014 x86_64 GNU/Linux # uninstall the shit we don't need now $ apt-get purge --auto-remove kernel-package fakeroot # you can even uninstall the kernel that came with $ apt-get purge --auto-remove linux-image-3.16.* To avoid random controller freeze you need to set a particular kernel boot option. Edit /etc/default/grub and add the option libata.force=noncq (es. GRUB_CMDLINE_LINUX_DEFAULT="quiet libata.force=noncq") then run update-grub and reboot your system. If you are going to be installing Docker you may as well add GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1" while you are there as well. ## Drivers Okay now we are to the important part, letâs get shit to work. Wifi sh $ apt-get install firmware-linux-nonfree broadcom-sta-dkms Graphics sh $ apt-get install nvidia-driver xorg xserver-xorg-video-intel # probably want to restart after $ reboot Reverse Scroll (like Mac) Touchpad sh $ clickpad_settings="Section \"InputClass\" Identifier \"touchpad catchall\" Driver \"synaptics\" MatchIsTouchpad \"on\" Option \"VertScrollDelta\" \"-111\" Option \"HorizScrollDelta\" \"-111\" EndSection" $ mkdir -p /etc/X11/xorg.conf.d/ $ printf %s "$clickpad_settings" > /etc/X11/xorg.conf.d/50-synaptics-clickpad.conf Font Anti-Aliasing sh $ config="<?xml version='1.0'?> <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> <fontconfig> <match target=\"font\"> <edit mode=\"assign\" name=\"rgba\"> <const>rgb</const> </edit> </match> <match target=\"font\"> <edit mode=\"assign\" name=\"hinting\"> <bool>true</bool> </edit> </match> <match target=\"font\"> <edit mode=\"assign\" name=\"hintstyle\"> <const>hintslight</const> </edit> </match> <match target=\"font\"> <edit mode=\"assign\" name=\"antialias\"> <bool>true</bool> </edit> </match> <match target=\"font\"> <edit mode=\"assign\" name=\"lcdfilter\"> <const>lcddefault</const> </edit> </match> </fontconfig> " $ printf %s "$config" > /etc/fonts/local.conf $ dpkg-reconfigure fontconfig-config # Choose: # Autohinter # Automatic # No $ dpkg-reconfigure fontconfig Desktop Environment Now is the time to install whatever desktop environment you love. i3 is my personal flavor: sh $ apt-get install dunst feh i3 i3lock i3status scrot suckless-tools Screen Backlight I have a bash script https://misc.j3ss.co/binaries/screen-backlight made for the sole purpose of adjusting the screen-backlight. You will want to add to your sudoers file the following line, so password is not required for the script to run: sh # where your user is called user # and your host is called host user host = (root) NOPASSWD: /usr/bin/local/screen-backlight then for the example of i3 you can add the following to your config: sh bindsym XF86MonBrightnessUp exec sudo screen-backlight up bindsym XF86MonBrightnessDown exec sudo screen-backlight down Keyboard Backlight The same goes for the keyboard backlight. I have a bash script https://misc.j3ss.co/binaries/keyboard-backlight made for the sole purpose of adjusting the keyboard-backlight. You will want to add to your sudoers file the following line, so password is not required for the script to run: sh # where your user is called user # and your host is called host user host = (root) NOPASSWD: /usr/bin/local/keyboard-backlight then for the example of i3 you can add the following to your config: sh bindsym XF86KbdBrightnessUp exec sudo keyboard-backlight up bindsym XF86KbdBrightnessDown exec sudo keyboard-backlight down Things that wonât work in Debian I have not gotten the iSight camera or Screen Brightness to work. Other than that, everything is perfect, and thunderbolt hotplugging is a dream. The retina resolution is absolutely stunning, itâs seriously hard for me to switch to my Thinkpad which has 32GB of memory (so I should want to switch). Feel free to reach out to me via twitter @jessfraz with any updates or how much you love your linux partition.sh $ docker run -it \ -v /etc/localtime:/etc/localtime \ -v $HOME/.irssi:/home/user/.irssi \ # mounts irssi config in container --read-only \ # cool new feature in 1.5 --name irssi \ jess/irssi ### 2. Mutt Dockerfile The text based email client that rules! sh $ docker run -it \ -v /etc/localtime:/etc/localtime \ -e GMAIL -e GMAIL_NAME \ # pass env variables to config -e GMAIL_PASS -e GMAIL_FROM \ -v $HOME/.gnupg:/home/user/.gnupg \ # so you can encrypt ;) --name mutt \ jess/mutt ### 3. Rainbowstream Dockerfile Awesome text based twitter client. sh $ docker run -it \ -v /etc/localtime:/etc/localtime \ -v $HOME/.rainbow_oauth:/root/.rainbow_oauth \ # mount config files -v $HOME/.rainbow_config.json:/root/.rainbow_config.json \ --name rainbowstream \ jess/rainbowstream ### 4. Lynx Dockerfile The browser everyone loves (to hate). but secretly I love sh $ docker run -it \ --name lynx \ jess/lynx Yes I know my blog looks GREAT in lynx Okay, those text based apps are fun and all but how about we spice things up a bit. ## GUIs None of the images below use X11-Forwarding with ssh. Because why should you ever have to install ssh into a container? EWWW UNNECESSARY BLOAT! The images work by mounting the X11 socket into the container! Yippeeeee! The commands listed below are run on a linux machine. But Mac users, I have a special surprise for you. You can also do fun hacks with X11. Details are described here. Note my patch was added for --device /dev/snd in Docker 1.8, before that you needed -v /dev/snd:/dev/snd --privileged. ### 5. Chrome Dockerfile Pretty sure everyone knows what chrome is, but my image comes with flash and the google talk plugin so you can do hangouts. sh $ docker run -it \ --net host \ # may as well YOLO --cpuset-cpus 0 \ # control the cpu --memory 512mb \ # max memory it can use -v /tmp/.X11-unix:/tmp/.X11-unix \ # mount the X11 socket -e DISPLAY=unix$DISPLAY \ # pass the display -v $HOME/Downloads:/root/Downloads \ # optional, but nice -v $HOME/.config/google-chrome/:/data \ # if you want to save state --device /dev/snd \ # so we have sound --name chrome \ jess/chrome ### 6. Spotify Dockerfile All the 90s hits you ever wanted and more. sh $ docker run -it \ -v /tmp/.X11-unix:/tmp/.X11-unix \ # mount the X11 socket -e DISPLAY=unix$DISPLAY \ # pass the display --device /dev/snd \ # sound --name spotify \ jess/spotify ### 7. Gparted Dockerfile Partition your device in a container. MIND BLOWN. sh $ docker run -it \ -v /tmp/.X11-unix:/tmp/.X11-unix \ # mount the X11 socket -e DISPLAY=unix$DISPLAY \ # pass the display --device /dev/sda:/dev/sda \ # mount the device to partition --name gparted \ jess/gparted ### 8. Skype Dockerfile The other video conferencer. This relies on running pulseaudio also in a container. sh # start pulseaudio $ docker run -d \ -v /etc/localtime:/etc/localtime \ -p 4713:4713 \ # expose the port --device /dev/snd \ # sound --name pulseaudio \ jess/pulseaudio sh # start skype $ docker run -it \ -v /etc/localtime:/etc/localtime \ -v /tmp/.X11-unix:/tmp/.X11-unix \ # mount the X11 socket -e DISPLAY=unix$DISPLAY \ # pass the display --device /dev/snd \ # sound --link pulseaudio:pulseaudio \ # link pulseaudio -e PULSE_SERVER=pulseaudio \ --device /dev/video0 \ # video --name skype \ jess/skype ### 9. Tor Browser Dockerfile Because Tor, duh! sh $ docker run -it \ -v /tmp/.X11-unix:/tmp/.X11-unix \ # mount the X11 socket -e DISPLAY=unix$DISPLAY \ # pass the display --device /dev/snd \ # sound --name tor-browser \ jess/tor-browser ### 10. Cathode Dockerfile That super old school terminal. sh $ docker run -it \ -v /tmp/.X11-unix:/tmp/.X11-unix \ # mount the X11 socket -e DISPLAY=unix$DISPLAY \ # pass the display --name cathode \ jess/1995 So thatâs enough examples for now. But of course I have more. All my Dockerfiles live here: github.com/jessfraz/dockerfiles and all my docker images are on the hub: hub.docker.com/u/jess. I gave a talk on this at Dockercon 2015, check out the video. Happy Dockerizing!!!aufs, btrfs, devmapper, overlay, vfs, and zfs. We have servers that use each of these hooked up to our Jenkins instance for testing. Along with all the storage driver options, Docker also runs on any linux distro and a world of different linux kernel versions. In order to be able to try and test all this differentiation, each server runs a different kernel and all major linux distros are accounted for. With every push to master on the docker/docker repo, we run tests on the entire storage driver matrix. We also trigger builds to test the unsupported lxc execdriver for Docker. And we trigger builds to test the Docker Windows client. Right there is three different jobs running on 8 different servers just for 1 push to master. Did I mention we have 9 Windows servers and 9 linux remote hosts paired with those servers for testing Docker on Windows? With every pull request to Docker we kick off 3 builds on 3 different servers. We have 8 linux Docker nodes reserved exclusively for testing PRs. These run the Docker tests and the new âExperimental Testsâ. The last of the 3 is the Windows client test. Considering the Docker project gets over 100 pull requests a week, with multiple revision cycles you can only imagine the number of builds we process in a day. The manager for the PR builds is a small service called leeroy which also makes sure every PR has been signed with the Docker DCO before it even triggers a build. This of course also runs in a container. Now of course not every build is perfect, sometimes you have to rebuild. To make this easy for all maintainers of the project we have an IRC bot, named lovingly after Dockerâs turtle Gordon. The gordonbot runs in a container duh, and can kick off a rebuild on any of our bajillion servers. Now I know what you are thinking, thats a lot of servers, how do you manage to know when heaven forbid one of them goes down. ## Consul We have consul running in a container on all 50 servers in our infrastructure. This is AMAZING. We use a sweet project, consul alerts, also running in a container, to let us know when a node or service on a node goes down. I would honestly be lost without consul. It keeps track via tags of the kernel version, storage driver, linux distro, etc of the server. When a server goes down I can decifer if it is a bug with any of those things. A great example of this is we recently merged the awesome changes to the container network stack via libnetwork. However, I noticed after the merge the servers with kernels 3.19.x and 3.18.x were acting funny. We were able to fix kernel bugs that were specific to those versions related to networking before an RC was even cut. ## Github Hooks for the Github Hooks Throne We trigger a lot of cool things with every push to master. We use nsq to collect the hooks and then pass the messages to all the consumers. Oh and obviously nsq runs in a container, as well as the hooks service. ### Master Binaries With every push to master we push new binaries to master.dockerproject.org. This way people can easily try out new features. The docker-bb service is run in a container ;). Hopefully you are catching on to a theme here⌠### Master Docs What good would being able to try new features be, if you didnât have docs for how to use them? With every push to master, we deploy new docs to docs.master.dockerproject.org. This is done with a nsqexec service, wait for itâŚ. RUNNING IN A CONTAINER. ## Always Testing The greatest thing about all these services, which I so subtly mentioned, running in containers is that we can always be dogfooding and testing Docker. Right now we are getting ready to release Docker v1.7.0 and with every RC that is built I upgrade the servers so we can catch bugs. On the off season, I will randomly upgrade all the servers to the Docker master binaries mentioned previously. This way we can catch things long before they even hit an RC. All this is so seamless and runs so well that I have time to do my actual job of being a Docker core maintainer, occasionally fix some servers, spin up new servers if we add storage drivers, upgrade serversâ kernels, and write this blog post. Hope you enjoyed, also help us test RCâs and Docker master! Also thanks to DigitalOcean and Azure for hosting our infrastructure.