This article serves as a quick reference on how to resinify your existing projects.
Why should you resinify your projects? Well it allows you to push updates to your linux devices from the couch while you sip on some hot coco. It also gives you a bunch of other developer super powers, but let's concentrate on the hot coco for now.
There are 3 steps needed to convert any project to a resin.io project.
- Create an app on our dashboard
- Add instructions for our build servers and device supervisor
- Deploy code with the standard git workflow
Using Google's the popular
coder project as a reference, let's expand on each step.
Google coder runs a small server which hosts webapp that allows users to craft neat little projects in HTML, CSS, and Javascript.
Step 1
Head over to your resin.io
dashboard and create an app. Download the device OS and extract its contents onto a SD card. Then pop the card into your device and boot it up. After a few minutes your device will appear on your dashboard.
If you get stuck at any point in this step, have a look at our docs for a more detailed explanation on getting your devices connected to resin.io.
Step 2
With resin.io there are two ways to issue instructions on how to build your image and what behaviour to execute when your application initializes on the device. One option is with a package.json file which is only used in node.js projects. The second is with a Dockerfile, this approach is far more flexible and allows you to craft applications in any language and with any linux base OS.
Before we create the instructions for resin.io let's clone the coder repository to our local machines with.
$ git clone https://github.com/googlecreativelab/coder.git
There are a few instructions we need to pass to resin.io in order to run the coder project on our device.
The first is what image we should build with. The second is what dependencies are needed and the third is what commands are needed to run when the container initializes on the device. Because coder is a node.js project you may follow either of the two approaches of implementing these instructions.
Dockerfile approach
As previously mentioned the Dockerfile is a more flexible approach as it allows you to build containers with custom images for applications written in any language. It is also recommended as it has better caching methods than the package.json, which means faster build speeds.
You can read up on docker commands
here. However we will be using the most basic ones.
The Dockerfile gives instructions to the build server and device supervisor on how to build the image and which commands to execute when the container starts on the device respectively. Let's construct a Dockerfile that will allow google's coder to run on a raspberry pi in a resin.io container.
First we'll need to pick a base image.
Resin.io has a bunch of images with node preinstalled on the
docker registry. I've chosen our defualt node image with node 0.10.22 installed as the latest node version has breaking changes. However your project may allow a build with the other images resin.io hosts or
your own custom image.
So create a Dockerfile in the root of your repository, and tell it which image you'd like to build with.
FROM resin/rpi-node:0.10.22
Then you need to add your projects files to your container. It's standard practice to put them into a directory named "app".
COPY . /app
Next step is to run any extra installs you need. In google coder's case, we need to install all the node dependencies in the coder-base. And all the predifined apps from coder-apps.
RUN cd /app/coder-base && \
npm install
RUN cd /app/coder-apps && \
./install_common.sh ../coder-base
Note: RUN commands occur on the build server and not on your device.
Then set your containers working directory to where you want to execute your device commands. (This command isn't nesscary but it makes the commands following a little easier on the eye as you don't have to cd into multiple directories).
WORKDIR /app/coder-base
Note: The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile.
Finally initiate your node server when the container starts.
CMD ["node", "server.js"]
Note: There can only be one CMD file per Dockerfile and it is only executed on the device.
You should end up with a Dockerfile looking something like this.
FROM resin/rpi-node:0.10.22
COPY . /app
RUN cd /app/coder-base && \
npm install
RUN cd /app/coder-apps && \
./install_common.sh ../coder-base
WORKDIR /app/coder-base
CMD ["node", "server.js"]
For a quick look at our code changes to google's coder have a look over the
fork diff.
Package.json approach
Package.json works in much the same way for resin.io as a Dockerfile. Although it only works for node images, hence it can be used for the google coder project.
First step is creating a package.json in the root of your repository in much the same way you would for a normal node package.
{
"name": "resin-coder",
"description": "resin compatible google-coder",
"version": "0.0.1",
"private": true,
"scripts": {
"preinstall": "COMMANDS TO EXECUTE ON RESIN BUILD SERVER",
"start": "COMMANDS TO EXECUTE ON DEVICE CONTAINER START"
}
}
The scripts property is the most important, resin.io has a few events that trigger these commands throughout the push cycle.
Preinstall occurs on the build server & start occurs once the container starts on the device. These can be compared to the RUN and CMD commands from our dockerfile.
There are a few commands we need to run on the build server so let's create a bash script that installs all the dependencies and downloads all the example coder apps. This is bash script is fulfilling the same functionality as our RUN command did in the Dockerfile.
#install.sh
set -o errexit
set -o pipefail
cd coder-base
npm install
cd ../coder-apps
./install_common.sh ../coder-base`
Now let's update our package.json to run this bash script.
"preinstall": "bash install.sh"
Then tell resin’s supervisor to run coder server when the container starts on the device.
"start": "cd coder-base && node server.js"
It's important to note that you cannot alter the node.js version with the package.json method. The image will be built off resin's defualt node image, which is currently 0.10.22.
For a quick look at our code changes to google's coder have a look over
fork diff.
Step 3
All that's left is pushing code to your devices. It's very simple as it follows git's standard practices but here is a blow by blow in case you aren't expierenced with git.
$ git init
$ git add .
$ git commit -a -m “resinifed”
You can get your applications git endpoint from the dashboard.
$ git remote add resin git@git.resin.io:($USERNAME)/($APPNAME).git
Then, push:
$ git push resin master
A unicorn will let you know that your push has been successful and your code will download on your device.
You’ll now have coder running on your raspberry pi. To access the server, go to
https://$(RASPBERY-PI-IP):8081. You can get the IP address of your device from the resin.io dashboard.
Now you can push updates to your project from the sofa, and if you have many RPi's you want to push to, simply add them to the app the same way you did the first one. The only time you’ll have to get up is for some more hot coco!
Any questions? or you'd just like to say hi, come find us on our
community chat.