Setup two stages of Dockerfile to build a nodejs app

In this post, I’ll create a simple http server app with nodejs and setup build scripts to bundle a project into a dist folder.
After validating that works well, I’ll create a Dockerfile to build the nodejs app in a container and then create a final image with only the dist folder as a new image layer.

An simple Nodejs App

  • Create a folder mkdir -p ~/two-stages-docker-build-nodejs-app and go to that folder cd ~/two-stages-docker-build-nodejs-app to intilize an npm project npm init --yes.
  • Add license npx license Apache-2
  • Create a src folder mkdir -p ~/two-stages-docker-build-nodejs-app/src and add a index.js file cd ~/two-stages-docker-build-nodejs-app/src && touch index.js with a simplest http server.
    1
    2
    3
    4
    5
    6
    7
    var http = require('http');

    //create a server object:
    http.createServer(function (req, res) {
    res.write('Hello World!'); //write a response to the client
    res.end(); //end the response
    }).listen(8080); //the server object listens on port 8080
  • We want to have gulp as a bundle tool and add babel, uglify and rename pipe to it
    1
    npm install @babel/core gulp gulp-babel gulp-uglify gulp-rename --save-dev
  • Create a gulpfile.js and add a simple build task in it, we take everything from src folder and put the result into dist folder
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    const { src, dest, parallel } = require('gulp');
    const babel = require('gulp-babel');
    const uglify = require('gulp-uglify');
    const rename = require('gulp-rename');

    function srcBuild() {
    return src("src/*.js")
    .pipe(babel())
    .pipe(dest('dist/'))
    .pipe(uglify())
    .pipe(rename({ extname: '.min.js' }))
    .pipe(dest('dist/'));
    }

    exports.default = srcBuild
  • Run the build to test it works npx gulp
  • Run the server to test it works node dist/index.min.js

To build the nodejs app into a docker container

  • Create a Dockerfile under the root of the project touch Dockerfile

    1
    2
    3
    4
    5
    6
    7
    8
    9
    FROM node:12 AS builder
    WORKDIR /build
    COPY . .
    RUN npm install && npx gulp

    FROM node:12
    WORKDIR /app
    COPY --from=builder /build/dist .
    ENTRYPOINT [ "node", "./index.js" ]
  • Build the image docker build . -t two-stages-docker-nodejs

  • Run the image docker run -p 8080:8080 two-stages-docker

  • Access in the browser http://localhost:8080

Related tools:

NPM
Gulp
Docker

References:

https://gulpjs.com/docs/en/getting-started/quick-start
https://docs.npmjs.com/getting-started
https://docs.docker.com/develop/develop-images/multistage-build/

Source code

https://github.com/kai-chu/PieceOfCodes/tree/master/two-stages-docker-build-nodejs-app