Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error running grunt in docker: Fatal error: Unable to find local grunt

Tags:

docker

gruntjs

I'm trying trying to run my project with all dependencies inside docker but I got stuck with grunt dependency, for some reason grunt fails with an error that it can't find local grunt.

I created an example of how to reproduce this:

.
├── code
│   ├── bower.json
│   ├── Gruntfile.js
│   └── package.json
├── docker-compose.yml
└── frontend.dockerfile

docker-compose.yml:

version: "2"
services:
  frontend:
    build:
      context: .
      dockerfile: frontend.dockerfile
    ports:
      - "8585:8000"
    volumes:
      - ./code:/srv/frontend
    command: grunt

frontend.dockerfile:

FROM node:wheezy

ADD code /srv/frontend
WORKDIR /srv/frontend
RUN npm install -g grunt-cli bower
RUN npm install

RUN groupadd -r usergroup && useradd -m -r -g usergroup user
RUN chown -R user:usergroup /srv/frontend
USER user

RUN bower install

bower.json:

{
  "name": "code",
  "description": "",
  "main": "index.js",
  "authors": [
    "Mr. No One"
  ],
  "license": "ISC",
  "homepage": "",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "angular": "^1.5.8"
  }
}

Gruntfile.json:

module.exports = function(grunt) {
    grunt.initConfig({});

    // tasks
    grunt.registerTask('default', []);
};

package.json:

{
  "name": "code",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "grunt": "^1.0.1"
  }
}

$ docker-compose up ... installing all dependencies ... after installation, it fails when tries to run the grunt command I specified in my docker-compose.yml file with this error:

frontend_1  | grunt-cli: The grunt command line interface (v1.2.0)
frontend_1  | 
frontend_1  | Fatal error: Unable to find local grunt.
frontend_1  | 
frontend_1  | If you're seeing this message, grunt hasn't been installed locally to
frontend_1  | your project. For more information about installing and configuring grunt,
frontend_1  | please see the Getting Started guide:
frontend_1  | 
frontend_1  | http://gruntjs.com/getting-started

package.json actually does include grunt as a dependency so it should be installed after RUN npm install.

like image 915
psycat Avatar asked Aug 26 '16 12:08

psycat


People also ask

How do I install local grunt?

Installing grunt-cli locally If you prefer the idiomatic Node. js method to get started with a project ( npm install && npm test ) then install grunt-cli locally with npm install grunt-cli --save-dev. Then add a script to your package. json to run the associated grunt command: "scripts": { "test": "grunt test" } .

What is npm install grunt cli?

The Grunt command line interface. Install this globally and you'll have access to the grunt command anywhere on your system. npm install -g grunt-cli. Note: The job of the grunt command is to load and run the version of Grunt you have installed locally to your project, irrespective of its version.

How do I download grunt from command line?

Installing the CLI. Run sudo npm install -g grunt-cli (Windows users should omit "sudo ", and may need to run the command-line with elevated privileges). The grunt command-line interface comes with a series of options. Use grunt -h from your terminal to show these options.


2 Answers

Do a docker exec -it <nameofyourcontainer> bash and look into node_modules if grunt is installed locally.

Did you set NODE_ENV to production somewhere? This causes npm to not install devDepedencies.

like image 162
Alexander Zeitler Avatar answered Sep 30 '22 19:09

Alexander Zeitler


I think I found the reason why node_modules and bower_components are not created in the docs.

Note: If any build steps change the data within the volume after it has been declared, those changes will be discarded.

While I don't have VOLUME declared in my dockerfile, I do have volumes in my docker-compose.yml so I suspect this note is affecting me because both npm install & bower install build steps do touch data within the volume.

I removed those build steps from the dockerfile and did them manually after build is complete:

$ docker-compose build
$ docker-compose run --rm frontend npm install
$ docker-compose run --rm frontend bower install

However, I encountered problem with permissions when running those commands above, since my newly created user did not have permissions to write to host and I didn't want to run as root inside container (bower for example will not like it without --allow-root)

The solution is to create user with the same UID and GID as the host.

I found that docker allows variable substitution and build arguments that means you don't have to hardcode UID and GID inside docker-compose.yml, instead, they can be taken from host env variables like so and can be accessed during the build.

$ export HOST_UID=$(id -u)
$ export HOST_GID=$(id -g)

frontend.dockerfile:

FROM node:wheezy

ARG hostuid
ARG hostgid

ADD code /srv/frontend
WORKDIR /srv/frontend
RUN npm install -g grunt-cli bower

RUN groupadd -g "$hostgid" devgroup && useradd -m -u "$hostuid" -g devgroup developer
RUN chown -R developer:devgroup /srv/frontend
USER developer

docker-compose.yml:

version: "2"
services:
  frontend:
    build:
      context: .
      dockerfile: frontend.dockerfile
      args:
        - hostuid=${HOST_UID}
        - hostgid=${HOST_GID}
    ports:
      - "8585:8000"
    volumes:
      - ./code:/srv/frontend
    command: grunt
like image 33
psycat Avatar answered Sep 30 '22 17:09

psycat