#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"