Node.js development with Skaffold file sync – Hacker Noon

Skaffold team recently announced an exciting new feature that allows to sync files between your machine and the development container, making a big step forward in supporting interpreted languages like Node.js.

Skaffold is a command line tool to develop applications against a Kubernetes cluster (either a local Minikube or a remote cluster). Skaffold handles the build, push and deploy process of the image upon code change. Until today, Skaffold was (IMHO) not well-suited to interpreted languages like Node.js, due the inherent slowness of the process. With version 0.16.0, Skaffold supports an hybrid approach, allowing to take advantage of the usual auto-reload mechanisms used by Node.js developers (e.g.: nodemon):

  • When a js file changes, Skaffold syncs it with the container and the app is restarted by nodemon
  • When a file change requires to rebuild the container (for example, a change to package.json), Skaffold does the full rebuild, push and deploy

This hybrid approach is perfectly suited to a large class of technology stacks, like Node.js, React, Angular, Python, etc.

Quick tutorial

Code available in the Skaffold master branch.

Install Skaffold

  • Installing Skaffold requires a Kubernetes cluster. A good local choice is Minikube or a recent (edge) Docker for Mac or Docker for Windows.

Create a Node.JS app

npm init
  • Add the Express web framework to package.json:
npm install express nodemon --save
  • Remove node_modules locally:
rm -rf node_modules
  • Add the nodemon run command to the scripts section in package.json:
"scripts": {
"dev": "nodemon index.js"
},
  • Create index.js:
index.js

Dockerize it

  • Create a Dockerfile:
  • Create a Kubernetes pod definition k8s-pod.yaml:
k8s-pod.yaml

If you use an editor that writes temporary files (like vim) you need a .dockerignore file to make sure that temporary files do not trigger a container build:

.dockerignore

Skaffold configuration

  • Create a skaffold.yaml:

The deploy section points to the pod definition, while the build section points to current directory, where the Dockerfile is located. The sync clause disables the full rebuild/push/deploy for *.js file changes and enables the sync process of those files to the container.

Running Skaffold

  • skaffold dev

This command starts the Skaffold file watcher, builds the image and deploys it on the cluster; it also shows you the application logs and it handles port forwarding for you. When you see:

...
[node] Example app listening on port 3000!

You’re ready to access the application:

$ curl localhost:3000
Hello World!

Development workflow

Make some changes to index.js. You will see that the modified file is synced to the container and nodemon restarts the application:

Syncing 1 files for gcr.io/k8s-skaffold/node-example:dirty-11d1880
Watching for changes every 1s...
[node] [nodemon] starting `node index.js`
[node] Example app listening on port 3000!
$ curl localhost:3000
Hello World - changed!

Fast and easy!

If you change a file that requires rebuilding the container (like adding a dependency in package.json) the full build/push/deploy mechanism is triggered:

Starting build...
Found [minikube] context, using local docker daemon.
Building [gcr.io/k8s-skaffold/node-example]...
Sending build context to Docker daemon 10.34MB
Step 1/5 : FROM node:8.12.0-alpine
---> df48b68da02a
...
Build complete in 8.236026621s
...
[node] Example app listening on port 3000!

The time it takes depends on the complexity of your package.json.

Future Improvements

Even if changing package.json does not happen that often, rebuilding a complex app can be lengthy. A mechanism is needed to make use of npm cache to speed up the process.

My upcoming talk

If you want to lean more about local development with Kubernetes, please join my talk at the amazing All Day DevOps online conference on October 17, 2018. It’s free!

read original article here