node.jsdockerdocker-composedockerfile

I am attempting to use Docker for a project that uses 3 containers (node, php, sql). The node part gets the following exception


I am attempting to use docker for the first time and I have figured out how to make the sql and the php containers work. But, I continue to get the same exception with my nodejs.

My code follows the following format: Customer-side written using nodejs and Vendor-side written using php

node-1    | node:internal/modules/cjs/loader:1143
node-1    |   throw err;
node-1    |   ^
node-1    |
node-1    | Error: Cannot find module '/app/customer/index.js'
node-1    |     at Module._resolveFilename (node:internal/modules/cjs/loader:1140:15)
node-1    |     at Module._load (node:internal/modules/cjs/loader:981:27)
node-1    |     at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:128:12)
node-1    |     at node:internal/main/run_main_module:28:49 {
node-1    |   code: 'MODULE_NOT_FOUND',
node-1    |   requireStack: []
node-1    | }
node-1    |
node-1    | Node.js v18.20.5

My code makes use of the following docker-compose

services:

  node:
    build:
      context: .
      dockerfile: Dockerfile.nodejs
    volumes:
      - ./customer:/app
      - /customer/node_modules
      - shared-package:/usr/src/app/shared
    depends_on:
      - mysql
    ports:
      - "3000:3000"
  apache:
    build:
      context: .
      dockerfile: Dockerfile.apache
    volumes:
      - ./vendor:/var/www/html
      - shared-package:/var/www/html/shared
    depends_on:
      - mysql
    ports:
      - "8080:80"

  mysql:
    image: mysql
    environment:
        MYSQL_ROOT_PASSWORD: root
    volumes:
      - ./mysql-data:/var/lib/mysql
    ports:
      - "3306:3306"

volumes:
  shared-package:
    driver: local

And this is my dockerfile.nodejs

FROM node:18-alpine

WORKDIR /app



COPY ./customer .
RUN npm install

WORKDIR /app/customer
EXPOSE 3000

CMD ["node", "index.js"]

File Structure This is a photo of my file structure


Solution

  • In the Dockerfile, the final WORKDIR line is wrong and you should delete it.

    WORKDIR /app
    COPY ./customer .
    # WORKDIR /app/customer  # delete this one
    

    Since the left-hand side of COPY is a directory, its contents are copied into the destination directory (which is the current container working directory, which is /app). The image filesystem has an /app/index.js file but not a /app/customer subdirectory.

    You can verify this by running docker-compose run node ls /app to launch a temporary container to see what's in the container filesystem.

    I'd also recommend deleting almost all of the volumes: blocks in the Compose file, except for the mysql container. Your code is already built into your image and you don't need to separately inject it; it can lead to reproducibility problems if you have code on your local system that isn't built into the image for whatever reason. The mix of container paths on the right-hand side of volumes: also doesn't look right to me and that can lead to further unexpected problems.