Docker Compose - compartilhe o volume nomeado entre vários contêineres

107

Estou usando docker-compose e v3. Estou tentando montar um volume no docker:

./appdata:/appdata

Eu gostaria de ter isso como um volume e, em seguida, fazer referência a esse volume de vários recipientes. A referência de configuração do volume é exibida apenas data-volume:como um volume nomeado, sem nenhum valor, portanto, não se parece com o acima.

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

Isso me dá:

ERRO: No arquivo './docker-compose.yml', o volume 'app-volume' deve ser um mapeamento, não uma string.

Obviamente, sei que preciso alterar o volumespar chave / valor, mas não tenho certeza de como alterar isso para que possa compartilhar um volume entre os serviços.

Eu também verifiquei, volumes_frommas isso efetivamente apenas permite a herança de outros contêineres. Eu vi alguém usar volumes_fromem outro contêiner que contém o mapeamento que eles querem, mas com command: truedefinido para que o contêiner nunca seja realmente executado, o que para mim parece um hack.

Como posso fazer isso?


Note, eu não tenho o seguinte trabalho:

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

Mas isso é apenas duplicação e é algo que espero que um volume nomeado possa me ajudar a evitar :-)

Jimbo
fonte
Você pode encontrar a resposta nesta resposta: stackoverflow.com/a/49920624
Isen Ng

Respostas:

141

Os volumes nomeados podem ser compartilhados entre contêineres da seguinte maneira:

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: 

Aqui está um exemplo de configuração que uso para melhor compreensão. Estou expondo os arquivos estáticos gerados do meu webcontêiner a um volume nomeado chamado static-contentque é então lido e servido pelo nginxcontêiner:

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
fonte
79
Onde você define a localização static_contentno sistema de arquivos do host?
Travis Bear
10
O espaço em branco app-volume: location_in_the_containerestá errado.
hasufell
4
E se /usr/src/appno nginxcontainer e /usr/src/app/publicno webcontainer ambos tivessem conteúdo original, qual será usado e por quê?
jallen0927
2
@TravisBear para este caso de uso (compartilhamento de dados entre contêineres), não há realmente necessidade de tê-lo no host. O exemplo com dados estáticos é ótimo - você executa collectstaticem um contêiner e deseja que os resultados estejam disponíveis em outro, mas não se preocupa com a pasta do host
The Godfather
7
A pergunta de @Kannaj TravisBear é a que identifica corretamente o problema que considero mais confuso. Como no arquivo de composição você pode especificar onde o volume nomeado é originado? Não quero deixar que o mecanismo do docker determine onde armazenar o volume nomeado no host, quero especificar um caminho.
Ben Collins,
33

Isso resolve sem usar volumes nomeados:

      volumes:
          - ./appdata:/appdata

Então, parece:

services:

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

  php:
      build: ./php/
      expose:
          - 9000
      volumes:
          - ./appdata:/appdata
Robert
fonte
4
Ah, bom momento! Eu fiz isso acima (veja minha mudança). No entanto, parece que ainda estamos duplicando o mapeamento. Se eu usar isso em 3 recipientes, fica grande. Podemos usar contêineres nomeados para evitar essa duplicação?
Jimbo
O fato é que os volumes nomeados não são apenas sobre sintaxe e código claro. Isso criará um volume dentro do diretório de instalação de dados do docker e você não terá seus arquivos locais lá (o ./appdata). É útil para você de qualquer maneira?
Robert
1
Definitivamente preciso ./appdata, é isso que estou tentando fazer. Deixe esta resposta aqui :) +1
Jimbo
2
O que acontece se eu tiver dois containers da mesma imagem, fazendo upload do arquivo (via serviço de upload de arquivo) em um container, ele estará disponível no outro? se não, como posso fazer isso?
magnoz
0

Os volumes nomeados do docker foram removidos a partir da versão docker-compose 3.

No entanto, você pode usar campos de extensão para evitar a duplicação da fonte de volumes e evitar erros de digitação futuros:

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: Esse recurso está disponível a partir do formato de arquivo da versão 3.4.

Andriy Ivaneyko
fonte
Se o * volume de serviços for apenas um ponteiro para o valor definido acima, isso parece incrível ... Vou ter que tentar.
Jimbo
@Jimbo sim, é, também observe que a versão do arquivo docker-compose será 3.4+
Andriy Ivaneyko
2
Volumes nomeados, também conhecidos como o volumescampo de nível superior , parecem ainda ser uma coisa na v3 dedocker-compose .
Alex Povel