Saya memiliki Dockerfile yang saya kumpulkan untuk menginstal lingkungan python vanilla (di mana saya akan menginstal aplikasi, tetapi di kemudian hari).
FROM ubuntu:12.04
# required to build certain python libraries
RUN apt-get install python-dev -y
# install pip - canonical installation instructions from pip-installer.org
# http://www.pip-installer.org/en/latest/installing.html
ADD https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py /tmp/ez_setup.py
ADD https://raw.github.com/pypa/pip/master/contrib/get-pip.py /tmp/get-pip.py
RUN python /tmp/ez_setup.py
RUN python /tmp/get-pip.py
RUN pip install --upgrade pip
# install and configure virtualenv
RUN pip install virtualenv
RUN pip install virtualenvwrapper
ENV WORKON_HOME ~/.virtualenvs
RUN mkdir -p $WORKON_HOME
RUN source /usr/local/bin/virtualenvwrapper.sh
Build berjalan ok sampai baris terakhir, tempat saya mendapatkan pengecualian berikut:
[previous steps 1-9 removed for clarity]
...
Successfully installed virtualenvwrapper virtualenv-clone stevedore
Cleaning up...
---> 1fc253a8f860
Step 10 : ENV WORKON_HOME ~/.virtualenvs
---> Running in 8b0145d2c80d
---> 0f91a5d96013
Step 11 : RUN mkdir -p $WORKON_HOME
---> Running in 9d2552712ddf
---> 3a87364c7b45
Step 12 : RUN source /usr/local/bin/virtualenvwrapper.sh
---> Running in c13a187261ec
/bin/sh: 1: source: not found
Jika saya ls
ke direktori itu (hanya untuk menguji bahwa langkah-langkah sebelumnya dilakukan) saya dapat melihat bahwa file ada seperti yang diharapkan:
$ docker run 3a87 ls /usr/local/bin
easy_install
easy_install-2.7
pip
pip-2.7
virtualenv
virtualenv-2.7
virtualenv-clone
virtualenvwrapper.sh
virtualenvwrapper_lazy.sh
Jika saya mencoba menjalankan source
perintah, saya mendapatkan kesalahan 'tidak ditemukan' yang sama seperti di atas. Jika saya MENJALANKAN sesi shell interaktif, sumber tidak bekerja:
$ docker run 3a87 bash
source
bash: line 1: source: filename argument required
source: usage: source filename [arguments]
Saya dapat menjalankan skrip dari sini, dan kemudian dengan senang hati mengakses workon
, mkvirtualenv
dll.
Saya telah melakukan beberapa penggalian, dan awalnya tampak seolah-olah masalahnya mungkin terletak pada perbedaan antara bash sebagai shell login Ubuntu , dan dash sebagai shell sistem Ubuntu , dash tidak mendukung source
perintah.
Namun, jawaban untuk ini tampaknya menggunakan '.' bukan source
, tapi ini hanya menyebabkan runtime Docker meledak dengan pengecualian panik pergi.
Apa cara terbaik untuk menjalankan skrip shell dari instruksi Dockerfile RUN untuk menyiasati ini (saya kehabisan gambar dasar default untuk Ubuntu 12.04 LTS).
CMD source activate django-py35
Jawaban:
RUN /bin/bash -c "source /usr/local/bin/virtualenvwrapper.sh"
sumber
source
sama sekali, vs adilbash /usr/local/bin/virtualenvwrapper.sh
, dalam kasus itu?RUN /bin/bash -c "source /usr/local/bin/virtualenvwrapper.sh; my_command; my_command; my_command;"
/bin/sh -c
shell default, "shell form" dari RUN ini diterjemahkan menjadiRUN ["/bin/sh", "-c", "/bin/bash" "-c" "source /usr/local/bin/virtualenvwrapper.sh"]
. Anda harus maju dan menggunakan "exec form" dari RUN sehingga Anda dapat mengambilsh
keluar seperti ituRUN ["/bin/bash" "-c" "source /usr/local/bin/virtualenvwrapper.sh"]
bash
bersarang dish
dan karenanya harus dihindari.Jawaban Asli
Ini harus bekerja untuk setiap gambar dasar buruh pelabuhan Ubuntu. Saya biasanya menambahkan baris ini untuk setiap Dockerfile yang saya tulis.
Edit oleh pengamat yang bersangkutan
Jika Anda ingin mendapatkan efek "gunakan
bash
alih-alihsh
seluruh Dockerfile ini", tanpa mengubah dan mungkin merusak * OS di dalam wadah, Anda bisa memberi tahu Docker niat Anda . Itu dilakukan seperti itu:Lebih detail dalam jawaban di bawah ini. https://stackoverflow.com/a/45087082/117471
sumber
ln -snf /bin/bash /bin/sh
sh
kebash
ln -s /bin/bash /bin/sh
ini ide yang buruk. target ubuntu / bin / sh untuk lari karena suatu alasan. dash adalah shell sepenuhnya posix yang perintah besarnya lebih cepat dari bash. menautkan / bin / sh ke bash akan secara drastis mengurangi kinerja server Anda. mengutip: wiki.ubuntu.com/DashAsBinShsh
shell, tetapi Anda menginginkannyabash
, solusi yang tepat adalah dengansh
meminta proses dipanggilbash
satu kali, misalnyabash -c 'source /script.sh && …'
, atau Anda bahkan dapat melangkah lebih jauh untuk menghindari bashisme (sepertisource
) sepenuhnya, dan sebagai gantinya memilih untuk hanya menggunakan setara POSIX yang valid, mis. /script.sh
. (Pikirkan ruang setelah.
!) Terakhir, jika skrip Anda dapat dieksekusi (bukan hanya sumber), jangan pernah membuat skrip Anda berbohong dengan#!/bin/sh
shebang jika tidak benar-benar kompatibel dengan sh. Gunakan#!/bin/bash
sebagai gantinya.Shell default untuk
RUN
instruksi adalah["/bin/sh", "-c"]
.Menggunakan instruksi SHELL , Anda dapat mengubah shell default untuk
RUN
instruksi selanjutnya di Dockerfile:Sekarang, shell default telah berubah dan Anda tidak perlu mendefinisikannya secara eksplisit di setiap instruksi RUN
Catatan Tambahan : Anda juga bisa menambahkan
--login
opsi yang akan memulai shell login. Ini berarti~/.bachrc
misalnya akan dibaca dan Anda tidak perlu sumber itu secara eksplisit sebelum perintah Andasumber
--login
- baru saja memikirkannya sendiriSHELL ["/bin/bash", "-c", "-l"]
saya dapat menggunakan pembaruan lebih lanjut untuk file .bashrc, yang memungkinkan saya untuk menjalankan perintah asdf dengan mudah.Saya memiliki masalah yang sama dan untuk mengeksekusi pip install di dalam virtualenv saya harus menggunakan perintah ini:
Saya harap ini membantu.
sumber
RUN /bin/bash -c "source /opt/ros/melodic/setup.bash && \ cd /home && \ git clone https://angelos.p:[email protected]/inno/grpc-comms.git && \ cd grpc-comms && \ mkdir build && \ cd build && \ cmake .. && make"
Cara paling sederhana adalah dengan menggunakan operator titik di tempat sumber, yang merupakan setara sh dari
source
perintah bash :Dari pada:
Menggunakan:
sumber
.
/source
juga menerima parameter posisi setelah nama filesource
atau.
hilang ketika perintah RUN selesai. Lihat: stackoverflow.com/a/40045930/19501Jika Anda menggunakan Docker 1.12 atau lebih baru, gunakan saja
SHELL
!Jawaban singkat:
umum:
untuk python vituralenv:
Jawaban panjang:
dari https://docs.docker.com/engine/reference/builder/#/shell
sumber
Membangun jawaban di halaman ini saya akan menambahkan bahwa Anda harus menyadari bahwa setiap pernyataan RUN berjalan secara independen dari yang lain
/bin/sh -c
dan karena itu tidak akan mendapatkan vars lingkungan yang biasanya bersumber di shell login.Cara terbaik yang saya temukan sejauh ini adalah menambahkan skrip ke
/etc/bash.bashrc
dan kemudian memanggil setiap perintah sebagai bash login.Misalnya Anda dapat menginstal dan mengatur virtualenvwrapper, membuat virtual env, mengaktifkannya ketika Anda menggunakan bash login, dan kemudian menginstal modul python Anda ke dalam env ini:
Membaca manual tentang file startup bash membantu memahami apa yang bersumber saat.
sumber
ADD env-file /etc/profile.d/installerenv.sh
RUN /bin/bash --login -c 'env'
RUN /bin/bash -c 'rm /etc/profile.d/installerenv.sh'
Jika kasus penggunaan seseorang menambahkan lebih banyak variabel lingkungan suntikan ke perspektif bangunan buruh pelabuhan seperti milik saya apakah saya akan merekomendasikan untuk melihat docs.docker.com/compose/yml / # env-file juga.RUN
perintah, yang berarti bahwa Anda tidak dapat menginstal seluruh banyak dependensi proyek dan kemudian menyalin kode sumber dan mengambil keuntungan dari manfaat dari Caching langkah menengah Docker. Ini akan menginstal ulang semua dependensi proyek setiap saat./etc/bashrc
untuk Redhat, bukan/etc/bash.bashrc
seperti yang disebutkan di atas (Untuk Ubuntu)Menurut https://docs.docker.com/engine/reference/builder/#run shell default [Linux]
RUN
adalah is/bin/sh -c
. Anda tampaknya mengharapkan bashism, jadi Anda harus menggunakan "formulir exec"RUN
untuk menentukan shell Anda.Jika tidak, menggunakan "shell form" dari RUN dan menentukan shell yang berbeda akan menghasilkan shell yang bersarang.
Jika Anda memiliki lebih dari 1 perintah yang membutuhkan shell yang berbeda, Anda harus membaca https://docs.docker.com/engine/reference/builder/#shell dan ubah shell default Anda dengan menempatkan ini sebelum perintah RUN Anda:
Akhirnya, jika Anda telah menempatkan sesuatu di pengguna root
.bashrc
file yang Anda butuhkan, Anda dapat menambahkan-l
bendera keSHELL
atauRUN
perintah untuk membuatnya menjadi shell login dan memastikan bahwa itu bersumber.Catatan: Saya sengaja mengabaikan fakta bahwa tidak ada gunanya untuk sumber skrip sebagai satu-satunya perintah dalam RUN.
sumber
SHELL ["/bin/sh", "-c", "-l"]
jadi sumber ~ / .bashrc dll jika Anda memiliki pengaturan lingkungan dari wadah dasar/bin/sh
yang tidak akan menyelesaikan masalah bash yang tidak digunakan. Juga, ketika melakukandocker build
itu tidak mungkin ada sesuatu yang berguna di .bashrc pengguna root yang Anda butuhkan. Tetapi, jika Anda memasukkan sesuatu di sana sebelumnya di Dockerfile (seperti mungkin aJAVA_HOME
, maka ya. Saya akan mencatatnya dalam jawaban saya.Menurut dokumentasi Docker
Lihat https://docs.docker.com/engine/reference/builder/#run
sumber
Jika Anda sudah
SHELL
tersedia, Anda harus pergi dengan jawaban ini - jangan gunakan yang diterima, yang memaksa Anda untuk menaruh sisa file docker dalam satu perintah per komentar ini .Jika Anda menggunakan versi Docker lama dan tidak memiliki akses
SHELL
, ini akan berfungsi selama Anda tidak memerlukan apa pun dari.bashrc
(yang merupakan kasus yang jarang terjadi di Dockerfiles):Perhatikan bahwa
-i
diperlukan untuk membuat bash membaca file rc sama sekali.sumber
Anda mungkin ingin lari
bash -v
untuk melihat apa yang bersumber.Saya akan melakukan hal berikut alih-alih bermain dengan symlink:
RUN echo "source /usr/local/bin/virtualenvwrapper.sh" >> /etc/bash.bashrc
sumber
Saya juga memiliki masalah dalam menjalankan
source
di DockerfileIni berjalan dengan baik untuk membangun CentOS 6.6 kontainer Docker, tetapi memberikan masalah dalam wadah Debian
Beginilah cara saya mengatasinya, mungkin bukan cara yang elegan tapi inilah yang berhasil bagi saya
sumber
Ini mungkin terjadi karena
source
built-in untuk bash daripada biner di suatu tempat di sistem file. Apakah niat Anda untuk skrip yang Anda cari mengubah wadah setelahnya?sumber
Saya akhirnya memasukkan barang-barang saya
.profile
dan bermutasiSHELL
sepertisumber
Jika Anda hanya mencoba menggunakan pip untuk menginstal sesuatu ke virtualenv, Anda dapat memodifikasi PATH env untuk mencari di folder bin virtualenv terlebih dahulu
ENV PATH="/path/to/venv/bin:${PATH}"
Kemudian setiap
pip install
perintah yang mengikuti di Dockerfile akan menemukan / path / ke / venv / bin / pip terlebih dahulu dan menggunakannya, yang akan menginstal ke dalam virtualenv itu dan bukan sistem python.sumber