Saya telah bermain-main dengan Docker untuk sementara waktu dan terus menemukan masalah yang sama ketika berhadapan dengan data persisten.
Saya membuat Dockerfile
dan memaparkan volume atau gunakan --volumes-from
untuk memasang folder host di dalam wadah saya .
Izin apa yang harus saya terapkan pada volume bersama di host?
Saya dapat memikirkan dua opsi:
Sejauh ini saya sudah memberi semua orang akses baca / tulis, jadi saya bisa menulis ke folder dari wadah Docker.
Petakan pengguna dari host ke dalam wadah, sehingga saya dapat menetapkan lebih banyak izin granular. Tidak yakin ini mungkin terjadi dan belum menemukan banyak tentang itu. Sejauh ini, yang bisa saya lakukan adalah menjalankan container sebagai beberapa pengguna:,
docker run -i -t -user="myuser" postgres
tetapi pengguna ini memiliki UID yang berbeda dari host sayamyuser
, jadi izin tidak berfungsi. Juga, saya tidak yakin jika memetakan pengguna akan menimbulkan risiko keamanan.
Apakah ada alternatif lain?
Bagaimana kalian menangani masalah ini?
Jawaban:
UPDATE 2016-03-02 : Pada Docker 1.9.0, Docker telah menamai volume yang menggantikan wadah hanya-data . Jawaban di bawah ini, serta posting blog saya yang tertaut, masih memiliki nilai dalam arti bagaimana berpikir tentang data di dalam buruh pelabuhan tetapi mempertimbangkan menggunakan volume bernama untuk menerapkan pola yang dijelaskan di bawah daripada wadah data.
Saya percaya cara kanonik untuk menyelesaikan ini adalah dengan menggunakan wadah data saja . Dengan pendekatan ini, semua akses ke data volume adalah melalui wadah yang menggunakan
-volumes-from
wadah data, sehingga host uid / gid tidak masalah.Misalnya, satu use case yang diberikan dalam dokumentasi adalah membuat cadangan volume data. Untuk melakukan ini, wadah lain digunakan untuk melakukan pencadangan melalui
tar
, dan juga digunakan-volumes-from
untuk memasang volume. Jadi saya pikir poin utama untuk grok adalah: daripada berpikir tentang cara mendapatkan akses ke data di host dengan izin yang tepat, pikirkan tentang bagaimana melakukan apa pun yang Anda butuhkan - backup, browsing, dll. - melalui wadah lain . Wadah itu sendiri harus menggunakan uid / gids yang konsisten, tetapi mereka tidak perlu memetakan apa pun di host, sehingga tetap portabel.Ini relatif baru bagi saya juga, tetapi jika Anda memiliki kasus penggunaan tertentu jangan ragu untuk berkomentar dan saya akan mencoba untuk memperluas jawabannya.
PEMBARUAN : Untuk kasus penggunaan yang diberikan dalam komentar, Anda mungkin memiliki gambar
some/graphite
untuk menjalankan grafit, dan gambarsome/graphitedata
sebagai wadah data. Jadi, mengabaikan port dan semacamnya,Dockerfile
gambarnyasome/graphitedata
adalah seperti:Buat dan buat wadah data:
The
some/graphite
Dockerfile juga harus mendapatkan uid yang sama / Gids, oleh karena itu mungkin terlihat seperti ini:Dan itu akan dijalankan sebagai berikut:
Oke, sekarang yang memberi kami wadah grafit dan wadah khusus data yang terkait dengan pengguna / grup yang benar (perhatikan bahwa Anda juga dapat menggunakan kembali
some/graphite
wadah tersebut untuk wadah data, mengesampingkan masukan / cmd saat menjalankannya, tetapi menjadikannya sebagai memisahkan gambar IMO lebih jelas).Sekarang, katakanlah Anda ingin mengedit sesuatu di folder data. Jadi daripada mengikat pemasangan volume ke host dan mengeditnya di sana, buat wadah baru untuk melakukan pekerjaan itu. Mari kita sebut saja
some/graphitetools
. Mari kita juga membuat pengguna / grup yang tepat, sepertisome/graphite
gambar.Anda dapat membuat KERING ini dengan mewarisi dari
some/graphite
atausome/graphitedata
di Dockerfile, atau alih-alih membuat gambar baru gunakan kembali salah satu yang sudah ada (menimpa entrypoint / cmd seperlunya).Sekarang, Anda cukup menjalankan:
dan kemudian
vi /data/graphite/whatever.txt
. Ini berfungsi dengan baik karena semua kontainer memiliki pengguna grafit yang sama dengan uid / gid yang cocok.Karena Anda tidak pernah me-mount
/data/graphite
dari host, Anda tidak peduli bagaimana host uid / gid memetakan ke uid / gid yang didefinisikan di dalamgraphite
dangraphitetools
kontainer. Kontainer tersebut sekarang dapat digunakan untuk host mana saja, dan mereka akan terus bekerja dengan sempurna.Hal yang rapi tentang ini adalah bahwa
graphitetools
bisa memiliki semua jenis utilitas dan skrip yang bermanfaat, yang kini dapat Anda gunakan secara portabel.UPDATE 2 : Setelah menulis jawaban ini, saya memutuskan untuk menulis posting blog yang lebih lengkap tentang pendekatan ini. Saya harap ini membantu.
UPDATE 3 : Saya memperbaiki jawaban ini dan menambahkan lebih spesifik. Sebelumnya berisi beberapa asumsi yang salah tentang kepemilikan dan perms - kepemilikan biasanya diberikan pada waktu pembuatan volume yaitu dalam wadah data, karena saat itulah volume dibuat. Lihat blog ini . Ini bukan persyaratan - Anda hanya dapat menggunakan wadah data sebagai "referensi / pegangan" dan mengatur kepemilikan / perms dalam wadah lain melalui chown di entri point, yang berakhir dengan gosu untuk menjalankan perintah sebagai pengguna yang benar. Jika ada yang tertarik dengan pendekatan ini, silakan komentar dan saya dapat memberikan tautan ke sampel menggunakan pendekatan ini.
sumber
/data/newcontainer
? Saya berasumsi Anda menjalankandocker
sebagai root (apakah mungkin untuk tidak melakukannya?) Juga, apakah ada perbedaan dalam izin tersebut jika data dipasang langsung di wadah utama atau melalui wadah data saja ?/var/lib/docker
suatu tempat tetapi masih sangat menyakitkanSolusi yang sangat elegan dapat dilihat pada gambar redis resmi dan secara umum di semua gambar resmi.
Dijelaskan dalam proses langkah demi langkah:
Seperti yang terlihat di komentar Dockerfile:
gosu adalah alternatif
su
/sudo
untuk step-down yang mudah dari pengguna root. (Redis selalu dijalankan denganredis
pengguna)/data
volume dan atur sebagai workdirDengan mengkonfigurasi volume / data dengan
VOLUME /data
perintah kita sekarang memiliki volume terpisah yang dapat berupa volume buruh pelabuhan atau bind-mount ke dir host.Mengkonfigurasinya sebagai workdir (
WORKDIR /data
) menjadikannya direktori default tempat perintah dijalankan.Ini berarti bahwa semua eksekusi kontainer akan dijalankan melalui skrip docker-entrypoint, dan secara default perintah yang akan dijalankan adalah redis-server.
docker-entrypoint
adalah skrip yang melakukan fungsi sederhana: Mengubah kepemilikan direktori saat ini (/ data) dan turun dariroot
menjadiredis
pengguna untuk menjalankanredis-server
. (Jika perintah yang dijalankan bukan redis-server, itu akan menjalankan perintah secara langsung.)Ini memiliki efek sebagai berikut
Jika direktori / data diikat-mount ke host, docker-entrypoint akan menyiapkan izin pengguna sebelum menjalankan redis-server di bawah
redis
pengguna.Ini memberi Anda kemudahan bahwa ada pengaturan nol untuk menjalankan wadah di bawah konfigurasi volume apa pun.
Tentu saja jika Anda perlu berbagi volume antara gambar yang berbeda, Anda perlu memastikan mereka menggunakan userid / groupid yang sama jika tidak, wadah terbaru akan membajak izin pengguna dari yang sebelumnya.
sumber
chown
itu di dalamENTRYPOINT
skrip?Ini bisa dibilang bukan cara terbaik untuk sebagian besar keadaan, tetapi belum disebutkan jadi mungkin itu akan membantu seseorang.
Bind mount volume host
Host folder FOOBAR is mounted in container /volume/FOOBAR
Ubah skrip startup kontener Anda untuk menemukan GID volume yang Anda minati
$ TARGET_GID=$(stat -c "%g" /volume/FOOBAR)
Pastikan pengguna Anda milik grup dengan GID ini (Anda mungkin harus membuat grup baru). Untuk contoh ini saya akan berpura-pura perangkat lunak saya berjalan sebagai
nobody
pengguna ketika berada di dalam wadah, jadi saya ingin memastikannobody
milik grup dengan id grup sama denganTARGET_GID
Saya suka ini karena saya dapat dengan mudah mengubah izin grup pada volume host saya dan tahu bahwa izin yang diperbarui berlaku di dalam wadah buruh pelabuhan. Ini terjadi tanpa izin atau modifikasi kepemilikan pada folder / file host saya, yang membuat saya senang.
Saya tidak suka ini karena mengasumsikan tidak ada bahaya dalam menambahkan diri Anda ke grup sewenang-wenang di dalam wadah yang kebetulan menggunakan GID yang Anda inginkan. Itu tidak dapat digunakan dengan
USER
klausa di Dockerfile (kecuali jika pengguna itu memiliki hak root). Juga, ia menjerit pekerjaan hack ;-)Jika Anda ingin menjadi hardcore, Anda dapat dengan jelas memperluas ini dengan banyak cara - mis. Mencari semua grup di subfil, banyak volume, dll.
sumber
$TARGET_GID
adalah menggunakangrep ':$TARGET_GID:'
, jika tidak, jika wadahnya memiliki, misalnya gid 10001 dan host Anda adalah 1000, cek ini akan berlalu tetapi seharusnya tidak.Ok, ini sekarang sedang dilacak pada masalah buruh pelabuhan # 7198
Untuk saat ini, saya berurusan dengan ini menggunakan opsi kedua Anda:
Dockerfile
CLI
PEMBARUAN Saya saat ini lebih condong ke jawaban Hamy
sumber
id -u <username>
,id -g <username>
,id -G <username>
untuk mendapatkan user id dan kelompok id dari pengguna tertentu bukannyaCobalah untuk menambahkan perintah ke Dockerfile
kredit jatuh ke https://github.com/denderello/symfony-docker-example/issues/2#issuecomment-94387272
sumber
Sama seperti Anda, saya sedang mencari cara untuk memetakan pengguna / grup dari host ke kontainer buruh pelabuhan dan ini adalah cara terpendek yang saya temukan sejauh ini:
Ini adalah ekstrak dari docker-compose.yml saya.
Idenya adalah untuk me-mount (dalam mode read-only) daftar pengguna / grup dari host ke container sehingga setelah kontainer dijalankan akan memiliki nama pengguna> username (dan juga grup) yang sama dengan host. Sekarang Anda dapat mengonfigurasi pengaturan pengguna / grup untuk layanan Anda di dalam wadah seolah-olah itu berfungsi pada sistem host Anda.
Ketika Anda memutuskan untuk memindahkan wadah Anda ke host lain, Anda hanya perlu mengubah nama pengguna di file konfigurasi layanan ke apa yang Anda miliki di host itu.
sumber
-u $( id -u $USER ):$( id -g $USER )
dan Anda tidak perlu lagi khawatir tentang nama pengguna. Ini bekerja dengan baik untuk lingkungan dev lokal di mana Anda ingin menghasilkan file (misalnya binari) yang telah Anda akses akses baca / tulis secara default.Berikut adalah pendekatan yang masih menggunakan wadah data saja tetapi tidak mengharuskannya untuk disinkronkan dengan wadah aplikasi (dalam hal memiliki uid / gid yang sama).
Agaknya, Anda ingin menjalankan beberapa aplikasi dalam wadah sebagai $ USER non-root tanpa shell login.
Di Dockerfile:
Lalu, di entrypoint.sh:
sumber
Untuk mengamankan dan mengubah root untuk wadah buruh pelabuhan tuan rumah buruh pelabuhan coba gunakan
--uidmap
dan--private-uids
opsihttps://github.com/docker/docker/pull/4572#issuecomment-38400893
Anda juga dapat menghapus beberapa kemampuan (
--cap-drop
) dalam wadah buruh pelabuhan untuk keamananhttp://opensource.com/business/14/9/security-for-docker
Dukungan UPDATE harus masuk
docker > 1.7.0
UPDATE Version
1.10.0
(2016/02/04) add--userns-remap
bendera https://github.com/docker/docker/blob/master/CHANGELOG.md#security-2sumber
--uidmap
maupun--private-uids
. Sepertinya PR tidak berhasil dan tidak digabung."We apparently do have so some of conflicting designs between libnetwork and user namespaces ... and something we'd like to get in for 1.8.0. So don't think we're dropping this, we're definitely going to take a break after all these, and see how we need to reconsider the current design and integration of libnetwork to make this possible. Thanks!"
github.com/docker/docker/pull/12648 Jadi saya pikir kita harus menunggu versi stabil berikutnya.Pendekatan saya adalah mendeteksi UID / GID saat ini, kemudian membuat pengguna / grup di dalam wadah dan menjalankan skrip di bawahnya. Akibatnya semua file yang akan dibuat akan cocok dengan pengguna di host (yang merupakan skrip):
sumber
Gambar Dasar
Gunakan gambar ini: https://hub.docker.com/r/reduardo7/docker-host-user
atau
Penting: ini menghancurkan portabilitas kontainer di seluruh host .
1)
init.sh
2)
Dockerfile
3) run.sh
4) Bangun dengan
docker
4) Lari!
sumber
Dalam kasus khusus saya, saya mencoba untuk membangun paket node saya dengan gambar docker simpul sehingga saya tidak perlu menginstal npm di server penyebaran. Ini bekerja dengan baik sampai, di luar wadah dan pada mesin host, saya mencoba untuk memindahkan file ke direktori node_modules yang telah dibuat gambar docker node, yang saya ditolak izinnya karena dimiliki oleh root. Saya menyadari bahwa saya dapat mengatasi ini dengan menyalin direktori keluar dari wadah ke mesin host. Melalui dok buruh pelabuhan ...
Ini adalah kode bash yang saya gunakan untuk mengubah kepemilikan direktori yang dibuat oleh dan di dalam wadah buruh pelabuhan.
Jika perlu, Anda dapat menghapus direktori dengan wadah buruh pelabuhan kedua.
sumber
Untuk berbagi folder antara host buruh pelabuhan dan wadah buruh pelabuhan, coba perintah di bawah ini
Bendera -v memasang direktori kerja saat ini ke dalam wadah. Ketika direktori host volume bind-mount tidak ada, Docker akan secara otomatis membuat direktori ini pada host untuk Anda,
Namun, ada 2 masalah yang kita miliki di sini:
Larutan:
Wadah: buat pengguna mengatakan 'testuser', secara default id pengguna akan mulai dari 1000,
Host: buat grup katakan 'testgroup' dengan id grup 1000, dan beri tahu direktori ke grup baru (testgroup
sumber
Jika Anda menggunakan Docker Compose, mulai wadah dalam mode yang dicegah:
sumber