438

I have a development environment I'm dockerizing and I would like the ability to livereload my changes without having to rebuild docker images. I'm using docker compose because redis is one of my app's dependencies and I like being able to link a redis container

I have two containers defined in my docker-compose.yml:

node: build: ./node links: - redis ports: - "8080" env_file: - node-app.env redis: image: redis ports: - "6379" 

I've gotten to the point in my node app's dockerfile where I add a volume, but how do I mount the the host's directory in the volume so that all my live edits to the code are reflected in the container?

Here's my current Dockerfile:

# Set the base image to Ubuntu FROM node:boron # File Author / Maintainer MAINTAINER Amin Shah Gilani <[email protected]> # Install nodemon RUN npm install -g nodemon # Add a /app volume VOLUME ["/app"] # TODO: link the current . to /app # Define working directory WORKDIR /app # Run npm install RUN npm install # Expose port EXPOSE 8080 # Run app using nodemon CMD ["nodemon", "/app/app.js"] 

My project looks like this:

/ - docker-compose.yml - node-app.env - node/ - app.js - Dockerfile.js 

8 Answers 8

463

Checkout their documentation

From the looks of it you could do the following on your docker-compose.yml

volumes: - ./:/app 

Where ./ is the host directory, and /app is the target directory for the containers.


EDIT:
Previous documentation source now leads to version history, you'll have to select the version of compose you're using and look for the reference.

For the lazy – v3 / v2 / v1

Side note: Syntax remains the same for all versions as of this edit

Sign up to request clarification or add additional context in comments.

10 Comments

Tried it, it didn't work: Error: Cannot find module '/data/app.js'
wait.. your VOLUME and WORKDIR points to /app/ why is your CMD pointing to /data
That was an error! Thank you for catching that! Fixed, and now I get Error: Cannot find module 'express' I'm gonna try a few things now.
For windows containers, you'll want a windows style path like - .:c:/app (this tripped me up)
Side note. If you need to mount 1 dir above the host dir, just use standard .. syntax: - ../:/app works on Linux containers and - ..\:\app works on Windows containers. At least it works with Docker engine 20.10.11 for me.
|
296

There are a few options for writing this in the volumes attribute within services.

Short syntax

Using the host:guest short syntax you can do any of the following:

 volumes: # Just specify a path and let the Engine create a volume - /var/lib/mysql # Specify an absolute path mapping - /opt/data:/var/lib/mysql # Path on the host, relative to the Compose file - ./cache:/tmp/cache # User-relative path; `:ro` makes it read-only - ~/configs:/etc/configs/:ro # Named volume - datavolume:/var/lib/mysql 

Long syntax

In 2017, docker-compose was updated to support long syntax for a service’s volumes. With this syntax, you explicitly specify the type of mount (volume, bind or tmpfs) and label the source and the target. This syntax also allows the configuration of additional fields that can’t be expressed in the short syntax.

services: web: image: nginx:alpine ports: ["80:80"] volumes: - type: volume source: mydata target: /data # nocopy has no equivalent in the short syntax: volume: nocopy: true - type: bind source: ./static target: /opt/app/static volumes: mydata: 

The long syntax behaves like Docker’s --mount flag, while the short syntax behaves like the older -v flag. This means the long syntax behaves differently from the short syntax when the bind mount source does not yet exist on the Docker host.

1 Comment

To add to your answer, there are also :cached and :delegated annotations in the short syntax. These matter if the host is Docker Desktop for Mac. They are documented in docker-docs.netlify.app/docker-for-mac/osxfs-caching but unfortunately not in the Docker Compose docs.
138

If you would like to mount a particular host directory (/disk1/prometheus-data in the following example) as a volume in the volumes section of the Docker Compose YAML file, you can do it as below, e.g.:

version: '3' services: prometheus: image: prom/prometheus volumes: - prometheus-data:/prometheus volumes: prometheus-data: driver: local driver_opts: o: bind type: none device: /disk1/prometheus-data 

By the way, in prometheus's Dockerfile, You may find the VOLUME instruction as below, which marks it as holding externally mounted volumes from native host, etc. (Note however: this instruction is not a must though to mount a volume into a container.):

Dockerfile

... VOLUME ["/prometheus"] ... 

Refs:

9 Comments

This worked. Thanks. Where is the documentation for the local driver type?
@mmell, you can find more details from this question: stackoverflow.com/questions/42195334/…
How did you know the settings in driver_opts: o: bind type: none?
@mmell Basically, those options are driver-dependent, and the built-in local driver on Linux accepts options similar to the linux mount command: man7.org/linux/man-pages/man8/mount.8.html. You can find more discussion at github.com/moby/moby/issues/19990#issuecomment-248955005, and stackoverflow.com/questions/35841241/…
This answer should be the accepted one for a separate question about how to mount a host directory across multiple containers; twas hard to find this!
|
21

It was two things:

I added the volume in docker-compose.yml:

node: volumes: - ./node:/app 

I moved the npm install && nodemon app.js pieces into a CMD because RUN adds things to the Union File System, and my volume isn't part of UFS.

# Set the base image to Ubuntu FROM node:boron # File Author / Maintainer MAINTAINER Amin Shah Gilani <[email protected]> # Install nodemon RUN npm install -g nodemon # Add a /app volume VOLUME ["/app"] # Define working directory WORKDIR /app # Expose port EXPOSE 8080 # Run npm install CMD npm install && nodemon app.js 

Comments

19

we have to create your own docker volume mapped with the host directory before we mention in the docker-compose.yml as external

1.Create volume named share

docker volume create --driver local \ --opt type=none \ --opt device=/home/mukundhan/share \ --opt o=bind share 

2.Use it in your docker-compose

version: "3" volumes: share: external: true services: workstation: container_name: "workstation" image: "ubuntu" stdin_open: true tty: true volumes: - share:/share:consistent - ./source:/source:consistent working_dir: /source ipc: host privileged: true shm_size: '2gb' db: container_name: "db" image: "ubuntu" stdin_open: true tty: true volumes: - share:/share:consistent working_dir: /source ipc: host 

This way we can share the same directory with many services running in different containers

2 Comments

why do I need to have ipc: host ?
that is only needed when we need to bind the network into host itself.
16

In docker-compose.yml you can use this format:

volumes: - host directory:container directory 

according to their documentation

2 Comments

Does this volume belongs to services section or stand alone section?
It should be indented under services.
7

Sharing redis golang docker-compose.yaml. Using bind-mount I've achieved it.

version: '3.0' services: redisdb: image: redis:6.0 restart: always ports: - "6379:6379" container_name: redisdb-container command: ["redis-server", "--bind", "redisdb", "--port", "6379"] urlshortnerservice: depends_on: - redisdb ports: - "7777:7777" restart: always container_name: url-shortner-container image: url-shortner-service volumes: - ../pkg/repository/filestorage:/pkg/repository/filestorage #host directory:container directory 

Comments

3

Here is my working example for Node.js application and MongoDB database :

docker-compose.yml

version: '3' services: my-app: container_name: my-app-container restart: always build: . volumes: - './storage:/usr/src/app/storage' ports: - "3000:3000" links: - my-app-db my-app-db: container_name: my-app-db-container image: mongo restart: always volumes: - './data:/data/db' ports: - "27017:27017" 

Dockerfile

FROM node:16.13.2 RUN mkdir -p /usr/src/app WORKDIR /usr/src/app COPY package.json ./ RUN npm install COPY . /usr/src/app/ EXPOSE 3000 CMD [ "npm", "start"] 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.