2

I'm using Docker on windows for development purposes and i'm trying to create a simple workflow for a node.js project.

I followed this tutorial https://nodejs.org/en/docs/guides/nodejs-docker-webapp/ so my Dockerfile looks like this

FROM node:boron

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
COPY package.json .
# For npm@5 or later, copy package-lock.json as well
# COPY package.json package-lock.json ./

RUN npm install

# Bundle app source
COPY . .

EXPOSE 8080
CMD [ "npm", "start" ]

My "workflow" for each change would look like this

FIRST BUILD

docker build -t thomas/myApp DockerProjects/myApp ; docker run --name app -p 49160:8080 -d thomas/myApp

AFTER EACH CHANGE

docker build -t thomas/myApp DockerProjects/myApp ; docker stop app  ; docker rm app ; docker run --name app -p 49160:8080 -d thomas/myApp

I don't want to have hundreds of containers after each change in the project, that's why i'm deleting it before creating another one.

I see several problems:

  • Each time there is a change and a new image is build, a new <none>:<none> image is created. These images have the same weight as the original one. How can I avoid that ?
  • Can I use nodemon somehow ?
  • Can I launch this process automatically each time I change something in the code ?

Docker is quite new for me and i'm still experimenting with it. Thanks

1
  • 1
    You should be using volume mount in case of development scenario. Mount your code as volume inside the container and don't build images every single time when code changes Commented Oct 24, 2017 at 18:11

2 Answers 2

3

You can use nodemon in your project to restart your app automatically while your source code directory would be mounted on a volume.

For instance, with this directory structure (which is using Grunt from package.json to run nodemon) :

app/
├── Dockerfile
├── package.json
├── Gruntfile.js
├── src/
│   └── app.js
└── docker-compose.yml

You can use docker-compose which is a tool used to run multiple container. This can be useful if you want to add a database container your app would talk to or any additionnal services interacting with your app.

The following docker-compose config will mount src folder on /usr/src/app/src on the container. With nodemon looking for changes inside src, you will be able to make changes on your machine that will restart the app on the container automatically

To use this you would do :

cd app
docker-compose up

The command above with build the image from dockerfile and start the containers defined in docker-compose.yml.

docker-compose.yml :

version: '2'

services:
  your-app:
    build: .
    ports:
     - "8080:8080"
    restart: always
    container_name: app_container
    volumes:
     - ./src:/usr/src/app/src
    environment:
     - SERVER_PORT=8080

Dockerfile :

FROM node:latest

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

COPY package.json .
COPY Gruntfile.js .

RUN npm install

CMD ["npm","start"]

Gruntfile.js :

var path = require('path');

module.exports = function (grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        concurrent: {
            dev: {
                tasks: ['nodemon'],
                options: {
                    logConcurrentOutput: true
                }
            }
        },
        nodemon: {
            dev: {
                script: 'src/app.js',
                options: {
                    ignore: [
                        'node_modules/**'
                    ],
                    ext: 'js'
                }
            }
        },
        clean: {}
    });
    grunt.loadNpmTasks('grunt-concurrent');
    grunt.loadNpmTasks('grunt-nodemon');
    grunt.registerTask('default', ['concurrent']);
};

package.json :

{
  "name": "your-app",
  "version": "1.0.0",
  "description": "service",
  "scripts": {
    "start": "grunt"
  },
  "author": "someone",
  "license": "MIT",
  "dependencies": {
    "express": "^4.14.0"
  },
  "devDependencies": {
    "grunt": "1.x.x",
    "grunt-cli": "1.x.x",
    "grunt-concurrent": "2.x.x",
    "grunt-nodemon": "0.4.x"
  }
}

Sample app.js :

'use strict';

const express = require('express');
const port = process.env.SERVER_PORT;

var app = express();

app.get('/', function(req, res) {
    res.send('Hello World');
});

app.listen(port, function() {
    console.log('listening on port ' + port);
});

To rebuild the image, you would perform docker-compose build

Sign up to request clarification or add additional context in comments.

Comments

0

Each time there is a change and a new image is build, a new <none>:<none> image is created. These images have the same weight as the original one. How can I avoid that ?

You can't. This : iamge is your previous image which was replaced by your new image. So just delete it: docker image prune

Can I use nodemon somehow?

I'm not familiar with that, but it looks like it only restarts your server, but doesnt't do a npm install.

Can I launch this process automatically each time I change something in the code?

I would use Jenkins and automatically build your new Docker image on each git commit.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.