Cara me-mount satu file dalam volume

257

Saya mencoba membuat aplikasi php. Di dockerfile saya mengunduh arsip, mengekstraknya dll.

Semuanya berfungsi dengan baik, namun jika versi baru dirilis, dan saya memperbarui dockerfile saya harus menginstal ulang aplikasi, karena config.php akan ditimpa.

Jadi saya pikir saya bisa me-mount file sebagai volume, seperti yang saya lakukan dengan database.

Saya mencobanya dua cara, dengan volume dan jalur langsung.

komposisi buruh pelabuhan:

version: '2'
services:
  app:
    build: src
    ports:
      - "8080:80"
    depends_on:
      - mysql
    volumes:
      -  app-conf:/var/www/html/upload
      -  app-conf:/var/www/html/config.php
    environment:
      DB_TYPE: mysql
      DB_MANAGER: MysqlManager

  mysql:
    image: mysql:5.6
    container_name: mysql
    volumes:
      - mysqldata:/var/lib/mysql
    ports:
      - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD:
      MYSQL_DATABASE:
      MYSQL_USER:
      MYSQL_PASSWORD:

volumes:
  mysqldata:
  app-conf:

Yang menghasilkan kesalahan:

Dan saya mencobanya dengan jalur yang diberikan, sebagai volume yang dipasang.

/src/docker/myapp/upload:/var/www/html/upload
/src/docker/myapp/upload:/var/www/html/config.php

Namun kedua cara tersebut tidak berfungsi. Dengan volume yang dipasang saya melihat bahwa unggahan dibuat.

Tetapi kemudian gagal dengan

/var/www/html/config.php \\ "menyebabkan \\" bukan direktori \\ "\" "

Jika saya mencobanya

/src/docker/myapp/upload/config.php:/var/www/html/config.php

Docker membuat folder unggah dan kemudian folder config.php. Bukan file.

Atau adakah cara lain untuk mempertahankan konfigurasi?

Jakub Juszczak
sumber
Dalam kasus saya, saya sederhana itu untuk "menyentuh" ​​file kosong sebelum membuat wadah / volume. Jika file tidak ada, itu membuat direktori.
FreeSoftwareServers

Jawaban:

312

TL; DR / Pemberitahuan:

Jika Anda mengalami direktori yang dibuat di tempat file yang ingin Anda mount, Anda mungkin gagal menyediakan jalur yang valid dan absolut . Ini adalah kesalahan umum dengan mode kegagalan diam dan membingungkan.

Volume file dilakukan dengan cara ini di buruh pelabuhan (contoh jalur absolut (dapat menggunakan variabel env), dan Anda perlu menyebutkan nama file):

    volumes:
      - /src/docker/myapp/upload:/var/www/html/upload
      - /src/docker/myapp/upload/config.php:/var/www/html/config.php

Anda juga dapat melakukan:

    volumes:
      - ${PWD}/upload:/var/www/html/upload
      - ${PWD}/upload/config.php:/var/www/html/config.php

Jika Anda memecat docker-compose dari /src/docker/myappfolder

BlackStork
sumber
81
Seperti yang saya katakan, jika saya mencoba /src/docker/myapp/upload/config.php:/var/www/html/config.php Docker membuat folder unggah dan kemudian folder config.php. Bukan file.
Jakub Juszczak
9
Dalam posting Anda, Anda menulis secara berbeda. Jika file ada di sana itu harus dipasang sebagai file.
BlackStork
16
Agar ini berfungsi saya harus menyediakan jalur absolut. Tip menggunakan PWD banyak membantu di sini, terima kasih!
Steve Smith
4
Bagi saya membuat folder daripada file, tapi saya pikir karena file itu disalin nanti di jalur itu ada pula untuk menunda mengikat?
eKelvin
18
jika /src/docker/myapp/upload/config.php tidak ada di host docker akan membuat folder ... Apa yang saya lakukan adalah membuat skrip yang membuat file kosong sebelum menjalankan docker run - akan ideal jika saya dapat menginstruksikan buruh pelabuhan untuk melakukannya untuk saya melalui argumen cmd line.
cancerbero
78

Saya telah menderita masalah yang sama. Saya mencoba mengimpor file konfigurasi saya ke wadah saya sehingga saya dapat memperbaikinya setiap kali saya perlu tanpa membangun kembali gambar.

Maksud saya, saya pikir perintah di bawah ini akan memetakan $(pwd)/config.pydari host Docker /root/app/config.pyke wadah sebagai file.

docker run -v $(pwd)/config.py:/root/app/config.py my_docker_image

Namun, itu selalu membuat direktori bernama config.py, bukan file.

sambil mencari petunjuk, saya menemukan alasannya (dari sini )

Jika Anda menggunakan -v atau --volume untuk mengikat-mount file atau direktori yang belum ada pada host Docker, -v akan membuat titik akhir untuk Anda. Itu selalu dibuat sebagai direktori .

Oleh karena itu, selalu dibuat sebagai direktori karena host buruh pelabuhan saya tidak punya $(pwd)/config.py.

Bahkan jika saya membuat config.py di host buruh pelabuhan. $(pwd)/config.pyhanya overwirte /root/app/config.pytidak mengekspor /root/app/config.py.

SangminKim
sumber
16
Saya baru saja menambahkan touch path/to/filedi Dockerfilesehingga ketika saya me-mount itu masih akan menjadi file (bukan dir dibuat)
shadi
8
sisi kiri :harus jalur penuh. Ini bekerja dengan cara ini
SDK
The touchadalah jawabannya, melakukan itu di Dockerfile kemudian Volume buruh pelabuhan-compose Anda me-mount akan bekerja dengan benar tanpa membuat direktori
ctrlbrk
27

Gunakan mount ( --mount) sebagai gantinya volume ( -v)

Info lebih lanjut: https://docs.docker.com/storage/bind-mounts/

Contoh:

Pastikan /tmp/a.txt ada di host buruh pelabuhan

docker run -it --mount type=bind,source=/tmp/a.txt,target=/root/a.txt alpine sh
Subbu M
sumber
Terima kasih Subbu, @ Jakub Juszczak, ini seharusnya jawaban yang diterima, itu satu-satunya jawaban yang menjawab pertanyaan sama sekali, dan itu berhasil untuk saya
neokyle
2
Ini tidak benar-benar menjawab pertanyaan itu. volume akan bekerja dengan baik (karena masalah ini berada di jalur absolut). Satu-satunya perbedaan antara --mountdan -vadalah perilaku ketika bagian host dari volume belum ada. Sesuai tautan Anda:> Jika Anda menggunakan -v atau --volume untuk mengikat-mount file atau direktori yang belum ada pada host Docker, -v menciptakan titik akhir untuk Anda. Itu selalu dibuat sebagai direktori.
The Godfather
2
Saya tidak tahu bagaimana menerjemahkan ini ke menulis buruh pelabuhan. 'Sedikit bantuan?
msanford
@ msanford saya menambahkan contoh buruh pelabuhan-menulis jawaban.
sebisnow
10

Bagi siapa pun yang menggunakan wadah Windows seperti saya, ketahuilah bahwa Anda TIDAK BISA mengikat atau memasang file tunggal menggunakan wadah Windows.

Contoh berikut akan gagal saat menggunakan wadah berbasis Windows, karena tujuan volume atau bind mount di dalam wadah harus salah satu dari: direktori tidak ada atau kosong; atau drive selain C :. Selanjutnya, sumber bind mount harus berupa direktori lokal, bukan file .

net use z: \\remotemachine\share

docker run -v z:\foo:c:\dest ...

docker run -v \\uncpath\to\directory:c:\dest ...

docker run -v c:\foo\somefile.txt:c:\dest ...

docker run -v c:\foo:c: ...

docker run -v c:\foo:c:\existing-directory-with-contents ...

Sulit dikenali tapi ada di sana

Tautan ke masalah Github tentang pemetaan file ke dalam wadah Windows

Justin Lessard
sumber
7

Pada file docker-compose versi 3.2 Anda dapat menentukan volume mount tipe "bind" (bukan tipe default "volume") yang memungkinkan Anda untuk memasang satu file ke dalam wadah. Cari "bind mount" di dok volume-buat dokumen volume: https://docs.docker.com/compose/compose-file/#volumes

Dalam kasus saya, saya mencoba me-mount satu file "rahasia." Ke dalam aplikasi saya yang berisi rahasia untuk pengembangan dan pengujian lokal saja. Dalam produksi, aplikasi saya mengambil rahasia ini dari AWS sebagai gantinya.

Jika saya memasang file ini sebagai volume menggunakan sintaks singkatan:

volumes:
 - ./.secrets:/data/app/.secrets

Docker akan membuat direktori ".secrets" di dalam wadah alih-alih memetakan ke file di luar wadah. Kode saya kemudian akan memunculkan kesalahan seperti "IsADirectoryError: [Errno 21] Adalah direktori: '.secrets'".

Saya memperbaikinya dengan menggunakan sintaks tangan lama sebagai gantinya, menentukan file rahasia saya menggunakan mount mount read-only "bind":

volumes:
 - type: bind
   source: ./.secrets
   target: /data/app/.secrets
   read_only: true

Sekarang Docker dengan benar me-mount file .secrets saya ke dalam wadah, membuat file di dalam wadah bukan direktori. Semoga orang lain menemukan contoh ini bermanfaat!

Carlton Duffett
sumber
Terima kasih Pak! Itulah solusi yang saya butuhkan untuk dapat me-mount file WordPress wp-config.php saya (dan menghentikannya dibuat sebagai direktori)
Jono
6

Anda juga dapat menggunakan jalur relatif ke docker-compose.ymlfile Anda seperti ini (diuji pada host Windows, wadah Linux):

 volumes:
      - ./test.conf:/fluentd/etc/test.conf
Daniel
sumber
1
Saya menguji ini pada Mac dengan version: '3.7'ditentukan dalam docker-compose.ymlfile dengan docker-compose versi 1.24.1, build 4667896b, dan itu berhasil.
Acumenus
6
Saya masih mendapatkan direktori, bukan file.
chovy
0

Bagi saya, masalahnya adalah saya memiliki tautan simbolis yang rusak pada file yang saya coba pasang ke wadah

jla
sumber
0

Saya memiliki masalah yang sama pada Windows Docker 18.06.1-ce-win73 (19507),.

Menghapus dan menambahkan kembali drive bersama melalui panel pengaturan Docker dan semuanya berfungsi kembali.

Kolam
sumber
0

Di windows, jika Anda memerlukan variabel env $ {PWD} di docker-compose.yml, Anda dapat membuat file .env di direktori yang sama dengan file docker-compose.yml lalu memasukkan secara manual lokasi folder Anda.

CMD (pwd_var.bat):

echo PWD=%cd% >> .env

Powershell (pwd_var.ps1):

$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'; echo "PWD=$(get-location).path" >> .env

Ada fitur yang lebih baik untuk mendengar variabel .env docker-compose: https://docs.docker.com/compose/reference/envvars/ terutama untuk COMPOSE_CONVERT_WINDOWS_PATHSvariabel env yang memungkinkan buruh pelabuhan menulis untuk menerima jalur windows dengan baskslash "\".

Saat Anda ingin membagikan file di windows, file tersebut harus ada sebelum membaginya dengan kontainer.

TeleponMarl
sumber
Anda tidak dapat menggunakan PowerShell dengan buruh pelabuhan, itu membuat vendor terkunci dan melukai komunitas ...
Matej 'Yin' Gagyi
0

Mungkin ini membantu seseorang.

Saya memiliki masalah ini dan mencoba segalanya. Binding Volume terlihat baik dan bahkan jika saya memasang direktori (bukan file), saya memiliki nama file di direktori yang terpasang dengan benar tetapi dipasang sebagai dirs.

Saya mencoba mengaktifkan kembali drive yang dipakai bersama dan Docker mengeluh firewallnya aktif.

Setelah menonaktifkan firewall semua bekerja dengan baik.

Josef Sábl
sumber
Terima kasih untuk itu! Pos Anda membuat saya menyadari bahwa selinux saya ditetapkan untuk ditegakkan dan itu menyebabkan semua masalah saya. Tidak tahu mengapa Anda terpilih sebagai ¯_ (ツ) _ / ¯
Oktavianus
0

Anda dapat memasang file atau direktori / folder itu semua tergantung pada file Sumber atau direktori. Dan juga Anda perlu memberikan path lengkap atau jika Anda tidak yakin Anda dapat menggunakan PWD. Ini adalah contoh kerja sederhana.

Dalam contoh ini, saya sedang memasang file env-commands yang sudah ada di direktori kerja saya

$ docker run  --rm -it -v ${PWD}/env-commands:/env-commands aravindgv/eosdt:1.0.5 /bin/bash -c "cat /env-commands"
Aravind GV
sumber
-1

Saya memiliki masalah yang sama pada Windows 8.1 saya

Ternyata itu karena sensitivitas case path. Saya menelepon docker-compose updari direktori cd /c/users/alex/dan di dalam wadah file diubah menjadi direktori.

Tetapi ketika saya melakukannya cd /c/Users/alex/(bukan Pengguna dengan huruf besar) dan menelepon docker-compose updari sana, itu berhasil.

Dalam sistem saya, dir Pengguna dan dir Alex dikapitalisasi, meskipun sepertinya hanya dir Pengguna.

Alex Velickiy
sumber