¿Cómo puedo montar un directorio de host como un volumen en Docker compose?

125

Tengo un entorno de desarrollo que estoy acoplando y me gustaría tener la capacidad de recargar en vivo mis cambios sin tener que reconstruir las imágenes de la ventana acoplable. Estoy usando docker compose porque redis es una de las dependencias de mi aplicación y me gusta poder vincular un contenedor de redis

Tengo dos contenedores definidos en mi docker-compose.yml:

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

redis:
    image: redis
    ports:
        - "6379"

Llegué al punto en nodeel dockerfile de mi aplicación en el que agrego un volumen, pero ¿cómo puedo montar el directorio del host en el volumen para que todas mis ediciones en vivo del código se reflejen en el contenedor?

Aquí está mi Dockerfile actual:

# 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"]

Mi proyecto se ve así:

/
- docker-compose.yml
- node-app.env
- node/
  - app.js
  - Dockerfile.js
Amin Shah Gilani
fuente

Respuestas:

137

Consulte su documentación

Por lo que parece, puede hacer lo siguiente en su docker-compose.yml

volumes:
    - ./:/app
jkris
fuente
2
Lo intenté, no funcionó:Error: Cannot find module '/data/app.js'
Amin Shah Gilani
2
espera ... tu VOLUME y WORKDIR apuntan a /app/por qué tu CMD apunta a/data
jkris
1
¡Eso fue un error! ¡Gracias por captar eso! Arreglado, y ahora lo entiendo Error: Cannot find module 'express'. Voy a intentar algunas cosas ahora.
Amin Shah Gilani
3
Para los contenedores de Windows, querrá una ruta de estilo de Windows como - .:c:/app(esto me hizo tropezar)
JohnnyFun
86

Hay algunas opciones

Sintaxis corta

Con el host : guestformato, puede realizar cualquiera de las siguientes acciones:

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
  - ~/configs:/etc/configs/:ro

  # Named volume
  - datavolume:/var/lib/mysql

Sintaxis larga

A partir de docker-compose v3.2, puede usar una sintaxis larga que permite la configuración de campos adicionales que se pueden expresar en forma corta, como mount type(volumen, vinculación o tmpfs) y read_only.

version: "3.2"
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - type: volume
        source: mydata
        target: /data
        volume:
          nocopy: true
      - type: bind
        source: ./static
        target: /opt/app/static

networks:
  webnet:

volumes:
  mydata:

Consulte https://docs.docker.com/compose/compose-file/#long-syntax-3 para obtener más información.

GreensterRox
fuente
21

Si desea montar un directorio de host en particular ( /disk1/prometheus-dataen el siguiente ejemplo) como un volumen en la volumessección del archivo YAML de Docker Compose, puede hacerlo de la siguiente manera, por ejemplo:

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

Por cierto, en el Dockerfile de prometheus, puede encontrar la VOLUMEinstrucción como se muestra a continuación, que lo marca como que contiene volúmenes montados externamente desde el host nativo, etc. (Sin embargo, tenga en cuenta: esta instrucción no es obligatoria para montar un volumen en un contenedor). :

Dockerfile

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

Refs:

Yuci
fuente
Esto funcionó. Gracias. ¿Dónde está la documentación para el localtipo de controlador?
2019
@mmell La documentación es el primer enlace Refs ( docs.docker.com/compose/compose-file/#driver ) Se lee: Especifique qué controlador de volumen debe usarse para este volumen. El valor predeterminado es cualquier controlador que el motor Docker se haya configurado para usar, que en la mayoría de los casos eslocal
Yuci
1
@mmell, puede encontrar más detalles de esta pregunta: stackoverflow.com/questions/42195334/…
Yuci
¿Cómo conociste la configuración driver_opts: o: bind type: none?
2019
1
@mmell Básicamente, esas opciones dependen del controlador, y el localcontrolador integrado en Linux acepta opciones similares al comando de montaje de linux: man7.org/linux/man-pages/man8/mount.8.html . Puede encontrar más discusiones en github.com/moby/moby/issues/19990#issuecomment-248955005 , y stackoverflow.com/questions/35841241/…
Yuci
9

Fueron dos cosas:

Agregué el volumen en docker-compose.yml:

node:
    volumes:
        - ./node:/app

Moví las npm install && nodemon app.jspiezas a un CMDporque RUNagrega cosas al sistema de archivos de la Unión, y mi volumen no es parte de 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
Amin Shah Gilani
fuente
2

tenemos que crear su propio volumen de docker mapeado con el directorio de host antes de mencionar en el docker-compose.yml como externo

1.Crear volumen denominado recurso compartido

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

2.Úselo en su 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

De esta manera podemos compartir el mismo directorio con muchos servicios que se ejecutan en diferentes contenedores.

Mukundhan
fuente
¿Por qué necesito tener ipc: host?
Vahid Noormofidi
eso solo es necesario cuando necesitamos unir la red al propio host.
Mukundhan