Kabuk betiğini kullanarak bir docker container içinde bir komut dosyası çalıştırma


88

Docker konteyner kurmak için bir kabuk komut dosyası oluşturmaya çalışıyorum. Komut dosyam şöyle görünüyor:

#!bin/bash

docker run -t -i -p 5902:5902 --name "mycontainer" --privileged myImage:new /bin/bash

Bu betik dosyasını çalıştırmak, kapsayıcıyı yeni çağrılan bir bash içinde çalıştıracaktır.

Şimdi, yukarıda verilen kabuk betiğinin içinde zaten bulunan bir betik dosyasını (test.sh) çalıştırmam gerekiyor. (Örneğin: cd /path/to/test.sh && ./test.sh) Bunu nasıl yapabilirim?


1
Neden WORKDIRve kullanmıyorsunuz CMD?
Dharmit

1
Muhtemelen burada ayrıcalıklı kullanmak istemezsiniz. Bakınız: stackoverflow.com/questions/36425230/…
CMP

Yanıtlar:


123

Aşağıdakileri kullanarak çalışan bir kapta bir komut çalıştırabilirsiniz docker exec [OPTIONS] CONTAINER COMMAND [ARG...]:

docker exec mycontainer /path/to/test.sh

Ve bir bash oturumundan çalıştırmak için:

docker exec -it mycontainer /bin/bash

Oradan komut dosyanızı çalıştırabilirsiniz.


6
Ya önce / bin / bash içine girmem ve sonra bu bash içinde komutu çalıştırmam gerekirse?
zappy

49
Doğrudan ana bilgisayardan yerel bir komut dosyası da çalıştırabilirsiniz. docker exec -i mycontainer bash < mylocal.sh Bu, yerel ana bilgisayar komut dosyasını okur ve onu konteynerin içinde çalıştırır. Bunu başka şeylerle de yapabilirsiniz (tar'a borulu .tgz dosyaları gibi) - sadece kapsayıcı işlem std girdisine yöneltmek için '-i' kullanır.
Marvin

@Marvin PowerShell'deki eşdeğeri nedir? "<" karakteri tanınmıyor.
Nicekiwi

1
Powershell gurusu değilim (neyse ki) ama SO'da dolaştım ve stackoverflow.com/a/11788475/500902'yi buldum . Yani, belki Get-Content mylocal.sh | docker exec -i mycontainer bash. Yine de işe yarayıp yaramadığını bilmiyorum.
Marvin

99

Docker konteynerinizin çalışır durumda olduğunu varsayarsak, komutları şu şekilde çalıştırabilirsiniz:

docker exec mycontainer /bin/sh -c "cmd1;cmd2;...;cmdn"

2
Bu cevabı beğendim; bir komutu veya komut kümesini yürütmek için docker konteynerinde oturum açmanız gerekmez. Teşekkür ederim!
Hatem Jaber

Bunu bir adım öteye nasıl taşıyacağınızı ve tüm komutu ( /bin/sh -c "cmd1; cmd2; ...; cmdn") bir kabuk değişkeninin değeri olarak nasıl geçireceğinizi biliyor musunuz ? Soruyorum, çünkü 'docker run' tek bir komut ve alıntılanmış bir dizeden ziyade tekil alıntılanmamış argümanlar bekliyor gibi görünüyor.
Davida

@meowsqueak: Bu cevap, o konteynere giriş yapmadan önceden oluşturulmuş ve çalışan bir konteynerde birden fazla komutun nasıl çalıştırılacağını söyler, bu otomasyonda yardımcı olur. Ancak (Not: liman işçisi çalıştırma komutu oluşturur ve konteyner başlar) konteyner yaratılış anda birden komutları çalıştırmak istiyorsanız, bu aynı iş parçacığı cevapları takip ederek elde edebilirsiniz stackoverflow.com/a/41363989/777617
Cyclops

Bunun yerine, cmd1tüm bir for-döngüsüne geçmem gerekiyor - ancak döngü ifadesinden ve do ifadesinden ;sonra bekliyor . Tüm for-döngüsünü tek bir komut olarak nasıl çalıştırabilirim ? Mümkün mü? cmd1
Nicholas K

19

Aynı soru için bir cevap arıyordum ve buldum benim için Dockerfile çözümünde ENTRYPOINT .

Dockerfile

...
ENTRYPOINT /my-script.sh ; /my-script2.sh ; /bin/bash

Artık konteyneri başlattığımda komut dosyaları çalıştırılıyor ve komut dosyaları çalıştırıldıktan sonra bash komut istemini alıyorum.


6

Docker görüntünüze yerel bir dizin de bağlayabilir ve komut dosyasını .bashrc . Her yeni kabukta çalıştırılmasını istemediğiniz sürece betiğin işlevlerden oluşması gerektiğini unutmayın. (Bu güncel değil, güncelleme bildirimine bakın.)

Docker örneğinin dışında komut dosyasını güncelleyebilmek için bu çözümü kullanıyorum. Bu şekilde, değişiklik olursa görüntüyü yeniden çalıştırmam gerekmiyor, sadece yeni bir kabuk açıyorum. (Bir kabuğu yeniden açmaktan kurtuldunuz - güncelleme bildirimine bakın)

Mevcut dizininizi şu şekilde bağlayabilirsiniz:

docker run -it -v $PWD:/scripts $my_docker_build /bin/bash

Artık geçerli dizininiz /scriptsdocker örneğinize bağlıdır.

(Güncel değil) .bashrcDeğişikliklerinizi kaydetmek için çalışma resminizi bu komutla uygulayın:

docker commit $container_id $my_docker_build

Güncelleme

Her değişiklik için yeni bir kabuk açmak için sorunu çözmek için şimdi aşağıdakileri yapıyorum:

Dockerfile'ın kendisine ekliyorum RUN echo "/scripts/bashrc" > /root/.bashrc". İçeridezshrc betikler dizinini yola aktarıyorum. Scripts dizini artık bir yerine birden çok dosya içeriyor. Artık her değişiklikte bir alt kabuk açmadan tüm betikleri doğrudan arayabiliyorum.

BTW geçmiş dosyasını konteynerinizin dışında da tanımlayabilirsiniz. Bu şekilde artık bir bash değişikliğine bağlı kalmak gerekli değildir.


Çok geç..! @javier zaten basit bir çözüm gösteriyor !! Bunun daha iyi olduğunu hissediyorum.
zappy

2
@zappy, javier çözümü bu sorunu benim için uygun bir şekilde çözmedi - ancak benim çözümüm çözdü, benzer bir sorunu olanların docker görüntülerini yeniden başlatmak istemedikleri için ilginç olacağını düşündüm. ihtiyaç duydukları işlevleri görüntüleyin. Örneğin, bir geliştirici kümesini döndürmek için aynı anda birden fazla docker görüntüsü kullanırsanız, bunları her zaman yeniden başlatmak istemezsiniz.
Devpool

3

Çalışan bir kap istemiyorsanız (veya sahip değilseniz), komut dosyanızı doğrudan runkomutla çağırabilirsiniz .

Yinelemeli tty -i -tbağımsız değişkenlerini kaldırın ve şunu kullanın:

    $ docker run ubuntu:bionic /bin/bash /path/to/script.sh

Bu, diğer komut dosyaları için de çalışacaktır (test etmedi):

    $ docker run ubuntu:bionic /usr/bin/python /path/to/script.py


0

Aynı komutu birden çok örnekte çalıştırmak istiyorsanız, bunu yapabilirsiniz:

for i in c1 dm1 dm2 ds1 ds2 gtm_m gtm_sl; do docker exec -it $i /bin/bash -c "service sshd start"; done
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.