วิธีเริ่มบริการโดยอัตโนมัติเมื่อเรียกใช้คอนเทนเนอร์นักเทียบท่า?


157

ฉันมีDockerfileเพื่อติดตั้งเซิร์ฟเวอร์ MySQL ในที่เก็บซึ่งฉันเริ่มต้นเช่นนี้:

sudo docker run -t -i 09d18b9a12be /bin/bash

แต่บริการ MySQL ไม่เริ่มทำงานโดยอัตโนมัติฉันต้องเรียกใช้ด้วยตนเอง (จากภายในคอนเทนเนอร์):

service mysql start

ฉันจะเริ่มบริการ MySQL โดยอัตโนมัติเมื่อฉันเรียกใช้คอนเทนเนอร์นักเทียบท่าได้อย่างไร


1
ไม่สำหรับบริการง่าย ๆ เพียงอย่างเดียวไม่จำเป็นต้องใช้หัวหน้างานมันทำให้ซับซ้อนสำหรับผู้ใช้เริ่มต้น
Larry Cai

8
คุณอาจต้องการคัดลอกไฟล์ dockerfile ที่นี่แทนที่จะลิงค์ไปยังไฟล์ที่ไม่มีอยู่อีกต่อไป
neo112

บทความนักเทียบท่าบน supervisord อยู่ที่นี่แล้ว: docs.docker.com/config/containers/multi-service_container ฉันใช้คำสั่ง && tail เพื่อให้บริการของฉันทำงาน - แต่จำเป็นต้องเพิ่ม "--cap-add SYS_PTRACE" ไปยังนักเทียบท่า เรียกใช้คำสั่ง
Ted Cahall

คำตอบ:


205

ก่อนมีปัญหาในของคุณDockerfile:

RUN service mysql restart && /tmp/setup.sh

อิมเมจของ Docker จะไม่บันทึกกระบวนการที่กำลังทำงานอยู่ ดังนั้นRUNคำสั่งของคุณจะดำเนินการเฉพาะในช่วงdocker buildเฟสและหยุดหลังจากการสร้างเสร็จสมบูรณ์ คุณต้องระบุคำสั่งแทนเมื่อคอนเทนเนอร์เริ่มต้นโดยใช้คำสั่งCMDหรือENTRYPOINTคำสั่งด้านล่าง:

CMD mysql start

ประการที่สองคอนเทนเนอร์นักเทียบท่าต้องการกระบวนการ (คำสั่งสุดท้าย) เพื่อให้ทำงานต่อไปมิฉะนั้นคอนเทนเนอร์จะออก / หยุด ดังนั้นservice mysql startคำสั่งปกติไม่สามารถใช้โดยตรงใน Dockerfile

สารละลาย

มีวิธีทั่วไปสามวิธีในการทำให้กระบวนการทำงานต่อไป:

  • ใช้serviceคำสั่งและผนวกคำสั่งที่ไม่สิ้นสุดหลังจากนั้นtail -F

    CMD service mysql start && tail -F /var/log/mysql/error.log
    

สิ่งนี้มักเป็นที่ต้องการเมื่อคุณมีบริการเดียวที่กำลังทำงานเพราะทำให้สามารถเข้าถึงบันทึกเอาต์พุตที่นักเทียบท่าได้

  • หรือใช้คำสั่งเบื้องหน้าเพื่อทำสิ่งนี้

    CMD /usr/bin/mysqld_safe
    

สิ่งนี้ใช้ได้เฉพาะในกรณีที่มีสคริปต์เช่นmysqld_safeนั้น

  • หรือรวมสคริปต์ของคุณเข้าstart.shด้วยกัน

    CMD /start.sh
    

สิ่งนี้จะดีที่สุดหากคำสั่งต้องดำเนินการตามลำดับขั้นตอน/start.shควรดำเนินการต่อ

บันทึก

สำหรับมือใหม่ที่supervisordไม่แนะนำให้ใช้ สุจริตมันเกินความจริง มันจะดีกว่ามากที่จะใช้บริการเดียว / คำสั่งเดียวสำหรับภาชนะ

BTW: โปรดตรวจสอบhttps://registry.hub.docker.comสำหรับรูปภาพ mysql docker ที่มีอยู่สำหรับการอ้างอิง


คุณจะเริ่มบริการได้อย่างไรเมื่อเริ่มต้นใน container docker
K - ความเป็นพิษใน SO กำลังเพิ่มขึ้น

3
@KarlMorrisondocker exec -it <CONTAINER NAME> mysql /etc/init.d/mysqld restart
kaiser

1
ฉันจะไม่แนะนำให้บันทึกข้อผิดพลาดของ tail'ing MySQL เพื่อตรวจสอบว่าฐานข้อมูลทำงานอยู่หรือไม่ ในการตั้งค่า mysqld ส่วนใหญ่เซิร์ฟเวอร์จะกู้คืนจากข้อผิดพลาดของ Soe และในขั้นตอนการทำบันทึกข้อผิดพลาดจะถูกปิดแล้วเปิดใหม่ ฉันยังไม่แน่ใจว่าหางของคุณ -F จะทำงานให้คุณในทุกกรณีหรือบางกรณี
Brian Aker

ฉันไม่แน่ใจว่าทำไม แต่ตัวเลือกโซลูชันแรกทำงานได้ดีสำหรับสคริปต์บริการ เมื่อคุณไม่ใช้ tail มันจะล้มเหลวแม้ว่าจะเริ่มให้บริการแล้ว (อย่างน้อยก็สำหรับบริการ tomcat7) ด้วยหางมันทำงาน สำหรับทั้งสองกรณีคุณจำเป็นต้องใช้สวิตช์ cap_add (- cap-add SYS_PTRACE สำหรับการทำงาน) อย่างน้อย SYS_PTRACE
zhrist

1
ไม่ดูเพิ่มเติมในstackoverflow.com/questions/46800594/…
Larry Cai

73

ในของคุณDockerfileเพิ่มที่บรรทัดสุดท้าย

ENTRYPOINT service ssh restart && bash

มันใช้งานได้สำหรับฉัน

และนี่คือผลลัพธ์ที่ได้:

root@ubuntu:/home/vagrant/docker/add# docker run -i -t ubuntu
 * Restarting OpenBSD Secure Shell server sshd   [ OK ]                                                                      
root@dccc354e422e:~# service ssh status
 * sshd is running

2
นี่เป็นสิ่งที่ดี แต่ฉันคิดว่าคุณไม่สามารถมีตู้คอนเทนเนอร์แยกออกด้วยวิธีนี้
mdob

1
มันใช้งานได้ดีสำหรับฉัน ฉันมีปัญหาในการเริ่มใช้ Nginx 1.8 โดยอัตโนมัติ คุณอาจพบว่าการเพิ่มประโยชน์ต่อไปนี้: RUN echo "daemon off;" >> /etc/nginx/nginx.conf RUN ln -sf / dev / stdout /var/log/nginx/access.log RUN ln -sf / dev / stderr /var/log/nginx/error.log
Lionel Morrison

1
มีข้อเสียในการแก้ไขปัญหานี้หรือไม่?
srph

2
การเริ่มใช้ Bash ในที่สุดก็เป็นความคิดที่ไม่ดีเมื่อคุณต้องการหยุดการให้บริการของคุณอย่างสง่างามเพราะในกรณีนี้นักเทียบท่าไม่สามารถหยุดdocker stopหรือจัดการได้docker restartอย่างสง่างามเพียงแค่ถูกฆ่า
Mohammed Noureldin

ฉันกำลังทำงานกับผู้แบ่งบรรจุเพื่อสร้างภาพนักเทียบท่าและดูเหมือนว่าจะแก้ไขปัญหาของฉันกับ conaitner ในไฟล์ packer "changes": ["ENTRYPOINT service nginx start && / bin / bash"]
karthik101

8

! ง่าย เพิ่มที่ส่วนท้ายของ dockerfile:

ENTRYPOINT service mysql start && /bin/bash

นี่คือคำตอบที่ดีที่สุดที่แก้ปัญหา Docker Container ปัจจุบันของฉัน: Docker version 18.09.7, build 2d0083dโดยไม่ต้อง&& /bin/bashใช้บริการจะหยุดทันที
Long

7

มีอีกวิธีที่จะทำสิ่งนั้นที่ฉันพบเสมอว่าอ่านง่ายขึ้น

พูดว่าคุณต้องการเริ่มต้น Rabbitmq และ mongodb เมื่อคุณเรียกใช้แล้วคุณCMDจะมีลักษณะเช่นนี้:

CMD /etc/init.d/rabbitmq-server start && \
    /etc/init.d/mongod start

เนื่องจากคุณสามารถมีได้เพียงหนึ่งCMDต่อDockerfileเคล็ดลับคือการเชื่อมคำแนะนำทั้งหมดที่มี&&และใช้\สำหรับแต่ละคำสั่งที่จะเริ่มต้นบรรทัดใหม่

หากคุณต้องการเพิ่มคำสั่งจำนวนมากฉันขอแนะนำให้คุณใส่คำสั่งทั้งหมดลงในไฟล์สคริปต์และเริ่มต้นเหมือน @ larry-cai

CMD /start.sh

3

ในกรณีของฉันฉันมี PHP เว็บแอปพลิเคชันที่ให้บริการโดย Apache2 ภายในคอนเทนเนอร์นักเทียบท่าที่เชื่อมต่อกับฐานข้อมูลแบ็กเอนด์ MYSQL โซลูชันของ Larry Cai ทำงานร่วมกับการดัดแปลงเล็กน้อย ฉันสร้างentrypoint.shไฟล์ที่ฉันจัดการบริการอยู่ ฉันคิดว่าการสร้างentrypoint.shเมื่อคุณมีมากกว่าหนึ่งคำสั่งที่จะดำเนินการเมื่อคอนเทนเนอร์ของคุณเริ่มต้นขึ้นเป็นวิธีที่สะอาดเพื่อ bootstrap docker

#!/bin/sh

set -e

echo "Starting the mysql daemon"
service mysql start

echo "navigating to volume /var/www"
cd /var/www
echo "Creating soft link"
ln -s /opt/mysite mysite

a2enmod headers
service apache2 restart

a2ensite mysite.conf
a2dissite 000-default.conf
service apache2 reload

if [ -z "$1" ]
then
    exec "/usr/sbin/apache2 -D -foreground"
else
    exec "$1"
fi

เพียงวางไว้ข้าง Dockerfile ของคุณ จากนั้นใน Dockerfile ของคุณคุณควรมีคำสั่งที่คัดลอกไฟล์นี้ไปยังตำแหน่งที่ต้องการ จากนั้นให้คุณชี้ENTRYPOINT ['your location']คำแนะนำไปยังไฟล์สคริปต์ อย่าลืมตั้งค่าการอนุญาตให้ใช้งานสคริปต์ของคุณ COPY entrypoint.sh /entrypoint.sh RUN chmod 755 /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]. ในตัวอย่างนี้ฉันคัดลอก entry point ของฉันไปยัง root directory ใน container docker
นาย Doomsbuster

Dockerfile อยู่ที่ไหน
Viktor Joras

3

ฉันมีปัญหาเดียวกันเมื่อฉันต้องการเริ่มบริการ ssh โดยอัตโนมัติ ฉันพบว่าผนวก

/etc/init.d/ssh เริ่มต้น
ถึง
~ / .bashrc
สามารถแก้ไขได้ แต่มีเพียงคุณเท่านั้นที่เปิดด้วย bash ที่จะทำ


1

ฉันเพิ่มรหัสต่อไปนี้ใน /root/.bashrc เพื่อเรียกใช้รหัสเพียงครั้งเดียว

โปรดส่งคอนเทนเนอร์ไปยังรูปภาพก่อนเรียกใช้สคริปต์นี้มิฉะนั้นไฟล์ 'docker_services' จะถูกสร้างขึ้นในภาพและจะไม่มีการเรียกใช้บริการใด ๆ

if [ ! -e /var/run/docker_services ]; then
    echo "Starting services"
    service mysql start
    service ssh start
    service nginx start
    touch /var/run/docker_services
fi

1

นี่คือวิธีที่ฉันจะเริ่มบริการ MySQL โดยอัตโนมัติเมื่อใดก็ตามที่คอนเทนเนอร์นักเทียบท่าทำงาน

ในกรณีของฉันฉันต้องเรียกใช้ไม่เพียง แต่ MySQL แต่ยังรวมถึง PHP, Nginx และ Memcached

ฉันมีบรรทัดต่อไปนี้ใน Dockerfile

RUN echo "daemon off;" >> /etc/nginx/nginx.conf
EXPOSE 80
EXPOSE 3306
CMD service mysql start && service php-fpm start && nginx -g 'daemon off;' && service memcached start && bash

การเพิ่ม&& bashจะทำให้ Nginx, MySQL, PHP และ Memcached ทำงานอยู่ในคอนเทนเนอร์


1

มันใช้งานไม่ได้ CMD service mysql start && /bin/bash

มันใช้งานไม่ได้ CMD service mysql start ; /bin/bash ;

- ฉันเดาว่าโหมดการโต้ตอบจะไม่รองรับการทำงานเบื้องหน้า

งานนี้ !! CMD service nginx start ; while true ; do sleep 100; done;

งานนี้ !! CMD service nginx start && tail -F /var/log/nginx/access.log

ระวังคุณควรใช้docker run -p 80:80 nginx_bashโดยไม่มีพารามิเตอร์คำสั่ง


0

เอกสารต่อไปนี้จากเว็บไซต์ Docker แสดงวิธีการใช้บริการ SSH ในคอนเทนเนอร์นักเทียบท่า ควรปรับให้เข้ากับบริการของคุณได้ง่าย:

รูปแบบของคำถามนี้ได้รับการถามที่นี่ด้วย:


เครื่องมือ nsenter เป็นอีกวิธีหนึ่งที่จะใส่ในภาชนะโดยไม่ต้องมีการติดตั้งเซิร์ฟเวอร์ SSH: github.com/jpetazzo/nsenter แต่วิธีการนี้ต้องการการเข้าถึงโฮสต์ Docker ของคุณ (โดยปกติแล้วการเข้าถึง SSH นั้นเพียงพอแล้ว)
Fabien Balageas

ลิงก์docs.docker.com/sorry/#/examples/running_ssh_serviceไม่ทำงาน คุณช่วยอัพเดทได้ไหม
Ankur

0
docker export -o <nameOfContainer>.tar <nameOfContainer>

อาจต้องตัดคอนเทนเนอร์ที่มีอยู่โดยใช้พรุนเทียบท่า ...

นำเข้าพร้อมการแก้ไขที่จำเป็น:

cat <nameOfContainer>.tar | docker import -c "ENTRYPOINT service mysql start && /bin/bash" - <nameOfContainer>

รันคอนเทนเนอร์ด้วยตัวเลือกรีสตาร์ทเสมอเพื่อให้แน่ใจว่าจะดำเนินการต่อโดยอัตโนมัติหลังจากที่โฮสต์ / daemon รีไซเคิล:

docker run -d -t -i --restart always --name <nameOfContainer> <nameOfContainer> /bin/bash

ด้านหมายเหตุ: ในความคิดของฉันที่เหมาะสมคือการเริ่มต้นเพียงบริการ cron ออกจากภาชนะที่สะอาดที่สุดเท่าที่จะเป็นไปได้แล้วเพียงแค่ปรับเปลี่ยน crontab หรือ cron.hourly, .daily ฯลฯ ... ด้วยสคริปต์ตรวจสอบ / ตรวจสอบที่สอดคล้องกัน เหตุผลคือคุณพึ่งพา daemon เพียงตัวเดียวและในกรณีที่มีการเปลี่ยนแปลงจะง่ายขึ้นด้วย ansible หรือ puppet เพื่อแจกจ่ายสคริปต์ cron แทนการติดตามบริการที่เริ่มต้นเมื่อเริ่มระบบ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.