Hizmetleri başlattıktan sonra Docker kapsayıcısını nasıl çalışır halde tutabilirsiniz?


156

Yapmaya çalıştığım aynı şeyi yapan bir sürü öğretici gördüm, ancak bazı nedenlerden dolayı Docker kaplarımdan çıkıyor. Temel olarak, bir web sunucusu ve bir Docker kapsayıcısının içinde birkaç arka plan oluşturuyorum. Bunun son bölümlerini run-all.shDockerfile'imde CMD ile çalıştırdığım bir bash betiği ile yapıyorum. run-all.shbuna benzer:

service supervisor start
service nginx start

Ve Dockerfile'ımın içine şu şekilde başlıyorum:

CMD ["sh", "/root/credentialize_and_run.sh"]

Bir şeyleri manuel olarak çalıştırdığımda (yani -i -t / bin / bash ile görüntüye devam ederken) hizmetlerin hepsinin doğru şekilde başladığını görebiliyorum ve görüntüyü çalıştırdığımda her şey doğru çalışıyor gibi görünüyor, ancak bir kez çıkıyor süreçlerimi başlatmayı bitiriyor. Süreçlerin süresiz olarak çalışmasını istiyorum ve anladığım kadarıyla, konteynerin bunun gerçekleşmesi için çalışmaya devam etmesi gerekiyor. Yine de koştuğumda docker ps -aşunu görüyorum:

➜  docker_test  docker ps -a
CONTAINER ID        IMAGE                            COMMAND                CREATED             STATUS                      PORTS               NAMES
c7706edc4189        some_name/some_repo:blah   "sh /root/run-all.sh   8 minutes ago       Exited (0) 8 minutes ago                        grave_jones

Ne oluyor? Neden çıkıyor? Bilmek için bash betiğimin sonuna bir süre döngü koyabileceğimi biliyorum, ama çıkmasını engellemenin doğru yolu nedir?


1
hizmetlerin bağlantı noktalarını dışarıya mı açıyorsunuz (liman işleyicisine -p seçeneği)? (elbette bu onların çıkmasını engellemez)
ribamar

1
Ben Dockerfile benim ENTRYPOINT kullanıyordum ve ENTRYPOINT (benim init betiğim) tanımlanan komut dosyası çalıştırıldıktan sonra günlüklerde ortaya çıktı ama benim kapsayıcı çıkış gibi görünüyordu. Bu nedenle, ENTRYPOINT yerine, komut dosyasını çalıştırmak için RUN komutunu kullandım ve kapsayıcı hala arka planda çalışıyor.
ypahalajani

Yanıtlar:


50

Docker kaplarınızı bu şekilde tasarlamalısınız.

Bir Docker kapsayıcısı tasarlarken, yalnızca bir işlem (yani, Nginx için bir konteynır ve yönetici veya çalıştırdığı uygulama için bir kabınız olmalıdır); ayrıca, bu işlem ön planda yürütülmelidir.

İşlemin kendisi çıktığında kap "çıkacaktır" (sizin durumunuzda, bu işlem bash betiğinizdir).


Ancak, Docker kapsayıcısında gerçekten birden fazla hizmet çalıştırmanız gerekiyorsa (veya istiyorsanız) , aşağıdakileri kullanan "Docker Base Image" dan başlamayı düşünün.runit sözde başlatma işlemi olarak kullanılan ( runitNginx ve Supervisor çalışırken çevrimiçi kalacaktır) diğer süreçleriniz işlerini yaparken ön plandadır.

Önemli dokümanları var, bu yüzden makul bir şekilde yapmaya çalıştığınız şeyi başarabilmelisiniz.


1
Neden yalnızca bir hizmetin çalışmam gerektiğini açıklayabilir misiniz? Gerekirse süpervizöre nginx ekleyebilirim, ancak bunun neden gerekli olduğundan emin değilim.
Eli

3
@Eli Kısa yanıt Docker'ın bu şekilde çalışmasıdır. Docker, konteyner başına yalnızca bir işlem (ve alt öğeleri) yürütür. Bu işlemin gerçek bir uygulama işlemi olması önerilir (böylece çıkarsa Docker bilir), ancak gerçekten bu süreç olarak süpervizörü kullanabilirsiniz. Denetçiyi, --nodaemonseçenek üzerinden yapılan ön planda çalışacak (yani arka plana geçmeyecek şekilde) yapılandırmanız gerektiğini unutmayın .
Thomas Orozco

1
@Eli Bu Docker blog yayını , birden çok işlemin (ve genel olarak konuşursak, bir kapsayıcıyı "küçük VPS" olarak görüntülemenin) çalıştırılmasının yetersiz olduğunu gösterir. Sizin durumunuzda, yorum dizisi büyük olasılıkla gerçek blog gönderisinden daha alakalı olacaktır.
Thomas Orozco

1
Docker temel görüntüsü, birçok kurumsal sorun için korkunç bir çözümdür, çünkü birkaç ciddi şirket ubuntu kullanır ve bunun yerine RHEL / Centos ağacı tercih eder.
Yazılım Mühendisi

9
"Birkaç ciddi şirket" savunulamaz görünüyor. İşletim sistemi seçimi tamamen kullanım durumuna dayanmaktadır. Herhangi bir şirketin dahili geliştirici kullanımı, dahili çalışan kullanımı, satış desteği, evreleme, POC'ler ve son olarak üretim (ve hatta bu belirsiz bir terim) dahil olmak üzere birçok farklı ortamı vardır. OP'nin kullanım durumundan bahsettiğine inanmıyorum, (nitpicky olduğu için özür dilerim), ancak bu tür bir yorum, neden olduğu konusunda hiçbir argüman olmadan yüksek oranda tartışılmış bilgiyi yayan türden gibi görünüyor.
John Carrell

155

Dockerfile kullanıyorsanız şunları deneyin:

ENTRYPOINT ["tail", "-f", "/dev/null"]

(Açıkçası bu sadece geliştirme amaçlıdır, bir işlemi çalıştırmadığı sürece bir konteynırı canlı tutmanıza gerek yoktur, örn. Nginx ...)


5
Ben kullanıyordum CMD["sleep", "1d"]ama çözüm daha iyi görünüyor
George Pligoropoulos

@GeorgiosPligoropoulos bu çizgide sıkışacak; belki arka planda çalışan çalışacak
Prashanth Sams

5
Ayrıca kullanabilirsiniz CMD["sleep", "infinity"].
Romain

5
ya da 'kedi' ama insanlar bunun hayvan istismarı olduğunu söyleyebilir. xD
lawphotog

Giriş noktası komut dosyanızı ile bitirebilirsiniz, exec tail -f /dev/nullancak giriş noktası tailolarak kullanmak yanlış bir yanıttır.
Torsten Bronger

86

Aynı problemi yaşadım ve konteynırınızı -tve -dbayrağıyla çalıştırıyorsanız, çalışmaya devam ettiğini öğrendim .

docker run -td <image>

Bayrakların yaptıkları (göre docker run --help):

-d, --detach=false         Run container in background and print container ID
-t, --tty=false            Allocate a pseudo-TTY

En önemlisi -tbayrak. -dkapsayıcıyı arka planda çalıştırmanıza izin verir.


3
Bunu yeniden üretemem. Lütfen bir örnek verir misiniz? Bunun çalışması için Dockerfile hakkında özel bir şey var mı (örneğin: CMD)?
Matheus Santana

2
Bu benim için işe yaramadı. Komutu docker logs <image>, docker kapsayımımın çıkmasına neden olan bir hata olduğundan emin olmak için kullandım . Çıkış durumu 0ve son çıktı sunucum lighttpdçalışıyor olduğunu confimation :[ ok ] Starting web server: lighttpd.
ob1

Docker ile bir süredir çalışmıyorum. Bu nedenle komut satırı arabiriminin değişmesi ve bu komutun artık çalışmaması mümkündür.
arne.z

4
Bunun gerçekten de en son docker sürümü ile çalıştığını doğrulayabilirim. Bu oturuma daha sonra eklemek isterseniz, -dit kullanmak da işe yarayacaktır.
John Hamilton

1
@Bir komut dosyası, start.sh dosyasının sonuna bir tty'yi kabul etmez, ekleme exec bashveya exec shbash yüklü değilse. Sonra -t bayrağını kullanabilirsiniz
123

43

Bunun nedeni kabuk betiğinin önce PID 1 olarak çalıştırılması ve tamamlandığında PID 1'in gitmiş olması ve docker'ın yalnızca PID 1 açıkken çalışmasıdır.

Her şeyi yapmak için süpervizörü kullanabilirsiniz, eğer "-n" bayrağı ile çalıştırılırsa, arka planını değiştirmemesi söylenir, böylece ilk işlem olarak kalacaktır:

CMD ["/usr/bin/supervisord", "-n"]

Ve supervisord.conf'unuz:

[supervisord]
nodaemon=true

[program:startup]
priority=1
command=/root/credentialize_and_run.sh
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
autorestart=false
startsecs=0

[program:nginx]
priority=10
command=nginx -g "daemon off;"
stdout_logfile=/var/log/supervisor/nginx.log
stderr_logfile=/var/log/supervisor/nginx.log
autorestart=true

Daha sonra istediğiniz kadar başka sürece sahip olabilirsiniz ve süpervizör gerektiğinde yeniden başlatır.

Bu şekilde nginx ve php5-fpm'ye ihtiyaç duyabileceğiniz durumlarda süpervizörü kullanabilirsiniz ve bunları ayırmak pek mantıklı değildir.


PID 1 biterse docker konteyneri çalışmayı durdurursa bu dokümanlar nerelerde bulunur?
8oh8

@ 8oh8 Temelde işlem ad alanları böyle çalışır; "tüm kapların altında yatan şey" kadar Docker'a özgü değildir. Gönderen man7.org/linux/man-pages/man7/pid_namespaces.7.html :If the "init" process of a PID namespace terminates, the kernel terminates all of the processes in the namespace via a SIGKILL signal. This behavior reflects the fact that the "init" process is essential for the correct operation of a PID namespace.
dannysauer

40

catkapsayıcıyı çalışmaya devam ettirmek için [@ kullanıcı girişini beklemekten başka hiçbir şey yapmadan] bro @ Sa'ad tarafından belirtildiği gibi herhangi bir argüman olmadan düz çalıştırabilirsiniz (Jenkins 'Docker eklentisi aynı şeyi yapar)


yanıtı: ancak docker-compose (daemonized değil) size konteyner iş akışını göstermek için kullanıldığını anlamak, bu yüzden başlatılan hizmetlerin günlük dosyalarını kuyruk kullanışlı olabilir. şerefe
Serge Velikanov

1
veya cat. jenkin'in docker eklentisi bunu yapar.
Sa'ad

12

daemon off;Size nginx.conf eklediğinizden emin olun veya CMD ["nginx", "-g", "daemon off;"]resmi nginx resmine göre çalıştırın.

Ardından kapsayıcısının çıkmasını önleyecek hem süpervizörü hizmet olarak hem de ön plan işlemi olarak nginx'i çalıştırmak için aşağıdakileri kullanın

service supervisor start && nginx

Bazı durumlarda, kapsayıcınızda birden fazla işlem olması gerekir, bu nedenle kapsayıcıyı tam olarak bir işlem yapmaya zorlamak işe yaramaz ve dağıtımda daha fazla sorun oluşturabilir.

Yani ödünleşmeleri anlamanız ve kararınızı buna göre vermeniz gerekiyor.


7

Motivasyon:

Orada bir liman işçisi kabın içine birden çok çalışan işlem hiçbir şey yanlış . Bir kişi docker'ı hafif bir VM olarak kullanmayı seviyorsa, öyle olsun. Diğerleri uygulamalarını mikro hizmetlere bölmeyi sever. Bana göre: Bir kapta bir LAMBA yığını? Harika.

Cevap:

Phusion temel görüntü gibi iyi bir temel görüntü ile sopa . Başkaları da olabilir. Lütfen yorumlayın.

Ve bu sadece süpervizör için bir başka yalvarış. Çünkü füzyon tabanı görüntüsü cron ve yerel ayar gibi bazı şeylerin yanında süpervizör sağlıyor. Bu kadar hafif bir VM çalıştırırken kurulum yapmayı sevdiğiniz şeyler. Değeri için de konteyner içine ssh bağlantıları sağlar.

Bu temel docker çalıştırma deyimini verirseniz, phusion görüntüsünün kendisi başlar ve çalışmaya devam eder:

moin@stretchDEV:~$ docker run -d phusion/baseimage
521e8a12f6ff844fb142d0e2587ed33cdc82b70aa64cce07ed6c0226d857b367
moin@stretchDEV:~$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS
521e8a12f6ff        phusion/baseimage   "/sbin/my_init"     12 seconds ago      Up 11 seconds

Ya da ölü basit:

Bir temel görüntü sizin için değilse ... Hızlı CMD'nin çalışmasını sağlamak için bash için böyle bir şey varsayalım:

CMD exec /bin/bash -c "trap : TERM INT; sleep infinity & wait"

Veya meşgul kutusu için bu:

CMD exec /bin/sh -c "trap : TERM INT; (while true; do sleep 1000; done) & wait"

O Bunun nedeni, güzel hemen çıkmak bir üstünde docker stop. Sadece düz sleepveya catkap çıkmadan birkaç saniye sürecek.


PostgreSQL 11'i yüklemek için centos7 temel görüntüsünü özelleştirdim. Bunu, / usr / pgsql-11 / bin / pg_ctl çağrısıyla başlatırsınız, ancak sunucu çalıştıktan sonra pg_ctl çıkar. Tuzak kullanma önerileriniz harika çalıştı; benim komut dosyası son satır pgstartwait.sh
Alchemistmatt

6

Bir değişkende ngnix işleminin PID'sini (örneğin $ NGNIX_PID) yakalayın ve giriş noktası dosyasının sonunda

wait $NGNIX_PID 

Bu şekilde, konteyneriniz ngnix hayatta olana kadar çalışmalıdır, ngnix durduğunda konteyner de durur


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.