2. Containerize the Express.js Server

Our application requires a Dockerfile and some Kubernetes manifests in order to run on Kubernetes. This is when DevSpace comes into play: it will autogenerate these files for us, thanks to a simple command:

devspace init

Create a Dockerfile

DevSpace automatically detects that there is no Dockerfile in our project root directory and shows several options to continue with. Select the first option Create a Dockerfile for me by hitting Enter and DevSpace will create a Dockerfile in your project directory.

? This project does not have a Dockerfile. What do you want to do? [Use arrows to move, space to select, type to filter]

> Create a Dockerfile for me

Enter path to your Dockerfile

Enter path to your Kubernetes manifests

Enter path to your Helm chart

Use existing image (e.g. from Docker Hub)

If there already is a Dockerfile in the project folder, DevSpace will detect it and suggest to use it instead of creating a new one.

Select The Programming Language

Our programming language will also be detected by DevSpace, so we can confirm that we are using javascript by hitting Enter .

? Select the programming language of this project

[Use arrows to move, space to select, type to filter]

csharp

go

java

> javascript

none

php

python

Choose an Image Registry

DevSpace is going to build a Docker image from our newly created Dockerfile. This image needs to be pushed somewhere. We get the following options:

? Which registry do you want to use for storing your Docker images? [Use arrows to move, space to select, type to filter]

Use hub.docker.com

> Use dscr.io (free, private Docker registry)

Use other registry

If you have no clue which registry to use, you can just use dscr.io. It is free and allows you to push the images to a private registry. DevSpace will then open a login page and allow you to sign up for dscr.io.

Define The Application Port

Enter the port of the Express.js server (remember, we specified it via app.listen() in index.js ). So in our case, we need to enter 3000 :

? Which port is your application listening on? (Enter to skip) 3000

Project Successfully Initialized

Once the init command has terminated, you will find the following new files in your project folder:

express-server/

|

|--devspace.yaml

|--Dockerfile

|--.dockerignore

|--.gitignore

Besides the configuration for DevSpace in devspace.yaml , there is a Dockerfile for building a Docker image for our Express.js server before deploying the app to Kubernetes.

Dockerfile

The autogenerated Dockerfile will look like this:

FROM node:8.11.4 # Create project directory (workdir)

RUN mkdir /app

WORKDIR /app # Add package.json to WORKDIR and install dependencies

COPY package.json .

RUN npm install # Add the remaining source code files to WORKDIR

COPY . . # Start the application

CMD ["npm", "start"]

This Dockerfile:

defines node as base image

as base image creates the working directory /app

copies the package.json into the image and installs the dependencies

into the image and installs the dependencies copies the rest of our application into the working directory

defines npm start as the start command for the container

Adding the package.json separately and installing dependencies before adding the rest of the application allows Docker to use layer-caching and saves a lot of time when building the image because the dependencies will only have to be re-installed when the package.json has changed and not every time we change any other source code file. Not having to install the dependencies every time we re-build and re-deploy our application saves a lot of time.

Note that this Dockerfile starts our Express.js server in development mode. For production, it is recommended to also set the environment variable NODE_ENV=production which would be possible using a separate Dockerfile just for production.

Component Helm Chart

By default, DevSpace deploys your application as a so-called component that uses a highly configurable Helm chart. To customize the deployment of your app, you can edit the values section of the deployments section within the devspace.yaml configuration file:

For more information on how to customize this component, take a look at customizing DevSpace components.

3. Deploy The Express.js Server

Now that our Express server is containerized, we are ready to deploy it to Kubernetes.

Option A: Create a Namespace

If you already have a Kubernetes cluster set up and the kube-context configured on your local machine, you can simply run this command:

devspace use namespace my-express-server

DevSpace will automatically create this namespace during the deployment process later on.

Option B: Create a Space

If you don’t have a Kubernetes cluster yet, it is much easier to create a ready-to-go Kubernetes namespace using DevSpace:

devspace create space my-express-server

This command will create a Kubernetes namespace on DevSpace Cloud. One space with up to 1GB is free in DevSpace Cloud.

Build & Deploy Your App

DevSpace automates the entire deployment process (image building, pushing images to the registry, creating resources in Kubernetes etc.), so you can just run one single command to deploy the Express.js server:

devspace deploy

This command takes a little while when you run it for the very first time. If you run it later again, it will be much quicker.

Now, it’s time to take a look at the deployment in the browser:

devspace open

When DevSpace asks you how to open your application, choose the first option: via localhost

? How do you want to open your application?

[Use arrows to move, space to select, type to filter]

> via localhost (provides private access only on your computer via port-forwarding)

via domain (makes your application publicly available via ingress)

If you are using DevSpace Cloud (i.e. you used devspace create space before), you can also use the option via domain to make your application publicly available on an auto-generated domain.

4. Start Development

If we want to develop this application instead of just running it, we can add nodemon as hot reloading tool and use the file-synchronization of DevSpace to update the deployment within seconds.

Add nodemon for Hot Reloading

Our server is running nicely; nevertheless, if you tried to mess around and modify anything to the index.js , you might have noticed that the changes are not applied, unless we run devspace deploy again. This is a very tedious task that has a negative impact on our development workflow and efficiency, hence it needs to be fixed.

Luckily, there is a nice package that was created to overcome this problem: nodemon. Once installed, it will automatically restart our Node.js application when file changes are detected in the directory. So, let’s install it:

npm install --save-dev nodemon

Instead of running node index.js , we can now run:

nodemon index.js

Change The Start Command

Let’s assume that you are in a small team, not everyone is supposed to know the specific command to use in order to start the app correctly. The best practice in this case is to add our nodemon index.js command in the scripts of the package.json :

"scripts": {

"start": "nodemon index.js"

},

This is only suitable for development. For production, you should add another script, e.g. "start-prod": "node index.js" .

Start Development Mode

You can now just run this command to develop directly inside the Kubernetes cluster:

devspace dev -b

Let’s change something in our app to check if the hot reloading is working. For instance, replace Hello World! with Bye World! and then save the file. If it's working, a message similar to the one below should be displayed in the console:

[nodemon] restarting due to changes...

[nodemon] starting `node index.js`

App listening on port 3000!

Refresh your web page at http://localhost:3000/ and you should see your changes without having to restart the app manually!

Happy Coding!

I hope you liked this tutorial and were able to deploy your first Express.js app to Kubernetes. Leave a comment, clap for this post on Medium or share the link with your colleagues, if this article was helpful for you.