Docker Compose: comparte un volumen con nombre entre varios contenedores

107

Estoy usando docker-compose y v3. Estoy intentando montar un volumen en la ventana acoplable:

./appdata:/appdata

Me gustaría tener esto como un volumen y luego hacer referencia a ese volumen desde varios contenedores. La referencia de configuración del volumen solo se muestra data-volume:como un volumen con nombre, sin valor, por lo que no se parece al anterior.

services:

    nginx:
        build: ./nginx/
        ports:
            - 80:80
        links:
            - php
        volumes:
            - app-volume

    php:
        build: ./php/
        expose:
            - 9000
        volumes:
            - app-volume

volumes:
     app-volume: ./appdata:/appdata

Esto me da:

ERROR: En el archivo './docker-compose.yml', el volumen 'app-volume' debe ser una asignación, no una cadena.

Obviamente, sé que necesito cambiar el volumespar clave / valor, pero no estoy seguro de cómo cambiar esto para poder compartir un volumen entre servicios.

También lo he comprobado, volumes_frompero esto efectivamente solo permite la herencia de otros contenedores. He visto a alguien usar volumes_fromen otro contenedor que contiene el mapeo que desea, pero con el command: trueconjunto para que el contenedor nunca se ejecute realmente, lo que a mí me parece un truco.

¿Cómo puedo hacer esto?


Tenga en cuenta, que no tienen el siguiente trabajo:

nginx:
    volumes:
        - ./appdata:/appdata
php:
    volumes:
        - ./appdata:/appdata

Pero eso es solo una duplicación y es algo que espero que un volumen con nombre pueda ayudarme a evitar :-)

Jimbo
fuente
Puede encontrar la respuesta en esta respuesta: stackoverflow.com/a/49920624
Isen Ng

Respuestas:

141

Los volúmenes nombrados se pueden compartir entre contenedores de la siguiente manera:

services:
    nginx:
        build: ./nginx/
        ports:
            - 80:80
        links:
            - php
        volumes:
            - app-volume:location_in_the_container

    php:
        build: ./php/
        expose:
            - 9000
        volumes:
            - app-volume:location_in_the_container

volumes:
     app-volume: 

Aquí hay una configuración de ejemplo que utilizo para una mejor comprensión. Estoy exponiendo los archivos estáticos generados desde mi webcontenedor a un volumen con nombre llamado static-contentque luego es leído y servido por el nginxcontenedor:

services:
  nginx:
    container_name: nginx
    build: ./nginx/

    volumes:
      - static-content:/usr/src/app

  web:
    container_name: web
    env_file: .env
    volumes:
      - static-content:/usr/src/app/public
    environment:
      - NODE_ENV=production

    command: npm run package

volumes:
  static-content:
Kannaj
fuente
79
¿Dónde establece la ubicación de static_contenten el sistema de archivos del host?
Travis Bear
10
El espacio en blanco app-volume: location_in_the_containeres incorrecto.
Hasufell
4
¿Qué pasa si /usr/src/appen el nginxcontenedor y /usr/src/app/publicen el webcontenedor ambos tienen contenido original, cuál se usará y por qué?
jallen0927
2
@TravisBear para este caso de uso (compartir datos entre contenedores) no es realmente necesario tenerlo en el host. El ejemplo con datos estáticos es excelente: ejecuta collectstaticen un contenedor y desea que los resultados estén disponibles en otro, pero no le importa la carpeta del host
El Padrino
7
La pregunta de @Kannaj TravisBear es la que identifica correctamente el problema que encuentro más confuso. ¿Cómo se puede especificar en el archivo de redacción de dónde proviene el volumen nombrado? No quiero dejar que el motor de la ventana acoplable determine dónde almacenar el volumen nombrado en el host, quiero especificar una ruta.
Ben Collins
33

Esto lo resuelve sin usar volúmenes con nombre:

      volumes:
          - ./appdata:/appdata

Entonces, se ve así:

services:

  nginx:
      build: ./nginx/
      ports:
          - 80:80
      links:
          - php
      volumes:
          - ./appdata:/appdata

  php:
      build: ./php/
      expose:
          - 9000
      volumes:
          - ./appdata:/appdata
Robert
fuente
4
¡Ah, buen momento! Hice esto arriba (vea mi cambio). Sin embargo, parece que todavía estamos duplicando el mapeo. Si utilizo esto en 3 contenedores, se agranda. ¿Podemos usar contenedores con nombre para evitar esta duplicación?
Jimbo
El caso es que los volúmenes con nombre no se trata solo de sintaxis y código claro. Creará un volumen dentro del directorio de instalación de datos de la ventana acoplable y no tendrá sus archivos locales allí (el ./appdata). ¿Es útil para ti de todos modos?
Robert
1
Definitivamente necesito el ./appdata, eso es lo que estoy tratando de hacer. Sin embargo, deje esta respuesta aquí :) +1
Jimbo
2
¿Qué sucede si tengo dos contenedores de la misma imagen, cargando un archivo (a través del servicio de carga de archivos) en un contenedor, estará disponible en el otro? si no, ¿cómo puedo hacer eso?
magnoz
0

Los volúmenes con nombre de la ventana acoplable se eliminaron a partir de la versión docker-compose 3.

Sin embargo, puede usar campos de extensión para evitar la duplicación de la fuente de los volúmenes y evitar futuros errores tipográficos:

version: '3.5'

x-services-volume:
  &services-volume
  type: bind
  source: ./appdata
  target: /appdata

services:

    nginx:
        build: ./nginx/
        ports:
            - 80:80
        links:
            - php
        volumes: *services-volume

    php:
        build: ./php/
        expose:
            - 9000
        # Use same way as for nginx if target override not needed.
        volumes:
            - <<: *services-volume
            target: /opt/target-override

NOTA: Esa función está disponible a partir del formato de archivo de la versión 3.4.

Andriy Ivaneyko
fuente
Si el * services-volume es solo un puntero al valor establecido anteriormente, esto se ve increíble ... tendré que probarlo.
Jimbo
@Jimbo sí, lo es, también tenga en cuenta que la versión del archivo docker-compose será 3.4+
Andriy Ivaneyko
2
Los volúmenes con nombre, también conocidos como el volumescampo de nivel superior , parecen ser todavía algo en la versión 3 dedocker-compose .
Alex Povel