在Docker中运行grunt时出现错误:致命错误:无法找到本地grunt。

6

我正在尝试在Docker中运行我的项目,并将所有依赖项放在其中,但是我卡在了grunt依赖项上。出于某种原因,grunt会失败并显示一个错误,指出它找不到本地的grunt。

我创建了一个示例来重现这个问题:

.
├── 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 ... 安装所有依赖项 ... 安装完成后,当尝试使用我在docker-compose.yml文件中指定的grunt命令运行时,会出现以下错误:

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实际上包含grunt作为一个依赖项,因此应在RUN npm install之后安装。

2个回答

3

执行 docker exec -it <容器名称> bash 命令,然后查看 node_modules 文件夹是否已本地安装了 grunt。

你有在某个地方设置 NODE_ENVproduction 吗? 这会导致 npm 不安装 devDependencies


看起来我唯一拥有的node_modules文件夹是/usr/local/lib/node_modules,项目文件夹中实际上缺少node_modulesbower_componentsNODE_ENV未设置。 - psycat
你的 package.json 是否存在于 WORKDIR 中? - Alexander Zeitler
还可以在你的命令中添加 cwd 来查看 grunt 在尝试运行的位置。 - Alexander Zeitler
package.json 存在于 WORKDIR 中,grunt 尝试从正确的 WORKDIR 运行,通过将 'ls' 和 'pwd' 放入 'command' 进行测试。 - psycat
如果你进入容器并在WORKDIR内运行npm install会发生什么? - Alexander Zeitler
显示剩余4条评论

1
我认为我找到了 node_modulesbower_components 未被创建的原因(在文档中)

注意:如果任何构建步骤更改已声明的卷中的数据,则这些更改将被丢弃。

虽然我没有在我的Dockerfile中声明 VOLUME,但我在我的 docker-compose.yml 中有 volumes,所以我怀疑这个提示会影响我,因为 npm installbower install 的构建步骤都会触及卷中的数据。

我从Dockerfile中删除了这些构建步骤,并在构建完成后手动执行它们:

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

然而,当我运行上述命令时,我遇到了权限问题,因为我的新建用户没有写入主机的权限,而且我不想在容器内以 root 用户身份运行(例如,bower 在没有 --allow-root 的情况下会不喜欢它)。
解决方法是创建一个与主机相同 UID 和 GID 的用户。
我发现 Docker 允许 变量替换构建参数,这意味着您不必在 docker-compose.yml 中硬编码 UID 和 GID,而是可以从主机环境变量中获取它们,并且可以在构建过程中访问。
$ 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接