Bagaimana saya bisa memasukkan file dari luar konteks pembangunan Docker menggunakan perintah "ADD" di file Docker?
Dari dokumentasi Docker:
Jalan harus berada di dalam konteks bangunan; Anda tidak dapat ADD ../something/something, karena langkah pertama pembuatan buruh pelabuhan adalah mengirim direktori konteks (dan subdirektori) ke daemon buruh pelabuhan.
Saya tidak ingin merestrukturisasi seluruh proyek saya hanya untuk mengakomodasi Docker dalam hal ini. Saya ingin menyimpan semua file Docker saya di sub-direktori yang sama.
Selain itu, tampaknya Docker belum (dan mungkin tidak pernah) mendukung symlink: Perintah ADD Dockerfile tidak mengikuti symlink pada host # 1676.
Satu-satunya hal lain yang dapat saya pikirkan adalah memasukkan langkah pra-bangun untuk menyalin file ke dalam konteks pembangunan Docker (dan mengonfigurasi kontrol versi saya untuk mengabaikan file-file itu). Apakah ada solusi yang lebih baik dari itu?
FROM
melanjutkan dari sana. Saya tidak akan mengubah struktur proyek untuk mengakomodasi Docker (atau alat membangun apa pun).Jawaban:
Cara terbaik untuk mengatasi ini adalah dengan menentukan Dockerfile secara independen dari konteks build, menggunakan -f.
Misalnya, perintah ini akan memberikan perintah ADD akses ke apa pun di direktori Anda saat ini.
Pembaruan : Docker sekarang memungkinkan Dockerfile berada di luar konteks build (diperbaiki pada 18.03.0-ce, https://github.com/docker/cli/pull/886 ). Jadi Anda juga bisa melakukan sesuatu seperti
sumber
dockerfile:
properti dibuild:
bagian dalam Compose file docs.docker.com/compose/compose-file/#/compose-file-referenceADD
file yang berada di luar direktori konteks? Itulah yang saya coba lakukan tetapi saya tidak berpikir untuk menggunakannya-f
membuat file eksternal dapat ditambahkan.build: context: .., dockerfile: dir/Dockerfile
. Sekarang konteks build saya adalah direktori induk!Saya sering mendapati diri saya menggunakan
--build-arg
opsi untuk tujuan ini. Misalnya setelah meletakkan yang berikut di Dockerfile:Anda bisa melakukannya:
Tetapi perhatikan peringatan berikut dari dokumentasi Docker :
Peringatan: Tidak disarankan untuk menggunakan variabel build-time untuk meneruskan rahasia seperti kunci github, kredensial pengguna, dll. Nilai variabel build-time terlihat oleh setiap pengguna gambar dengan perintah history docker.
sumber
Di Linux Anda dapat memasang direktori lain alih-alih menghubungkannya
Lihat /superuser/842642 untuk lebih jelasnya.
Saya tidak tahu apakah sesuatu yang serupa tersedia untuk OS lain. Saya juga mencoba menggunakan Samba untuk berbagi folder dan mengirimnya kembali ke dalam konteks Docker yang berfungsi juga.
sumber
Saya menghabiskan waktu yang baik untuk mencari tahu pola yang baik dan bagaimana menjelaskan dengan lebih baik apa yang terjadi dengan dukungan fitur ini. Saya menyadari bahwa cara terbaik untuk menjelaskannya adalah sebagai berikut ...
Jadi, dengan itu, inilah contoh Dockerfile yang perlu menggunakan kembali file yang disebut
start.sh
Dockerfile
Ini
ALWAYS
akan memuat dari jalur relatifnya, memiliki dir saat ini sendiri sebagailocal
referensi ke jalur yang Anda tentukan.File
Mempertimbangkan gagasan ini, kita dapat berpikir memiliki banyak salinan untuk Dockerfiles membangun hal-hal tertentu, tetapi mereka semua memerlukan akses ke
start.sh
.Mempertimbangkan struktur ini dan file-file di atas, inilah docker-compose.yml
docker-compose.yaml
shared
dir konteks Anda adalahruntime
dir.context
.dockerfile
.The
docker-compose.yml
adalah sebagai berikutall-service
diatur sebagai konteks, file bersamastart.sh
disalin di sana serta Dockerfile ditentukan oleh masing-masingdockerfile
.Bersulang!
sumber
a/b/c
, maka ya berjalandocker build .
dic
tidak akan memungkinkan Anda untuk mengakses../file-in-b
. Tapi, saya pikir kesalahpahaman umum dalam hal ini (atau setidaknya milik saya) adalah bahwa konteksnya ditentukan oleh lokasi yang dinyatakan oleh argumen pertama dari perintah build, bukan oleh lokasi Dockerfile. Jadi seperti yang dinyatakan dalam jawaban yang diterima: froma
:docker build -f a/b/c/Dockerfile .
berarti bahwa di Dockerfile.
sekarang foldera
Jika Anda membaca diskusi dalam masalah 2745 tidak hanya buruh pelabuhan mungkin tidak pernah mendukung symlinks mereka mungkin tidak pernah mendukung penambahan file di luar konteks Anda. Tampaknya menjadi filosofi desain bahwa file yang masuk ke bangunan buruh pelabuhan harus secara eksplisit menjadi bagian dari konteksnya atau berasal dari URL yang mungkin juga digunakan dengan versi tetap sehingga pembuatannya dapat diulang dengan URL atau file terkenal yang dikirimkan bersama wadah buruh pelabuhan.
Hanya pendapat saya tapi saya pikir Anda harus merestrukturisasi untuk memisahkan kode dan repositori buruh pelabuhan. Dengan cara itu wadah bisa menjadi generik dan menarik versi kode apa pun pada saat dijalankan daripada membangun waktu.
Atau, gunakan buruh pelabuhan sebagai artefak penyebaran kode dasar Anda dan kemudian Anda letakkan buruh pelabuhan di root repositori kode. jika Anda menggunakan rute ini mungkin masuk akal untuk memiliki container docker induk untuk detail level sistem yang lebih umum dan container anak untuk pengaturan khusus untuk kode Anda.
sumber
Saya percaya solusi yang lebih sederhana adalah mengubah 'konteks' itu sendiri.
Jadi, misalnya, alih-alih memberi:
yang menetapkan direktori saat ini sebagai konteks, katakanlah Anda menginginkan direktori induk sebagai konteks, cukup gunakan:
sumber
make build
dan menarik semua file yang diperlukan jika mereka diperbarui dan kemudian memanggil build docker yang sesuai ... Saya perlu melakukan pekerjaan ekstra, tetapi bekerja dengan sempurna karena saya dalam kendali penuh.Anda juga dapat membuat tarball dari apa yang dibutuhkan gambar terlebih dahulu dan menggunakannya sebagai konteks Anda.
https://docs.docker.com/engine/reference/commandline/build/#/tarball-contexts
sumber
tar zc /dir1 /dir2 |docker build -
. Ini sangat membantu dalam kasus saya.Menggunakan docker-compose, saya menyelesaikan ini dengan membuat layanan yang me-mount volume yang saya butuhkan dan melakukan gambar kontainer. Kemudian, dalam layanan selanjutnya, saya mengandalkan gambar yang dilakukan sebelumnya, yang memiliki semua data yang disimpan di lokasi yang dipasang. Anda kemudian harus menyalin file-file ini ke tujuan akhir mereka, karena direktori yang di-host di host tidak mendapatkan komitmen ketika menjalankan
docker commit
perintahsumber
Saya memiliki masalah yang sama dengan proyek dan beberapa file data yang saya tidak dapat pindah ke dalam konteks repo karena alasan HIPPA. Saya akhirnya menggunakan 2 Dockerfiles. Seseorang membangun aplikasi utama tanpa barang-barang yang saya butuhkan di luar wadah dan menerbitkannya ke repo internal. Kemudian dockerfile kedua menarik gambar itu dan menambahkan data dan membuat gambar baru yang kemudian digunakan dan tidak pernah disimpan di mana pun. Tidak ideal, tetapi berfungsi untuk tujuan saya menjaga informasi sensitif dari repo.
sumber
Solusi mudahnya adalah dengan memasang volume (menggunakan flag -v atau --mount) ke kontainer saat Anda menjalankannya dan mengakses file dengan cara itu.
contoh:
untuk lebih lanjut lihat: https://docs.docker.com/storage/volumes/
sumber
docker run
sudah terlambat.Seperti yang dijelaskan dalam masalah GitHub ini , build benar-benar terjadi
/tmp/docker-12345
, jadi path relatif seperti../relative-add/some-file
relatif terhadap/tmp/docker-12345
. Maka akan dicari/tmp/relative-add/some-file
, yang juga ditampilkan dalam pesan kesalahan. *Tidak diperbolehkan memasukkan file dari luar direktori build, jadi ini menghasilkan pesan "Jalur terlarang". "
sumber
Salah satu cara cepat dan kotor adalah mengatur konteks build sebanyak level yang Anda butuhkan - tetapi ini dapat memiliki konsekuensi. Jika Anda bekerja dalam arsitektur layanan microser yang terlihat seperti ini:
Anda dapat mengatur konteks build ke
Code
direktori induk dan kemudian mengakses semuanya, tetapi ternyata dengan sejumlah besar repositori, ini dapat menyebabkan build membutuhkan waktu lama.Contoh situasi bisa jadi tim lain mengelola skema basis data
Repo1
dan kode tim AndaRepo2
bergantung pada ini. Anda ingin mengurangi ketergantungan ini dengan beberapa data seed Anda sendiri tanpa khawatir tentang perubahan skema atau mengotori repositori tim lain (tergantung pada apa perubahannya Anda mungkin masih harus mengubah skrip data seed Anda tentu saja) Pendekatan kedua adalah hacky tetapi mengatasi masalah long build:Buat skrip sh (atau ps1)
./Code/Repo2
untuk menyalin file yang Anda butuhkan dan aktifkan perintah buruh pelabuhan yang Anda inginkan, misalnya:Dalam file pembuatan docker, cukup atur konteksnya sebagai
Repo2
root dan gunakan konten./db/schema
direktori di dockerfile Anda tanpa khawatir tentang path. Ingatlah bahwa Anda akan menjalankan risiko tidak sengaja melakukan direktori ini ke kontrol sumber, tetapi tindakan pembersihan skrip harus cukup mudah.sumber
Dalam kasus saya, Dockerfile saya ditulis seperti templat yang berisi placeholder yang saya ganti dengan nilai nyata menggunakan file konfigurasi saya.
Jadi saya tidak bisa menentukan file ini secara langsung tetapi pipa ke bangunan buruh pelabuhan seperti ini:
Tetapi karena pipa itu,
COPY
perintahnya tidak bekerja. Tetapi cara di atas menyelesaikannya dengan-f -
(secara eksplisit mengatakan file tidak disediakan). Melakukan hanya-
tanpa-f
bendera, konteks DAN Dockerfile tidak disediakan yang merupakan peringatan.sumber
Triknya adalah mengenali bahwa Anda dapat menentukan konteks dalam perintah build untuk memasukkan file dari direktori induk jika Anda menentukan jalur Docker, saya akan mengubah Dockerfile saya menjadi seperti ini:
Maka perintah build saya dapat terlihat seperti ini:
Dari direktori proyek
Dari proyek / buruh pelabuhan
sumber