Docker Compose - Udostępnij nazwany wolumin między wieloma kontenerami

116

Używam docker-compose i v3. Próbuję zamontować wolumin w dockerze:

./appdata:/appdata

Chciałbym mieć to jako objętość, a następnie odwoływać się do tej objętości z wielu pojemników. Referencyjna konfiguracja objętość tylko pokazuje data-volume:jak nazwanego objętości, bez wartości, więc nie wyglądają jak wyżej.

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

To daje mi:

BŁĄD: W pliku „./docker-compose.yml” wolumin „app-volume” musi być mapowaniem, a nie ciągiem.

Oczywiście wiem, że muszę zmienić volumesparę klucz / wartość, ale nie jestem pewien, jak to zmienić, aby móc dzielić wolumen między usługami.

Sprawdziłem również, volumes_fromale to skutecznie pozwala tylko na dziedziczenie z innych kontenerów. Widziałem, jak ktoś używa volumes_frominnego kontenera, który zawiera żądane mapowanie, ale zcommand: true ustawieniem, aby kontener nigdy nie był faktycznie uruchamiany, co dla mnie wydaje się po prostu włamaniem.

Jak mogę to zrobić?


Uwaga, to nie mają następującą pracę:

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

Ale to tylko powielanie i mam nadzieję, że nazwany tom mógłby mi pomóc uniknąć :-)

Jimbo
źródło
Możesz znaleźć odpowiedź w tej odpowiedzi: stackoverflow.com/a/49920624
Isen Ng

Odpowiedzi:

154

Nazwane woluminy można udostępniać w kontenerach w następujący sposób:

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: 

Oto przykładowa konfiguracja, której używam do lepszego zrozumienia. Wystawiam pliki statyczne wygenerowane z mojego webkontenera do nazwanego woluminu, static-contentktóry jest następnie odczytywany i obsługiwany przez nginxkontener:

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
źródło
80
Gdzie ustawiasz lokalizację w static_contentsystemie plików hosta?
Travis Bear
10
Białe spacje app-volume: location_in_the_containersą błędne.
hasufell
6
A co jeśli /usr/src/appw nginxkontenerze i /usr/src/app/publicw webkontenerze obie otrzymają oryginalną zawartość, która zostanie wykorzystana i dlaczego?
jallen0927
2
@TravisBear w tym przypadku użycia (udostępnianie danych między kontenerami) tak naprawdę nie ma potrzeby posiadania go na hoście. Przykład z danymi statycznymi jest świetny - wykonujesz collectstaticw jednym kontenerze i chcesz, aby wyniki były dostępne w innym, ale nie obchodzi Cię folder hosta
Ojciec chrzestny
7
Pytanie @Kannaj TravisBear jest tym, które poprawnie identyfikuje problem, który uważam za najbardziej zagmatwany. W jaki sposób w pliku redagowania można określić, skąd pochodzi nazwany wolumin? Nie chcę pozostawiać tego silnikowi dokera, aby określić, gdzie przechowywać nazwany wolumin na hoście, chcę określić ścieżkę.
Ben Collins,
35

To rozwiązuje problem bez używania nazwanych woluminów:

      volumes:
          - ./appdata:/appdata

Wygląda więc na to:

services:

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

  php:
      build: ./php/
      expose:
          - 9000
      volumes:
          - ./appdata:/appdata
Robert
źródło
4
Ach, niezłe wyczucie czasu! Zrobiłem to powyżej (zobacz moją zmianę). Wygląda jednak na to, że nadal kopiujemy mapowanie. Jeśli użyję tego powyżej 3 pojemników, zrobi się duży. Czy możemy używać nazwanych kontenerów, aby uniknąć tego powielania?
Jimbo
Rzecz w tym, że nazwane woluminy to nie tylko składnia i przejrzysty kod. Spowoduje to utworzenie woluminu w katalogu instalacyjnym danych Dockera i nie będziesz mieć tam swoich plików lokalnych (plik ./appdata). Czy jest to dla ciebie przydatne?
Robert
2
Zdecydowanie potrzebuję ./appdata, to jest to, co próbuję zrobić. Zostaw tę odpowiedź tutaj :) +1
Jimbo
3
Co się stanie, jeśli mam dwa kontenery tego samego obrazu, przesyłając plik (za pośrednictwem usługi przesyłania plików) w jednym kontenerze, będzie on dostępny w drugim? jeśli nie, jak mogę to zrobić?
magnoz
5

Docker o nazwie woluminy zostały usunięte począwszy od wersji docker-compose 3.

Możesz jednak użyć pól rozszerzeń, aby uniknąć powielania źródła woluminów i zapobiec przyszłym literówkom:

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

UWAGA: Ta funkcja jest dostępna od wersji 3.4.

Andriy Ivaneyko
źródło
Jeśli * services-volume jest tylko wskaźnikiem do wartości ustawionej powyżej, wygląda to niesamowicie ... Muszę spróbować.
Jimbo
@Jimbo tak, to jest, pamiętaj również, że wersja pliku docker-compose będzie 3.4+
Andriy Ivaneyko
2
Nazwane woluminy, czyli pola najwyższego poziomu volumes, nadal wydają się być czymś w wersji 3 programudocker-compose .
Alex Povel
Wypróbowałem dokładnie to podejście do udostępniania danych między trzema kontenerami i hostem. W moim przypadku struktury folderów w kontenerach są równe. Wygląda na to, że działa to zgodnie z oczekiwaniami. Nie dostaję, który kontener (lub host) ma uprzywilejowane prawo przy ponownym uruchomieniu? Co mam na myśli: podczas wydawania docker-compose down, wewnętrzny system plików każdego kontenera jest zapisywany gdzieś wewnętrznie. Kiedy teraz zmienię dane w folderze hosta i ponownie utworzę okno dokowane: Jaka jest reguła dotycząca zawartości w folderze udostępnionym? Czy dane z hosta zastąpią dane zapisane wewnętrznie? Thx!
and0r
@ and0r jest zachowywany i taki sam dla wszystkich kontenerów, więc zawartość zostanie zachowana.
Andriy Ivaneyko