node.jsdockerdocker-composedockerfiledocker-command

docker-compose create volume of my app folder and run node command in it


Docker beginner here.

I am trying to set up docker for local development. My ultimate goal is to be able to use "vite" to do hot module reloading development server.

Here's what I am trying:

#docker-compose.yml
version: '3.8'
services:
  mpvdb:
    image: mysql:5.7
    restart: unless-stopped
    environment:
      - MYSQL_ROOT_PASSWORD=123456
      - MYSQL_DATABASE=cicd
    ports:
      - 3307:3306
    volumes:
      - db:/var/lib/mysql
      - ./mysql-dump:/docker-entrypoint-initdb.d
  mvpnode:
    image: node:18.1.0
    ports:
      - 4444:4444
    volumes:
      - type: volume
        source: client
        target: /client
    command: sh -c "cd ./client && npm run start"
volumes:
  db:
  client:

Note that I have folder in my repo called client I want to have this folder be accessible to the node container so that if I make a change to it the vite dev server (started via npm run start) will detect changes and do its thing, ultimately serving an app to port 4444.

The issue I am facing is either in my attempt to establish the client volume or in my command script. When I try to run the command and start the server I get the following:

mvpnode_1  | npm ERR! code ENOENT
mvpnode_1  | npm ERR! syscall open
mvpnode_1  | npm ERR! path /client/package.json
mvpnode_1  | npm ERR! errno -2
mvpnode_1  | npm ERR! enoent ENOENT: no such file or directory, open '/client/package.json'
mvpnode_1  | npm ERR! enoent This is related to npm not being able to find a file.
mvpnode_1  | npm ERR! enoent

Firstly, how can I change my yml file to make this work?

Secondly, is my assumption that the container will maintain a connection to the /server folder on my windows filesystem correct? So that if I change the code in the application it will be reflected in the container's volume? Or is this wrong and it caches a copy of the code when I spin up the container? I have found conflicting information about this online.

Thanks!


Solution

  • I think your issue is that you're using a docker volume. A docker volume is a piece of storage managed by docker. What you usually want when you're doing development with hot reload is a bind mount which lets the container access a part of the host's file system. With hot reload, you make a bind mount to the place where you keep your source code.

    If your source code is in a client directory below the directory with the docker-compose file, you can do

    version: '3.8'
    services:
      mpvdb:
        image: mysql:5.7
        restart: unless-stopped
        environment:
          - MYSQL_ROOT_PASSWORD=123456
          - MYSQL_DATABASE=cicd
        ports:
          - 3307:3306
        volumes:
          - db:/var/lib/mysql
          - ./mysql-dump:/docker-entrypoint-initdb.d
      mvpnode:
        image: node:18.1.0
        ports:
          - 4444:4444
        volumes:
          - ./client:/client
        command: sh -c "cd /client && npm install && npm run start"
    volumes:
      db:
    

    You should also add npm install to the commands run on startup, since you need to have the relevant node modules installed before starting the app.