Docker build IMAGE приводит к ошибке, но docker-compose up -d работает нормально

Я новичок в докере. Я пытаюсь создать образ Docker для проекта NodeJS, который я буду загружать / размещать в хранилище Docker. Когда я выполняю docker-compose up -d все работает нормально, и я могу получить доступ к серверу nodeJS, который находится внутри контейнеров Docker. После этого я остановил все контейнеры и попытался создать образ Docker из файлов Docker, используя следующие команды:

docker build -t adonis-app .
docker run adonis-app

Первая команда выполняется без ошибок, но вторая команда выдает эту ошибку:

> adonis-fullstack-app@4.1.0 start /app
> node server.js

internal/modules/cjs/loader.js:983
  throw err;
  ^

Error: Cannot find module '/app/server.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:980:15)
    at Function.Module._load (internal/modules/cjs/loader.js:862:27)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! adonis-fullstack-app@4.1.0 start: `node server.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the adonis-fullstack-app@4.1.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /app/.npm/_logs/2020-02-09T17_33_22_489Z-debug.log

Может кто-нибудь помочь мне с этой ошибкой и сказать, что с ней не так?

Dockerfile Я использую:

FROM node

ENV HOME=/app
RUN mkdir /app

ADD package.json $HOME

WORKDIR $HOME

RUN npm i -g @adonisjs/cli && npm install

CMD ["npm", "start"]

докер-compose.yaml

version: Ɖ.3'

services:
  adonis-mysql:
    image: mysql:5.7
    ports:
      - 񠁚:3306'
    volumes:
      - $PWD/data:/var/lib/mysql
    environment:
      MYSQL_USER: ${DB_USER}
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_RANDOM_ROOT_PASSWORD: 1
    networks:
      - api-network
  adonis-api:
    container_name: "${APP_NAME}-api"
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/app
      - /app/node_modules
    ports:
      - "3333:3333"
    depends_on:
      - adonis-mysql
    networks:
      - api-network

networks: 
  api-network:

Всего 2 ответа


В вашем Dockerfile отсутствует шаг COPY чтобы фактически скопировать код вашего приложения в изображение. Когда вы docker run образ, нет исходного кода для запуска, и вы получаете сообщение об ошибке.

Ваш Dockerfile должен выглядеть так:

FROM node
WORKDIR /app     # creates the directory; no need to set $HOME
COPY package.json package.lock .
RUN npm install  # all of your dependencies are in package.json
COPY . .         # actually copy the application in
CMD ["npm", "start"]

Теперь, когда ваш образ Docker является автономным, вам не нужны volumes: которые пытаются внедрить в него содержимое хоста. Вы также можете смело полагаться на некоторые настройки Docker Compose по умолчанию (сеть по default и сгенерированное имя_ container_name: оба прекрасно подходят для использования). Более простой docker-compose.yml выглядит так

version: Ɖ.3'    
services:
  adonis-mysql:
    image: mysql:5.7
    # As you have it, except delete the networks: block
  adonis-api:
    build: .   # this directory is context:, use default dockerfile:
    ports:
      - "3333:3333"
    depends_on:
      - adonis-mysql

В наборе артефактов и команд, которые вы показываете, есть несколько ключевых проблем:

docker run и docker-compose ... - это отдельные команды. В показанной вами команде docker run образ запускается как есть, с командой по умолчанию, без смонтированных томов и без опубликованных портов. docker run не знает о файле docker-compose.yml , поэтому любые параметры, которые вы там указали, не будут иметь docker-compose.yml эффекта. Вы можете иметь в виду docker-compose up , который также запустит базу данных. (В вашем приложении не забудьте попробовать несколько раз, чтобы оно появилось, часто это может занять 30-60 секунд.)

Если вы планируете нажать на изображение, вам нужно включить исходный код. По сути, вы создаете два отдельных артефакта в этой настройке: образ Docker с Node и некоторыми библиотеками, а также приложение Javascript на вашем хосте. Если вы docker push изображение в Docker, оно не будет включать приложение (потому что вы не COPY его), поэтому вам также придется отдельно распространять исходный код. На этом этапе использование Docker не приносит большой пользы; конечный пользователь может также установить Node, клонировать ваш репозиторий и запустить npm install самостоятельно.

Вы запрещаете Docker видеть обновления библиотеки. node_modules в анонимном томе, кажется, является популярной установкой, и Docker будет копировать содержимое из образа в этот каталог при первом запуске приложения. Во второй раз, когда вы запускаете приложение, Docker видит, что каталог уже существует, предполагает, что он содержит ценные пользовательские данные, и отказывается обновлять его. Это приводит к таким вопросам, как «я обновил свой файл package.json но мой контейнер не обновляется».


Ваш файл docker-compose.yaml имеет две службы:

  1. Адонис-MySQL
  2. Адонис-апи

Только второй элемент использует текущий файл Docker. Как видно из следующего раздела:

build:
      context: .
      dockerfile: Dockerfile

docker build . командной docker build . создаст образ только в текущем файле докера aka adonis-api. И тогда он запускается.

Поэтому, скорее всего, это может быть отсутствующий сервис mysql, который выдает ошибку. Вы можете проверить, запустив

docker ps -aq

проверить, запущен ли контейнер sql. Надеюсь, это поможет.

Вывод: используйте docker-compose.


Есть идеи?

10000