Building a slack bot with botkit node and docker


Recently I have needed to dig deeper into node and docker.  I decided to make a slack bot (easy to do) so that the problem being solved didn’t require additional learning (making bots is fun).  I ended up finding botkit (a node based slack integration) and set off building something simple with the intent of hosting it in Docker.  This took me down an interesting path as I tried to fit all these things together to make something small but useful.

I ended up creating a FitBot that gives you a random exercise to do every hour.  My bot got way more complex (code wise) than is needed for this discussion.  I figured we might instead build a simple weather bot using the weather underground.  But first we have to get the plumbing working.

What will you learn from this post?

  1. How to install node on a mac (will point to windows how-too)
  2. How to use the basics of NPM for node package management
  3. How to write some simple node (javascript) and test it locally
  4. How to create a Slack bot
  5. How to push all of this into a docker container
  6. How to push your docker container over to a bot host
  7. Build a weather bot
  8. What is chatops

This post is “just enough” to scratch the surface.  It is intended to get you touching all of these concepts just enough that they are no longer scary unknown topics.  There are many pluralsight videos that take you deep into each of these technologies.  Let’s get started.

Node stuff

I was most interested to get my hands dirty with node which ultimately led me down this path.  This then led me to finding a slack SDK for node.  Node is great.  Many web devs naturally know javascript.  Taking your client side javascript skills to the server makes a lot of sense.  Let’s start by getting node up and running.

Node pre-requisites for mac

As I started my journey for getting node up and running I bumped over a few articles.  I ultimately found that I needed to install XCode and HomeBrew which would then allow me to get node up and running quickly.

XCode allows you to build mac and ios apps.  It also provides you with all the tools you need to compile software for use on a mac.  You can find XCode in the apple store.

HomeBrew is the “package manager that mac forgot”.  It makes installing various other bits of software on your mac very easy.  For installing node you can simple type out…

brew install node

…and you have node running!  But first we need to get HomeBrew installed and running.  To get HomeBrew installed just copy and paste the line below in a terminal window:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com
/Homebrew/install/master/install)"

Installing node

With HomeBrew installed you can now type out the following in a terminal window:

brew install node

To verify that node is installed appropriately type these commands to get the version of the installed software:

node -v
npm -v

For windows go grab an installer from nodejs.org and run through the installer.

Testing node on your box

With node installed on your machine you can now run a node server.  Doing this is also pretty easy.  Open up your preferred text editor and type in the following code and save it as program.js.

Then open up a terminal window and cd into the directory with your program.js file.  Then type the following on a command line.

node program.js

You should see:

Server running at http://127.0.0.1:8124/

Now you can open a browser window at that url and port number.  The page should load with “Hello World”.

Install botkit

Now that we know that we have node installed and we have set up our first node server we can move on to building up a Slack bot using node.  We will use botkit provided by howdyai.

According to their instructions on their github page we can use npm to install botkit.

npm install --save botkit

Slack stuff

Now we are ready to install a bot into Slack.  To get started you need to have a Slack team you want to attach your bot too.  Inside your slack team go manage your apps and add a Bots integration: https://{your team}.slack.com/apps/manage/custom-integrations.  Then search for Bots and add a Slack Real Time Messaging bot.  Give your bot a name and then copy and paste the API Token (looks like a gobble-d-guck string – GUIDish).

Bot stuff

With your API key in hand you can now create a new file in your preferred text editor called robot.js and enter the following code:

Make sure you replace the <my_slack_bot_token> with your API token.

Then in a terminal window you can cd your way to the directory that has your robot.js file.  Then run the following command.

node robot.js

You should now have a bot user (named what you named it when you created it) showing as an active user in your team.  You can now direct message that bot user or mention the user saying “hello”.  The bot should response with “Hello yourself.”.

If anything goes wrong you will see some output in your terminal window that is running your robot.

Another node tidbit

Now that we have a node app that can be a slack bot let’s add another tidbit that will make our node app operate more like a node app.  We need this primarily to support the ability to shove our app into docker to run it as a node app.

Specifically we need to add a package.json file which is basically a configuration and meta data file.  This is a json file that houses the name of the application, its version, a description, etc.  But it also defines dependencies, how scripts wire up, and so on.  Here is a link that describes all the various pieces you can stuff into this file.

http://browsenpm.org/package.json

Here is the contents of the file I am currently using for my bot.

With this file named package.json and living next to your robot.js file you can now use the following command to start your node app.

npm start

The start command points at your start script in the package file and executes the appropriate commands.  This means who ever is running your app doesn’t really have to understand how to get it running.

Ultimately, we want this so that we can issue simple commands in our docker bits to get our node app running.

Moving right along…

Docker stuff

If you haven’t taken a deep dive into docker yet…oh my!  This technology recently turned three and has turned out world on its head as far as how to develop, test, deploy, and manage our applications.  The statement “works on my machine” sort of disappears.  Vendor lock in with a virtualization layer, or even a cloud provider, can largely be removed as well.  You can push docker instances just about anywhere these days.  And when it comes to not treating your servers as pets docker is the king.  Spin them up, tear them down.  Spin up many of them to handle load.  Docker is great.

So let’s host our bot in a docker container and see how all this works.

Install docker tools

The local story for docker has changed now and then.  The current iteration is pretty easy actually.  But there is an even better story coming soon.  Let’s see how docker tools works.

First off – I am not going to detail all the steps needed for getting Docker running on your mac or windows machines.  They do a great job of this already.  For mac folks go here.  For windows folks go here.  Grab your installers here.

As long as you have the Docker Quickstart Terminal running you should be good to go.

Dockerize your node app

Once you have installed docker and have touched their simple tutorials (understanding the basics) you will need to understand the Dockerfile (capital D is important for some reason).  Start by creating a file named Dockerfile.  This is just an empty text file with no file extension.  This is the configuration for your docker image.  Here is the one I am using for my bot.

Here is the formal docs for Dockerfile if you really want to dig deep on this.

But let me give you the quick overview.  All docker containers start from a base image using the keyword FROM {image name}.  I chose to start from the node:argon image which is a lightweight node base.  You can start from many of the different node ready containers.  Search through the docker hub to find one that suites you.

Then we need to create a location to host our node app.  I chose to put my app in /user/src/app using RUN mkdir -p /usr/src/app.  Then I set that to the working directory with WORKDIR /usr/src/app.

Next we need to run some commands inside our image to get it ready to host our node app.  RUN npm install botkit –save is the same as we did when readying our development environment up above.  We have to repeat this in our docker image.  The same work is done installing botkit in the container.  This gets us ready to take a dependency on botkit.

And then we can copy in our script and package.json file.  This is done with COPY bot.js /usr/src/app/ and COPY package.json /usr/src/app/.

Finally we set the command to be issued when the container starts up with CMD [ “npm”, “start” ] 

Building your image

Now that you have a Dockerfile in your app we can build a docker image.  We do this by opening up the Docker Quickstart Terminal.  Then cd your way into the folder that has your robot application (and Dockerfile) in it.  Then issue this command:

$ docker build -t <your username>/<image name> .

The -t flag allows you to tag your image so that you can easily find it in a long list of images.

: this can be anything.  I use first initial last name ‘asiemer’ : this can also be anything.  I use the app that I am putting in the image.  So your bots purpose is good. To follow along with what we have done so far you could use something like this:
$ docker build -t asiemer/robot .
When you hit enter you will see a long list of information stream by as your image is created for you.  When that is all done you can list out your images.  You should see your freshly built image in the list.
$ docker images
### Running your image Next we can run the image.  We do this with the following entry.
$ docker run -p 49160:8080 -d asiemer/robot
-p is a port mapping (which isn’t entirely needed by your bot unless you intend to have some management screen as part of your node app).  In this case we mapped 8080 inside the container to 49160 on your physical machine. -d runs the container in detached mode which leaves the container running in the background (so that you can run your bot and continue to work in docker). Now that we have the robot running in the background we need to be able to see what it is doing.  We can do this by locating our running container and then tapping into its logs.
$ docker ps
You should see your running container _asiemer/robot._  Next we can print the logs to the screen by getting the logs from the running container by its container id._ _ Thankfully you don’t have to type out the entire container id.  Just the first few characters to make it unique.
$ docker logs <container id>
This should show any output from your robot. To stop the docker container that is running we can use the same container id and issue this command.
$ docker stop <container id>
## Hosting your bot stuff Now that we have done all the leg work of setting up node, getting a slack bot running, and hosting it locally in docker – we are ready to push this bot somewhere that it can live for a longer time than just when your laptop is running.  There are many great platforms for hosting a docker application.  But I also found a specific bot hosting platform that gives you hosting for cheap, but also gives you a complete CI/CD set up in seconds. ### BeepBoopHQ BeepBoop is a slack bot hosting company.  They run your bot on the google cloud.  They integrate the CI/CD story through github with docker.  Perfect for us! To get started you need to create a github repository and push all your bot bits into that new repository.  Reminder: robot.js, package.json, Dockerfile.  You can sync this repository to your local computer or you can just upload those files directly to your new repository. _You will want to sync this to you machine at some point…but not needed for now._ Now you can sign into BeepBoopHQ using your github credentials.  This will prompt you for some additional information.  And you should recieve a beepboophq.slack.com invite.  Add this to your slack app as all the magic of their CI/CD story happens directly in slack (pure magic). Then create a new project (my projects at the top).  Clicking on create a new project will list all your code repositories.  Select the repository that has your bot in it.  There are various details you can set about your bot but those aren’t important just now. As soon as you wire a github repository into beepboop you should see some slack activity in their team.
New Project Created
Github Webhook Registered Build Requested
If you have a Dockerfile (and your other files) in the github repository and all your code was working locally you should see other messages too about the image being built and deployed.  If there are any errors you will see very detailed messaging in the slack channel around what you are missing or what broke. Once everything is running you will have a bot in your slack team that you can do all sorts of things with. ## Build a weather bot Now that all of our plumbing is configured let’s build a quick weather bot.  To use this bot you will have to create a free account with [Weather Underground](https://www.wunderground.com/weather/api/d/docs?d=index&MR=1) so that you can get an API key. With the API key in hand you can then create a simple bot that queries the forecast for a given city and writes the weather back to slack. You can find [the source for this weather bot here](https://github.com/asiemer/weather-bot). ## Chat ops Now you are ready to start tackling the concept of ChatOps.  Hopefully your team (dev team, business team, marketing team, family, slack is great for everybody) is using Slack or similar already.  Now you just need to figure out what could make working together better?  And how to weave your bot above into the conversation. According to StackStorm chat ops is: > ChatOps is a new operational paradigm where work that is already happening in the background today is brought into a common chatroom. By doing this, you are unifying the communication about what work should get done with actual history of the work being done. Things like deploying code from chat, viewing graphs from a TSDB or logging tool, or creating new Jira tickets… all of these are examples of tasks that can be done via ChatOps. > > Not only does ChatOps reduce the feedback loop of work output, it also empowers others to accomplish complex self-service tasks that they otherwise would not be able to do. Combining ChatOps and StackStorm is an ideal combination, where from Chat users will be able to execute actions and workflows to accelerate the IT delivery pipeline. There are all sorts of presentations on ChatOps. Here is a getting started presentation on ChatOps and why. And here is one of the first ChatOps videos around HuBot at github. ##
Are you learning Docker yet