NodeJS не может найти модуль при работе в контейнере Docker

Я пытаюсь закрепить приложение node.js (называемое «Хаб») в докере для Windows с контейнерами на базе Linux, но при создании/запуске контейнера не удается получить доступ к зависимости. Приложение является частью микросервисной архитектуры, в которой у меня есть несколько локальных общих модулей, которые используются различными службами. Hub-сервис не использует никаких томов.

В этом конкретном случае затронутая служба использует модуль аутентификации и вспомогательный модуль. Модуль аутентификации также включает в себя вспомогательный модуль. Кажется, в этом проблема.

Я получаю следующую ошибку:

hub-1  | Error: Cannot find module 'helper'
hub-1  | Require stack:
hub-1  | - /src/apps/Common/Authentication/index.js
hub-1  | - /src/apps/Hub/WS/eventhandler.js
hub-1  | - /src/apps/Hub/WS/initws.js
hub-1  | - /src/apps/Hub/index.js
hub-1  |   requireStack: [
hub-1  |     '/src/apps/Common/Authentication/index.js',
hub-1  |     '/src/apps/Hub/WS/eventhandler.js',
hub-1  |     '/src/apps/Hub/WS/initws.js',
hub-1  |     '/src/apps/Hub/index.js'
hub-1  |   ]
hub-1  | }

Структура папок соответствует предложению: Настройка приложения docker nodejs с локальными зависимостями npm

Это выглядит так:

Main Folder
|- <Dockerfiles for each service>-> "Dockerfile_Hub"
|- compose.yaml (Docker-compose)
|-apps
  |-Hub
  |- ...several other services
  |-Common
    |-Authentication
    |-Helper 
    |- ... several other common modules

В файле docker я копирую ВСЕ часто используемые модули в контейнер, а затем запускаю команду установки npm. У меня есть другой сервис, где это работает безупречно, похоже, это как-то связано с путями к файлам во взаимозависимости между общими модулями (модуль аутентификации также зависит от вспомогательного модуля).

Package.json-файлы:

{
  "name": "hub",
  "version": "1.0.0",
  "description": "Hub Service",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "authentication": "file:../Common/Authentication",
    "axios": "^1.6.8",
    "config": "file:../Common/Config",
    "crypto": "^1.0.1",
    "express": "^4.19.1",
    "express-session": "^1.18.0",
    "fs": "^0.0.1-security",
    "helper": "file:../Common/Helper",
    "http": "^0.0.1-security",
    "jsonwebtoken": "^9.0.2",
    "keycloak-connect": "^24.0.2",
    "logger": "file:../Common/Logger",
    "node-jose": "^2.2.0",
    "socket.io": "^4.7.5",
    "swagger-jsdoc": "^6.2.8",
    "swagger-ui-express": "^5.0.0"
  }
}

{
  "name": "authentication",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "config": "file:../Config",
    "helper": "file:../Helper",
    "jsonwebtoken": "^9.0.2",
    "jswt": "^1.4.4",
    "logger": "file:../Logger"
  }
}

Файлы Docker (как предложено в упомянутой статье):


ARG NODE_VERSION=20.12.0

FROM node:${NODE_VERSION}-alpine

ENV NODE_ENV development

WORKDIR /usr/src/app

RUN mkdir -p /src
COPY ./apps/Common /src/apps/Common
COPY ./apps/Hub /src/apps/Hub

# Download dependencies as a separate step to take advantage of Docker's caching.
# Leverage a cache mount to /root/.npm to speed up subsequent builds.
# Leverage a bind mounts to package.json and package-lock.json to avoid having to copy them into
# into this layer.
RUN --mount=type=bind,source=/apps/Hub/package.json,target=package.json \
    --mount=type=bind,source=/apps/Hub/package-lock.json,target=package-lock.json \
    --mount=type=cache,target=/root/.npm \
    npm ci --omit=dev


RUN cd /src/apps/Hub && npm install

# Run the application as a non-root user.
USER node

# Expose the port that the application listens on.
EXPOSE 8000

# Run the application.
CMD node /src/apps/Hub/index.js

Docker-составьте:

version: "3"

#Hub

services:
  hub:
    build:
      context: .
      dockerfile: Dockerfile_Hub
    environment:
      NODE_ENV: development
      APP_PATH: /src/apps/Hub
      PINO_LOG_LEVEL: debug
    ports:
      - 3000:3000

Процесс сборки выполняется без каких-либо ошибок:

[+] Building 0.0s (0/0)  docker:default
[+] Building 0.0s (0/0)  docker:defaultr reading preface from client //./pipe/docker_engine: file has already been closed
[+] Building 3.2s (15/15) FINISHED                                                                                                                  
 => [hub internal] load build definition from Dockerfile_Hub                                                                                        
 => => transferring dockerfile: 1.38kB                                                                                                              
 => [hub] resolve image config for docker.io/docker/dockerfile:1                                                                                    
 => CACHED [hub] docker-image://docker.io/docker/dockerfile:1@sha256:a57df69d0ea827fb7266491f2813635de6f17269be881f696fbfdf2d83dda33e               
 => [hub internal] load metadata for docker.io/library/node:20.12.0-alpine                                                                          
 => [hub internal] load .dockerignore                                                                                                               
 => => transferring context: 2B                                                                                                                     
 => [hub stage-0 1/8] FROM docker.io/library/node:20.12.0-alpine@sha256:ef3f47741e161900ddd07addcaca7e76534a9205e4cd73b2ed091ba339004a75            
 => [hub internal] load build context                                                                                                               
 => => transferring context: 478.86kB                                                                                                               
 => CACHED [hub stage-0 2/8] WORKDIR /usr/src/app                                                                                                   
 => CACHED [hub stage-0 3/8] RUN mkdir -p /src                                                                                                      
 => CACHED [hub stage-0 4/8] COPY ./apps/Common /src/apps/Common                                                                                    
 => CACHED [hub stage-0 5/8] COPY ./apps/Hub /src/apps/Hub                                                                                          
 => CACHED [hub stage-0 6/8] RUN --mount=type=bind,source=/apps/Hub/package.json,target=package.json     --mount=type=bind,source=/apps/Hub/package-
 => CACHED [hub stage-0 7/8] RUN cd /src/apps/Hub && npm install                                                                                    
 => [hub stage-0 8/8] WORKDIR /src/apps/Hub                                                                                                         
 => [hub] exporting to image                                                                                                                        
 => => exporting layers                                                                                                                             
 => => writing image sha256:4f2ce3b43d06485ec72da1c107df361e6b0a11d44785beea3baff85ff60170a3                                                        
 => => naming to docker.io/library/finslice-hub                                                                                                     
[+] Running 2/2
 ✔ Container crazy_rosalind  Removed
 ✔ Container finslice-hub-1  Recreated
Attaching to hub-1
hub-1  | node:internal/modules/cjs/loader:1146
hub-1  |   throw err;
hub-1  |   ^
hub-1  | 
hub-1  | Error: Cannot find module 'helper'
hub-1  | Require stack:
hub-1  | - /src/apps/Common/Authentication/index.js
hub-1  | - /src/apps/Hub/WS/eventhandler.js
hub-1  | - /src/apps/Hub/WS/initws.js
hub-1  | - /src/apps/Hub/index.js
hub-1  |   requireStack: [
hub-1  |     '/src/apps/Common/Authentication/index.js',
hub-1  |     '/src/apps/Hub/WS/eventhandler.js',
hub-1  |     '/src/apps/Hub/WS/initws.js',
hub-1  |     '/src/apps/Hub/index.js'
hub-1  |   ]
hub-1  | }
hub-1  |
hub-1  | Node.js v20.12.0
hub-1 exited with code 1

Если я получу доступ к файловой системе контейнеров, я увижу, что все файлы/папки скопированы правильно.

Контейнерная файловая система

Вероятно, это как-то связано с тем, как я установил команды WORKDIR/CD в файле docker. Я попытался изменить это на (последние 2 строки файла docker):

РАБОЧИЙ ПАРАМЕТР /src/apps/Hub Узел CMD index.js

с тем же результатом.

Запуск приложения только через node.js вне докера работает без каких-либо проблем.

Почему вы начали свой путь с корня? Ставьте лайк /src/apps/Common. так и должно быть ./src/apps/Common. Его можно увидеть во всем файле докера. Гораздо лучше использовать COPY . . и игнорировать ненужные файлы, используя файл .dockerignore.

Raeisi 20.05.2024 12:52
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
120
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я наконец решил это. Попробовав совет Раиси и перейдя на файлы .dockerignore вместо выборочного копирования файлов, я внимательно изучил файловую систему в копии контейнера.

Что происходит: npm install для внутренних зависимостей (т. е. npm install ../Common/Authentication и т. д.) только создает символические ссылки на папку, но фактически не копирует модуль в папку. Вероятно, это сработало бы, если бы я работал на машине с Linux, но на машине с Windows символические ссылки относятся к каталогу в стиле Windows (т.е. d:\myApp\myModule), который, конечно, не будет работать в контейнере на базе Linux.

Что решило проблему, так это статья:

Установить каталог локального модуля npm без символических ссылок?

простое решение: «используйте npm install --install-links ../module» вместо «npm install ../module». Это скопирует весь исходный код, как если бы это был внешний пакет.

Другие вопросы по теме