Docker 构建不在 `node_modules` 卷中安装包

Docker build does not install packages in `node_modules` volumes

什么原因导致 yarn/npm 安装时未在卷中安装任何软件包?

我有一个 Docker 文件,其中包含 运行 纱线安装的说明(使用 NPM 和 YARN 进行了测试),但是容器内的包 node_modules 目录是空的。如果我 exec -it service_name bash 和 运行 手动安装命令,它会正确安装包。 我在重构后注意到了这一点,我有一个 Worker 服务执行安装过程,第二个 运行 开发服务器。决定将所有内容都保留在相同的 Docker-compose 声明中,但由于问题开始发生,它仍然存在。尝试完全重置等但没有成功(关闭、rm 容器、p运行e 等)。

Docker-compose 文件中声明的相关服务:

  node_dev:
    build:
      context: .
      dockerfile: ./.docker/dockerFiles/node.yml
    image: foobar/node_dev:latest
    container_name: node_dev
    working_dir: /home/node/app
    ports:
     - 8000:8000
     - 9000:9000
    environment:
      - NODE_ENV=development
      - GATSBY_WEBPACK_PUBLICPATH=/
    volumes:
      - ./foobar-blog-ui/:/home/node/app
      - ui_node_modules:/home/node/app/node_modules
      - ui_gatsbycli_node_module:/usr/local/lib/node_modules/gatsby-cli
      - ./.docker/scripts/wait-for-it.sh:/home/node/wait-for-it.sh
    command: /bin/bash -c '/home/node/wait-for-it.sh wordpress-reverse-proxy:80 -t 10 -- yarn start'
    depends_on:
      - mysql
      - wordpress
    networks:
      - foobar-wordpress-network

服务中的相关 Volumes 引用:

volumes:
    ui_node_modules:
    ui_gatsbycli_node_module:

最后,生成图片的Docker文件:

FROM node:8.16.0-slim

ARG NODE_ENV=development
ENV NODE_ENV=${NODE_ENV}

WORKDIR /home/node/app

RUN apt-get update
RUN apt-get install -y rsync vim git libpng-dev libjpeg-dev libxi6 build-essential libgl1-mesa-glx

RUN yarn global add gatsby-cli
RUN yarn install

此外,尝试 yarn install --force --no-lockfile 并确保它在项目根目录中没有任何包或 yarn 锁定文件的情况下进行测试,反之亦然。

我发现这很奇怪,肯定是某个地方的错字,但我还没有发现。

主机系统是 macOS Mojave。

我想提一下,如果 exec -it service_name bash 并执行 NPM/YARN 安装,node_modules 会填充软件包。 在我做的大多数测试之前,我还尝试通过以下方式重置:

docker-compose stop
docker-compose rm -f
docker volume prune -f
docker network prune -f

现在测试了:

docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
docker volume prune -f
docker volume rm $(docker volume ls -qf dangling=true)
docker network prune -f
docker system prune --all --force --volumes
rm -rf ./.docker/certs/ ./.docker/certs-data/ ./.docker/logs/nginx/ ./.docker/mysql/data

特定图像的日志:

Building node_dev
Step 1/8 : FROM node:8.16.0-slim
8.16.0-slim: Pulling from library/node
9fc222b64b0a: Pull complete
7d73b1e8f94b: Pull complete
1059045652d5: Pull complete
08cd60b80e4e: Pull complete
b7d875c65da4: Pull complete
Digest: sha256:0ec7ac448d11fa1d162fb6fd503ec83747c80dcf74bdf937b507b189b610756a
Status: Downloaded newer image for node:8.16.0-slim
 ---> 67857c9b26e1
Step 2/8 : ARG NODE_ENV=development
 ---> Running in da99a137d733
Removing intermediate container da99a137d733
 ---> 0f9b718d3f66
Step 3/8 : ARG NPM_TOKEN=3ea44a41-9293-4569-a235-a622ae216d60
 ---> Running in e339a4939029
Removing intermediate container e339a4939029
 ---> e47b42008bc3
Step 4/8 : ENV NODE_ENV=${NODE_ENV}
 ---> Running in fdc09147e9da
Removing intermediate container fdc09147e9da
 ---> 3b28ab5539d3
Step 5/8 : WORKDIR /home/node/app
 ---> Running in 44eef1d9293d
Removing intermediate container 44eef1d9293d
 ---> 2d07ecf3de2e
Step 6/8 : RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc
 ---> Running in a47d5e22839b
Removing intermediate container a47d5e22839b
 ---> bd9f896846b7
Step 7/8 : RUN yarn global add gatsby-cli
 ---> Running in ca3e74d12df4
yarn global v1.15.2
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Installed "gatsby-cli@2.7.47" with binaries:
      - gatsby
Done in 15.51s.
Removing intermediate container ca3e74d12df4
 ---> bc8d15985ad0
Step 8/8 : RUN yarn install --force --no-lockfile
 ---> Running in 3f0e35e5487b
yarn install v1.15.2
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Rebuilding all packages...
Done in 0.04s.
Removing intermediate container 3f0e35e5487b
 ---> 485b9e9bccba
Successfully built 485b9e9bccba
Successfully tagged foobar/node_dev:latest

将服务命令更改为 sleep 300sexect -itls -la /home/node/app/node_modules 以查找:

.yarn-integrity

cat .yarn-integrity 我看到:

{
  "systemParams": "linux-x64-57",
  "modulesFolders": [],
  "flags": [],
  "linkedModules": [],
  "topLevelPatterns": [],
  "lockfileEntries": {},
  "files": [],
  "artifacts": {}
}

您在构建期间安装了节点包,并且如您从日志中看到的那样正确安装,没有任何错误。所以 docker-compose 或现有卷的问题。

因此,可以帮助您调试的一件事是创建卷,然后尝试使用 docker 运行 而不是 docker-compose。

docker volume create my_node_modules
docker run -it --rm -v my_node_modules:/home/node/app foobar/node_dev:lates bash -c "cd /home/node/app;npm list"

现在通过附加任何容器来检查体积以验证行为

docker run -it --rm -v my_node_modules:/home/test/ node:alpine ash -c "cd /home/test/;npm list"

或者另一种选择是在 运行 时安装软件包,然后安装的软件包将在任何卷中可用。

    command: /bin/bash -c '/home/node/wait-for-it.sh wordpress-reverse-proxy:80 -t 10 -- yarn install && yarn start'

验证包是否退出尝试 运行 没有 docker-compose。

docker run -it --rm foobar/node_dev:lates bash -c "cd /home/node/app;npm list"

移动 yarn install 到入口点或不附加节点模块的卷。

我找到了一个解决方案,通过 COPY 指令利用 Docker 的缓存系统,我已将其设置为 COPY package.json、package-lock.json 和 yarn.lock;它缓存构建步骤并且仅在文件有任何差异时更新,否则跳过重新安装包。

总而言之,Docker compose 中的服务与卷保持不变,遵循社区中针对 nodejs 项目共享的最佳实践。

我们可以在volumes中看到一个bind-mount ./foobar-blog-ui/:/home/node/app,它将宿主机上的App源代码挂载到容器中的app目录中。这允许一个快速的开发环境,因为我们在主机中所做的更改会立即填充到容器中,否则不可能这样做。

最后是 node_modules 的命名卷,我将其命名为 ui_node_modules,这很难理解,因为我们首先绑定安装包含根目录的应用程序源代码,其中 node_modules 坐下。 npm install 运行时 node_modules 目录在容器中创建,对吗?但是我们声明的 bind-mount 隐藏了它。因此,名为 ui_node_modules 的命名 node_modules 卷通过将 /home/node/app/node_modules 目录的内容持久化到容器中并绕过隐藏的 bind-mount.

来解决它。
  node_dev:
    build:
      context: .
      dockerfile: ./.docker/dockerFiles/node.yml
    image: foobar/node_dev:latest
    container_name: node_dev
    working_dir: /home/node/app
    ports:
     - 8000:8000
     - 9000:9000
    environment:
      - NODE_ENV=development
      - GATSBY_WEBPACK_PUBLICPATH=/
    volumes:
      - ./foobar-blog-ui/:/home/node/app
      - ui_node_modules:/home/node/app/node_modules
      - ui_gatsbycli_node_module:/usr/local/lib/node_modules/gatsby-cli
      - ./.docker/scripts/wait-for-it.sh:/home/node/wait-for-it.sh
    command: /bin/bash -c '/home/node/wait-for-it.sh wordpress-reverse-proxy:80 -t 10 -- yarn start'
    depends_on:
      - mysql
      - wordpress
    networks:
      - foobar-wordpress-network

volumes:
    ui_node_modules:
    ui_gatsbycli_node_module:

但是 Docker 文件包含复制包的指令*。json 文件有助于确定何时应更新指令步骤或层的 Docker 缓存。

FROM node:8.16.0-slim

ARG NODE_ENV=development

ENV NODE_ENV=${NODE_ENV}

RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app

WORKDIR /home/node/app

# The package files should use Docker cache system
COPY ./foobar-blog-ui/package*.json .
COPY ./foobar-blog-ui/yarn.lock .

RUN yarn global add gatsby-cli
RUN yarn install

RUN apt-get update
RUN apt-get install -y rsync vim git libpng-dev libjpeg-dev libxi6 build-essential libgl1-mesa-glx

EXPOSE 8000

希望这对以后的其他人有所帮助!