Docker - "Missing script: "dev"" - But it's there?

Viewed 704

I'm using Docker Compose for a React/Express application.

Dockerfile for the server:

FROM node:latest 
WORKDIR /app/server 
COPY package.json /app/server
COPY package-lock.json /app/server 
RUN npm install 
COPY . /app/server
CMD [ "npm", "run", "dev" ]

Dockerfile for the client:

FROM node:latest
WORKDIR /app/client
COPY package.json /app/client
COPY package-lock.json /app/client
RUN npm install
COPY . /app/client
CMD [ "npm", "start" ]

And my docker-compose file:

version: '3' 
services:
    server:
        build: ./server
        expose: 
            - "3001"
        ports:
            - "3001:3001"
        volumes:
            - ./server/src/:/app/server
        command: npm run dev
        tty: true

    client:
        build: ./client
        expose:
            - "3000"
        ports:
            - "3000:3000"
        volumes: 
            - ./client/src/:/app/client
        links:
            - server
        command: npm run start
        tty: true

After running "docker-compose up" the server crashes:

npm ERR! Missing script: "dev"

However, I DO have a "dev" script inside my package.json:

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "nodemon index.js",
    "start": "node index.js"
  },

What is the problem here? The script is there. Is there something wrong with my Docker files? "npm run dev" works just fine without Docker.

Thanks!

2 Answers

Hmm, apparently, Docker can't find a package.json file that includes a dev script.

My first suggestion would be to ensure that package.json is in the root folder of the project, at the same folder level as the docker-compose.yml.

When your docker-compose.yml file says

volumes:
  - ./server/src/:/app/server

this hides everything the Dockerfile did in the /app/server directory and replaces it with the contents of that host directory. Since the only things your Dockerfile does are in the /app/server directory, you're essentially not using your Docker image at all.

I'd generally recommend removing these volumes:, along with some other unnecessary options. (You do not need to expose: ports in Compose pretty much ever; you do not need to repeat the command: from the image; links: are obsolete networking setup.) You can reduce the file to just

version: '3.8'
services:
    server:
        build: ./server
        ports:
            - "3001:3001"
    client:
        build: ./client
        ports:
            - "3000:3000"

If you do include volumes:, you need to make sure that the layout of the mounted content exactly matches what's supposed to be in the container. (Try running docker-compose run server ls with and without the volumes: line.) Here you're building the image from the ./server directory, but then mounting its src subdirectory over the whole application. It may work better to mount it only on the src subdirectory inside the container too

volumes:
  - ./server/src:/app/server/src
Related