Simplify Your Technical Presentations with Docker Containers
I'm presenting at SPTechCon in Boston, demonstrating how to build an Office Add-in for Outlook with Angular 2, using a hands-on approach.
This week I’m presenting a session at the 2016 Boston installment of SPTechCon. At this show I’m doing two presentations, one of which shows how to build an Office Add-in for Outlook using Angular 2. As a developer, I find the most effective way to learn is to show someone what the goal or final result of a demo will be, then to go back and do it. A huge bonus is when I can walk away with the implementation & even replicate the demo quickly and easily myself. As a presenter, that’s not always easy, especially in this loosely connected cloud world.
Let’s take my session this week. An Office Add-in, in its most minimalist form, is an HTTPS secured website with an XML file that tells the Office client about the application & website. If I was attending my session here’s what I’d want:
- Lecture consisting of a few slides - really… just a few slides… because as we all know, power corrupts, and PowerPoint corrupts absolutely
- Demo of the final working solution so I can see what we’re trying to accomplish
- Live coding of the demo from scratch or an acceptable starting point
- Because live coding demos don’t always go to plan, if the presenter was running out of time, they need a way to quickly jump to the working solution so you can walk through the code
- Link to download the code so I can explore it later on my own time
- A way to easily spin up the demo in my environment
Sound like a plan? Me too… so let me explain to you how I’m doing it. It’s all in the magical beauty of Docker! The solution & presentation can be found in this repo: andrewconnell/pres-ng2-officeaddin.
What’s Docker? Is is the company behind one of the most widely adopted container specifications & ecosystems out there. So what’s a container? Go read my Docker & Containers 101 - What is Docker? post if you aren’t familiar with Docker & containers. But if you want to just get the gist:
Building a Containerized Presentation
I started out by figuring out what the best starting point would be. Starting with the Angular 2 Quickstart sample, I cloned it locally and then killed the .git folder. Then I did a bunch of manual tweaks as I needed a webserver for my demo. This left me with a good starting point: a project that included a Node.js webserver hosting a REST API behind HTTPS and serving up the sample Angular 2 Quickstart application. At that point, I committed the changes and tagged them.
Next, I created the Office Add-in using Angular 2 and made sure everything worked.
The last step in the process was containerizing the application. This is the easiest step. To do this add a new text file to the root of the project named Dockerfile.
1FROM node:5
2
3# create folders, group & user
4RUN mkdir -p /ac/demo /home/nodejs && \
5 groupadd -r nodejs && \
6 useradd -r -g nodejs -d /home/nodejs -s /sbin/nologin nodejs && \
7 chown -R nodejs:nodejs /home/nodejs
8
9# add npm & Typings configs, install all modules & TypeScript type defs
10WORKDIR /ac/demo
11COPY package.json typings.json tsconfig.json /ac/demo/
12RUN npm install --unsafe-perm=true
13
14# copy codebase for app into container
15RUN mkdir src
16COPY src /ac/demo/src
17RUN chown -R nodejs:nodejs /ac/demo
18USER nodejs
19
20# run app
21CMD npm startThe comments in the file explain what’s going on, but let me give you a little breakdown:
- The image is based on the official image by the Node.js foundation with Node.js v5 installed.
- Create two folders & a new group (nodejs) and user in that group (nodejs) and give the group ownership rights on the folders.
- Create a new folder
/ac/demooff the root of the system, copy the npmpackage.json, Typingstypings.json& TypeScript compiler configurationtsconfig.jsoninto the folder and then runnpm installto download all the npm packages (this also runs thetypings installstep which downloads the type definitions for TypeScript). - Create a new folder
srcand copy the contents of the current working folder’ssrcfolder into it. - Set the user to nodejs and if no startup command is provided, run
npm startwhen an instance of the image is started.
To build the image, run the following command (-t tells Docker what to name the image… the . on the end tells Docker where to find the Dockerfile.
1$ docker build -t pres-ng2-officeaddin .
What’s cool about this scenario is that now, I have, and you have access to, a single package that contains the entire demo application. For this scenario, a webserver is started on port 3433 over HTTPS.
Running the Working Demo in a Container
To get the site working, all you have to do is run the following command on your machine:
1$ docker run -it -p 443:3433 pres-ng2-officeaddin
This will spin up a new container based on that image, mapping port 443 on your host machine to port 3433 in the container. It will also start it in interactive mode (-i) with a TTY command prompt (-t… combined with the -i).
Here’s what it looks like when you run that without ever using docker before. Because containers are nested on top of other containers, be aware you might be about to download about 880MB of container layers. This first downloads all the layers for the container to run and then spins it up which you see about a minute into it. I then quit the container and do a few queries to see a list of all the images on my machine (docker images), the running containers (docker ps) and then all containers, even those run in the past who aren’t running (docker ps -a).
I then installed the add-in into Outlook using the URL of the add-in’s manifest file: https://localhost:443/app.xml & tada, it works!

Sample SPA app
Kill the container by hitting CTRL+C a few times in the command prompt / terminal window.
Jump Back to Starting Point for Live Demo
This is the tricky part… you want to not destroy the work you did for the working solution while quickly jumping back in time to start doing the live coding demo and, at the same time, giving yourself a failsafe to jump back to the working solution quickly in case you’re running out of time. This is where Docker sprinkled with a little Git saves the day.
I’m going to use the container you just ran as the core of my demo. Why? Because in a presentation room, I don’t want to go through the process of downloading all the npm packages my application uses (or, if I was using .NET, NuGet packages). Since the container already has all the npm packages in it’s node_modules folder & I’ve downloaded the container, I’ll be good to go. The same is true for the typings folder for my TypeScript type definitions.
But what about the source code for the app? That’s also in the container. Here’s where the trick comes in: When I start the container I’ll tell it to map the path to the source code in the container to a folder on the host laptop! Then all I have to do is get the local code back to the starting point. Git to the rescue!
1# get the list of tags for the repo
2$ git tag -l
3ng2-demo-tag
4
5# use the tag name to get the SHA of it's commit
6$ git rev-list -n 1 ng2-demo-start
7cb02f3b21038c6c304a93397afb79ebc09f99027
8
9# reset the workspace back to the way it was at that tag
10$ git reset [COMMIT-SHA] .
11
12# undo the changes to the files that existing then, but have been edited in the final version
13$ git checkout -- demos/ng2-outlook-minicrm/src/client/index.html
14$ git checkout -- demos/ng2-outlook-minicrm/src/client/app/main.ts
15$ git checkout -- demos/ng2-outlook-minicrm/src/client/app/app.component.ts
16
17# remove all stuff that was added after this comment
18$ git clean -fdx
At this point, the locally cloned repo for the application is back the way it was at the starting point. So now the trick is to get it running. To do this, I need to put my Docker hat back on and create a new file that will be used to spin up the container, but with some special parameters. This is a Docker Compose file:
1version: '2'
2services:
3 webapp:
4 # use the image that's clean, ready to do the live coding demo
5 image: andrewconnell/pres-ng2-officeaddin:ng2-demo-start
6 ports:
7 - "443:3433"
8 # map the current folder root on HOST => CONTAINER so container will
9 # use files from HOST as I code locally
10 # but leave node_modules & typings in the container so don't have to
11 # download them again
12 volumes:
13 - ./src:/ac/demo/src
14 # run TSC in watch mode & node in debug mode
15 command: npm run devThe comments explain most of what’s going on that you should understand from what I’ve already covered, but let me elaborate a bit.
- The highlighted lines say map the local folder
./srcto the folder in the container located at/ac/demo/src. So now, when the container runs like it did last time in the working solution, everything is the same except the code is not coming from the container, but instead from my laptop. As you saw, in the last step I just reset the code on my laptop to the starting point so I just bypassed the final working solution! - The last line says instead of using the
npm startas the startup command in the container as defined in theDockerfile, usenpm run dev. A quick peek atpackage.jsonshows that this does the same as thenpm startcommand except it also starts the TypeScript compiler in watch mode so any changes to TypeScript will get automatically transpiled to JavaScript.
Now to spin up the container with this configuration, just run:
1$docker-compose -f docker-compose.demo.yml up
Now hit the site at https://localhost and you get the starting point:

Docker for presentations
At this point, I can start doing the live coding demo.
Quickly Jump Back to Working Demo
What if you need to bailout and show the working version again? Again, Docker & git play a key role here.
First, reset the code to the final working version in the cloned repo so you can explain it to your attendees:
1$ git reset --hard HEAD
Now that the code is set, kill the old running container and start it up using the original docker run command you used above. This time, it uses the working app in the container, not your mapped folder one.
Cleanup
How do you remove this stuff you just downloaded to your machine? You the container you ran is still there, just not in a running state. Then there’s the 800MB collection of layers that makeup the image. Here’s what you do:
- remove the container using
docker rm [container ID] - remove the image using
docker rmi [image ID]
Conclusion
If you’re new to Docker, this might be a bit much to bite off for a session. However if you’ve used Docker in any way previously, you’ll agree that there’s very little I had to do here to set this up as I only created two files (Dockerfile & docker-compose.demo.yml) and wrote down a few commands in git. All of this is easily repeatable in other demos.
Maybe this works for you as a presenter, maybe not… it works for me and I wanted to share it to give you a good use case of containers in the real world.
If you’re at the SPTechCon conference this week and wonder this is all fine and good, but I don’t do Node.js and I don’t want to work in Linux (because today, production containers are a Linux only thing). Well for those of you in the .NET & Windows world, containers are coming to you too! Docker supports Windows containers, something that’s coming in Windows Server 2016 (already working in the latest tech preview) so you can use classic .NET applications in containers. Or, you can leverage .NET Core / ASP.NET Core to build .NET applications that run on any platform.
Oh wait, I almost forgot…
There were two more steps I mentioned above in my presentation goal. One was a link to where you can get the presentation. Well for this one, go here: https://github.com/andrewconnell/pres-ng2-officeaddin.
The other was where you can get the working solution. Well you can build it yourself from the GitHub repo in the previous paragraph, or you can download it to your machine:
1$ docker pull andrewconnell/pres-ng2-officeaddin
or just download & run it in one command:
1$ docker run -it -p 433:3433 andrewconnell/pres-ng2-officeaddin:ng2-demo-start