简体   繁体   中英

Writable node_modules with read only source files in docker

My webapp/Dockerfile looks like this:

FROM project_base-container

EXPOSE 9100

# ...

# Using copy instead of mount, since we need to write in sub-directories like node_modules etc.
COPY . /usr/src/app/webapp

CMD ["bash", "webapp/scripts/build_and_run.sh", "setup_deps_and_run_app"]

I want to allow the app to be able to read the source code and also write into sub-folders like node_modules , but I don't want those changes to come in my local machine. Hence, I have two choices:

  1. Change --prefix='/tmp' in node install and mount the src as ro
  2. Copy COPY the src and then the container can write wherever it wants.

Solution 1 wrecks havoc, because now I have to copy/link all files like package.json, index.html etc to the prefix location. Solution 2 is what I have done above.

When I use COPY everything is fine for the first time. But now the problem is that after changes in source code, I want to update the source code in the image every time I do:

sudo docker-compose down && sudo docker-compose up --build -d

But the COPY command is cached by docker and won't be updated, even after file changes.


TL;DR: I have a src folder 'webapp' that I want to mount from host as readonly, but my app wants to write to a subfolder 'webapp/node_modules'.

To create a writable mount inside a read only mount, you need to ensure that the read-only directory has the mount points (folders), even if they are empty .

To create empty mount points and commit them, please see this answer .

For running node, you need following 4 folders writable:

$ mkdir webapp/frontend/node_modules webapp/frontend/build webapp/frontend/.config webapp/frontend/.npm

$ cat > webapp/frontend/node_modules/.gitignore
# Ignore everything in this directory
*
# Except this file
!.gitignore

$ git add -f webapp/frontend/node_modules/.gitignore

$ cat docker-compose.yml  # Filtered output below
version: "2"
services:
    webapp:
        build: ./webapp
        expose:
          - "9900"
        # Named volumes, defined below.
        volumes:
          - ./webapp:/usr/src/app/webapp:ro
          - webapp_config:/usr/src/app/webapp/frontend/.config:rw
          - webapp_npm:/usr/src/app/webapp/frontend/.npm:rw
          - webapp_node_modules:/usr/src/app/webapp/frontend/node_modules:rw
          - webapp_build:/usr/src/app/webapp/frontend/build:rw
          - ./config.ini:/usr/src/app/config.ini:ro
# Named volumes. These will stay in the host, but not in the current directory.
volumes:
      webapp_node_modules:
      webapp_build:
      webapp_config:
      webapp_npm:

You can use internal docker-volumes.

version: "3"

services:

  postgres:
    image: postgres:9.4
    volumes:
      - db-data:/var/lib/db

  redis:
    image: redis
    ports:
      - "6379:6379"
    volumes:
      - ./data:/data

volumes:
  db-data:

From documentation

Explaination:

Postgress service uses a named volume and that is located inside the directory where docker is installed. For Ubuntu, it is /var/lib/docker/aufs/ . This directory may be different and can be found by using docker inspect <vulume_name> .

Redis services uses another type of volumes, the ones which are more popular and which are used to mount host directory inside container directory. The data folder is in the same directory as the one in which docker-compose.yml file is present, and this folder is mounted inside the container at /data .

Is it possible for you to store all code you want to be editable in some sub-directory (say src )? If yes, then you could do the following

  • Use COPY as you are doing now, which is probably needed for deployment anyway.
  • In addition (read-only) mount src to /usr/src/app/webapp/src during development.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM