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
.
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" } .
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.
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.
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
.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With