Biasanya, masalah izin dengan pemasangan volume host adalah karena uid / gid di dalam wadah tidak memiliki akses ke file sesuai dengan izin uid / gid dari file pada host. Namun, kasus spesifik ini berbeda.
Titik di akhir string izin drwxr-xr-x.
,, menunjukkan SELinux dikonfigurasi. Saat menggunakan host host dengan SELinux, Anda harus memberikan opsi tambahan ke akhir definisi volume:
- The
z
pilihan menunjukkan bahwa mengikat gunung konten dibagi di antara beberapa kontainer.
- The
Z
pilihan menunjukkan bahwa bind mount konten pribadi dan pembagiannya.
Perintah volume mount Anda akan terlihat seperti:
sudo docker run -i -v /data1/Downloads:/Downloads:z ubuntu bash
Lihat lebih lanjut tentang host host dengan SELinux di: https://docs.docker.com/storage/#configure-the-selinux-label
Untuk orang lain yang melihat masalah ini dengan wadah berjalan sebagai pengguna yang berbeda, Anda perlu memastikan uid / gid dari pengguna di dalam wadah memiliki izin ke file di host. Pada server produksi, ini sering dilakukan dengan mengendalikan uid / gid dalam proses pembuatan gambar agar sesuai dengan uid / gid pada host yang memiliki akses ke file (atau bahkan lebih baik, jangan menggunakan host host dalam produksi).
Volume bernama sering dipilih untuk meng-host mount karena akan menginisialisasi direktori volume dari direktori gambar, termasuk kepemilikan dan izin file apa pun. Ini terjadi ketika volume kosong dan wadah dibuat dengan volume bernama.
Pengguna MacOS sekarang memiliki OSXFS yang menangani uid / gid secara otomatis antara host Mac dan wadah. Satu tempat yang tidak membantu adalah file dari dalam VM tertanam yang bisa dipasang ke dalam wadah, seperti /var/lib/docker.sock.
Untuk lingkungan pengembangan tempat host uid / gid dapat berubah per pengembang, solusi pilihan saya adalah memulai wadah dengan entrypoint berjalan sebagai root, perbaiki uid / gid pengguna di dalam wadah agar sesuai dengan volume host uid / gid, dan lalu gunakan gosu
untuk menjatuhkan dari root ke pengguna wadah untuk menjalankan aplikasi di dalam wadah. Skrip penting untuk ini ada fix-perms
di skrip gambar dasar saya, yang dapat ditemukan di: https://github.com/sudo-bmitch/docker-base
Bit penting dari fix-perms
skrip adalah:
# update the uid
if [ -n "$opt_u" ]; then
OLD_UID=$(getent passwd "${opt_u}" | cut -f3 -d:)
NEW_UID=$(stat -c "%u" "$1")
if [ "$OLD_UID" != "$NEW_UID" ]; then
echo "Changing UID of $opt_u from $OLD_UID to $NEW_UID"
usermod -u "$NEW_UID" -o "$opt_u"
if [ -n "$opt_r" ]; then
find / -xdev -user "$OLD_UID" -exec chown -h "$opt_u" {} \;
fi
fi
fi
Itu mendapatkan uid dari pengguna di dalam wadah, dan uid dari file, dan jika mereka tidak cocok, panggilan usermod
untuk menyesuaikan uid. Terakhir ia melakukan pencarian rekursif untuk memperbaiki file yang belum berubah. Saya suka ini lebih baik daripada menjalankan wadah dengan -u $(id -u):$(id -g)
bendera karena kode entri di atas tidak mengharuskan setiap pengembang untuk menjalankan skrip untuk memulai wadah, dan file apa pun di luar volume yang dimiliki oleh pengguna akan memiliki izin mereka diperbaiki.
Anda juga dapat membuat buruh pelabuhan menginisialisasi direktori host dari sebuah gambar dengan menggunakan volume bernama yang melakukan mount mengikat. Direktori ini harus ada sebelumnya, dan Anda harus memberikan path absolut ke direktori host, tidak seperti volume host dalam file penulisan yang bisa menjadi path relatif. Direktori juga harus kosong untuk buruh pelabuhan untuk menginisialisasi. Tiga opsi berbeda untuk mendefinisikan volume bernama ke bind mount terlihat seperti:
# create the volume in advance
$ docker volume create --driver local \
--opt type=none \
--opt device=/home/user/test \
--opt o=bind \
test_vol
# create on the fly with --mount
$ docker run -it --rm \
--mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=none,volume-opt=o=bind,volume-opt=device=/home/user/test \
foo
# inside a docker-compose file
...
volumes:
bind-test:
driver: local
driver_opts:
type: none
o: bind
device: /home/user/test
...
Terakhir, jika Anda mencoba menggunakan ruang nama pengguna, Anda akan menemukan bahwa volume host memiliki masalah izin karena uid / gid dari wadah tersebut digeser. Dalam skenario itu, mungkin paling mudah untuk menghindari volume host dan hanya menggunakan volume bernama.