2

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'.

Shubham Chaudhary
  • 47,722
  • 9
  • 78
  • 80
  • why don't you use ssh into the container? then you can sync whatever you need – Edwin Aug 09 '17 at 13:31
  • @Edwin Can you please elaborate? My whole point of using docker is to automate my environment. Where does sshing into the container come into the picture? – Shubham Chaudhary Aug 09 '17 at 13:46
  • the thing is that is not very clear what do you want to achieve and how your environment is set. If you have just a problem with the cached copy you can use by build `--no-cache`. Until now I got just that you have a container with your server + app and then your local files and you want to sync the code just when `docker-compose up ...` is ran. Is this right? – Edwin Aug 09 '17 at 14:24
  • @Edwin I have a src folder 'webapp' that i want to mount from host as ro, but my app wants to write to a subfolder 'webapp/node_modules'. I need a way to fulfil this somehow in docker. – Shubham Chaudhary Aug 09 '17 at 16:55
  • Related: https://stackoverflow.com/questions/37883895/can-i-have-a-writable-docker-volume-mounted-under-a-read-only-volume – Shubham Chaudhary Aug 10 '17 at 04:40

3 Answers3

3

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:

Shubham Chaudhary
  • 47,722
  • 9
  • 78
  • 80
0

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.

Ayushya
  • 9,599
  • 6
  • 41
  • 57
  • That doesn't seem to be the case. Please see https://gist.github.com/shubhamchaudhary/d7d42b8bcb6d60b1fa77c2e7ef33c07d. Here the changes I made in the container, persisted in local, even after I stopped the container. – Shubham Chaudhary Aug 09 '17 at 13:11
  • Well thats the expected behavior. You mounted volumes inside container, and then modified content inside that volume. Since those volumes were mounted, they immediately reflected those changes. What else should have happened? – Ayushya Aug 09 '17 at 13:20
  • I understant that it is the expected behaviour. But my use case is that "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." – Shubham Chaudhary Aug 09 '17 at 13:23
  • I think you want that those changes should remain internal to container. If you want those changes to not be visible to user you should use internal docker volumes. I know how it is done in docker-compoose and am sure that there is some way to implement that in dockerfile as well – Ayushya Aug 09 '17 at 13:25
  • I'm using docker-compose with these, but how can I mount a volume of source as read-only, but still have writable sub-directories in that mount. – Shubham Chaudhary Aug 09 '17 at 13:26
  • I've made changes to my answer, please check – Ayushya Aug 09 '17 at 13:36
  • 1
    Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/151502/discussion-between-shubham-chaudhary-and-ayushya). – Shubham Chaudhary Aug 09 '17 at 13:39
0

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.
Ralf Stubner
  • 26,263
  • 3
  • 40
  • 75
  • I can do this, i did this, but then i also have to mount more files like package.json etc. That doesn't feel right. – Shubham Chaudhary Aug 09 '17 at 16:59
  • Also if I copy the entire ` webapp` folder, it becomes a pain to update the image. On my system, it always picks from the cache, even if the host directory's contents have changed. – Shubham Chaudhary Aug 10 '17 at 05:27
  • 1
    `COPY` using the cache when the files have changed fits neither the [documentation](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#build-cache) nor my experience. Maybe you create a new question for that including a minimal example. – Ralf Stubner Aug 10 '17 at 08:32
  • Hmmm, looking at the documentation, that is the behavior I desire, but that is not what is happening. I'll look into it more and see if I can make the error reproducible, if so, I'll create a new issue. --no-cache is fine, but that removes the cache for everything. That is something I want to avoid, since base images take a lot of time. If I want to disable cache, I'd like to disable it only for copy step and steps followed by that. – Shubham Chaudhary Aug 11 '17 at 04:33