docker-compose up не может найти модуль, но запуск из bash работает

#node.js #docker #docker-compose

#node.js #docker #docker-compose

Вопрос:

Я собирал Node.js приложение в Docker и следование советам из превосходных уроков Джона Лис-Миллера по созданию приложения Node в Docker для настройки моей среды. Все работало нормально в течение недели или двух, но сегодня я начал сталкиваться с проблемой, которую я не могу понять.

В двух словах, я больше не могу запускать приложение через docker-compose up ; Я получаю ошибку узла из-за недавно добавленных зависимостей модуля:

 sfsftp_1  | module.js:327
sfsftp_1  |     throw err;
sfsftp_1  |     ^
sfsftp_1  | 
sfsftp_1  | Error: Cannot find module 'eval'
sfsftp_1  |     at Function.Module._resolveFilename (module.js:325:15)
sfsftp_1  |     at Function.Module._load (module.js:276:25)
sfsftp_1  |     at Module.require (module.js:353:17)
sfsftp_1  |     at require (internal/module.js:12:17)
sfsftp_1  |     at Object.<anonymous> (/home/app/sfsftp/lib/reformatter.js:4:13)
sfsftp_1  |     at Module._compile (module.js:409:26)
sfsftp_1  |     at Object.Module._extensions..js (module.js:416:10)
sfsftp_1  |     at Module.load (module.js:343:32)
sfsftp_1  |     at Function.Module._load (module.js:300:12)
sfsftp_1  |     at Module.require (module.js:353:17)
  

Однако, если я запускаю оболочку bash:

 docker-compose run --rm sfsftp /bin/bash 
  

и запустите приложение node изнутри контейнера с помощью node sftp.js , приложение запустится нормально!

Изначально у меня была эта проблема ранее сегодня с модулем jsonminify , который я недавно добавил в проект; Я полагаю, что я запускал приложение обоими способами ( docker-compose up и docker-compose run через bash) с момента внесения этого изменения, но, возможно, нет? В интересах целесообразности я решил разобраться с проблемой и удалил свое использование на jsonminify . Позже мне нужно было добавить eval модуль в мой проект, и теперь я получаю ту же ошибку для этого модуля. Я чувствую, что docker-compose up команда использует более старую копию изображения, чем docker-compose run команда, без моих недавних изменений.

Когда я добавил модули, я проследил за процессом в статье — используйте docker-compose run , чтобы получить оболочку bash и запустить npm install --save module внутри запущенного экземпляра. Мои package.json и npm-shrinkwrap.json файлы обновляются, и я вижу eval модуль в обоих.

Я все еще довольно новичок в разработке в контейнерах Docker, поэтому я достиг точки «давайте попробуем это»; до сих пор я пытался:

  • docker-compose build за которым следует docker-compose up
  • docker-compose up --build
  • docker-compose build --no-cache за которым следует docker-compose up
  • docker run -p 22:9001 sftpdocker_sfsftp

Последнее сработало — запуск docker напрямую, а не через docker-compose. Но при этом теряются некоторые преимущества настройки. Как мне заставить docker-compose работать?

Для справки, вот мой Dockerfile :

 # prepared with reference to http://jdlm.info/articles/2016/03/06/lessons-building-node-app-docker.html
# Current LTS Node version
FROM node:4.6.0

# Let's not run as Root.  And, update to recent NPM
RUN useradd --user-group --create-home --shell /bin/false app amp;amp;
  npm install --global npm@3.7.5

ENV HOME=/home/app

# Get what we need for npm install
COPY package.json npm-shrinkwrap.json $HOME/sfsftp/
RUN chown -R app:app $HOME/*

# and install dependencies
USER app
WORKDIR $HOME/sfsftp
RUN npm install amp;amp; npm cache clean

# do this after dependencies, so that if only the app changes, npm install won't be rerun
USER root
COPY . $HOME/sfsftp
RUN chown -R app:app $HOME/*
USER app

# Start it up!
CMD ["node", "sftp.js"]
  

and docker-compose.yml :

 sfsftp:
  build: .
  ports:
    - '22:9001'
  volumes:
    - .:/home/app/sfsftp
    - /home/app/sfsftp/node_modules
  

и, наконец, package.json :

 {
  "name": "sftp2sf",
  "version": "1.0.0",
  "description": "",
  "main": "sftp.js",
  "scripts": {
    "start": "node sftp.js",
    "test": "mocha",
    "coverage": "istanbul cover _mocha -- -R spec amp;amp; open coverage/lcov-report/index.html"
  },
  "author": "Jason Clark <jason.clark@example.com>",
  "license": "UNLICENSED",
  "dependencies": {
    "buffer-equal-constant-time": "^1.0.1",
    "byline": "^5.0.0",
    "eval": "^0.1.1",
    "fast-csv": "^2.3.0",
    "jsforce": "^1.7.0",
    "jsonminify": "^0.4.1",
    "minimatch": "^3.0.3",
    "minimist": "^1.2.0",
    "moment": "^2.15.1",
    "ssh2": "^0.5.2",
    "through": "^2.3.8"
  },
  "devDependencies": {
    "chai": "^3.5.0",
    "istanbul": "^0.4.5",
    "mocha": "^3.1.0",
    "sinon": "^1.17.6",
    "stream-to-array": "^2.3.0"
  }
}
  

Обновление: Для решения предлагаемого решения по удалению раздела volumes из docker-compose.yml: Раздел volumes является важной частью этой настройки и позволяет моему локальному хосту обмениваться файлами с запущенным образом docker во время разработки, за исключением node_modules, которые находятся только в образе; смотрите Связанную статью для полного объяснения. Ничего не стоит, что я использовал эту настройку с этими инструкциями volume с момента запуска этого проекта, и есть по крайней мере дюжина других модулей узла, которые были установлены таким же образом, и они не вызывают исключения — если я удаляю eval , код работает.

Обновление 17 ноября 2016: Казалось, что это исправилось само собой; после переключения передач на проект с более высоким приоритетом в течение нескольких дней у меня больше не было проблемы. Я не верю в исправление ошибок самостоятельно, но я не могу понять, что я мог сделать для решения проблемы. Сегодня мне пришлось добавить новый модуль node в проект ( docker-compose -f docker-compose.yml run --rm sfsftp /bin/bash , npm install --save module изнутри запущенной оболочки, docker-compose build ), и теперь проблема вернулась, только это новый модуль, который не может быть найден.

Ответ №1:

Я столкнулся с той же проблемой и обнаружил, что решение состояло в том, чтобы удалить контейнер и затем запустить его снова, т. Е.

 npm install some-package --save

docker-compose down

docker-compose up --build
  

17 20 ноября — отредактировал вышесказанное, чтобы сделать его более кратким

Комментарии:

1. В частности, мне нужно было отключить перед сборкой.

2. ооо, ты спас мой день

3. Я не могу этого достаточно поддержать! Я был в тупике целый день по этому поводу.

Ответ №2:

Проблема в том, что node_modules том в файле compose установлен как анонимный, анонимные тома сохраняются при воссоздании контейнеров, даже при --build том, что узел все еще не может найти недавно добавленный модуль. Смотрите проблемы здесь.

На данный момент я использую эти две команды, чтобы заставить его работать, поскольку docker-compose версии v1.9 с ведьмой—renew-anon-volumes, которую, я думаю, следует использовать для решения этой ситуации, официально еще не выпущена:

 docker-compose down
docker-compose up --build
  

Ответ №3:

Раздел volumes отсутствует в docker run том, который работал:

   volumes:
    - .:/home/app/sfsftp
    - /home/app/sfsftp/node_modules
  

Я рекомендую попробовать точно имитировать то, docker run что сработало в docker-compose.yml файле. Это удаляет раздел volumes.

Если удаление раздела volumes работает, значит, что-то, что у вас есть или чего не хватает на вашем хосте, вызывает проблему при монтировании.

Также я рекомендую обновить ваш файл до version: '2' . Docker compose странно ведет себя с файлами версии 1.

Надеюсь, это поможет

Комментарии:

1. Спасибо @carlos-rafael-ramirez, но тома являются предполагаемой частью настройки, которая ранее работала; подробности см. в моем добавленном примечании в конце моего вопроса.

2. Проблема не в объемах, а в содержимом. Если вы удалили раздел volumes и все сработало, теперь вы знаете, в чем проблема. Что-то, что вы изменяете, вводя файлы со своего хоста.

Ответ №4:

В моем случае docker-compose down не помогает, поэтому мне нужно удалить том вручную.

Использование docker volume ls для перечисления всех томов, а затем docker volume rm $VOLUME_ID для удаления anonymous томов

Кроме того, вы должны назвать свой node_modules том, чтобы он был указан в docker volume ls

 services: 
  sfsftp:
    ...
    volumes:
      - .:/home/app/sfsftp
      - node_modules:/home/app/sfsftp/node_modules

volumes:
  node_modules:


  

Ответ №5:

Я столкнулся с ошибкой модуль bash не найден, когда я пытался контейнеризировать изображение на основе alpine с помощью bash с помощью command bash -c "my commands" , а затем я узнал, что bash обычно не устанавливается в изображениях на основе alpine, поэтому мне пришлось переключиться на sh, и команда становится sh -c "my commands"