Docker Compose ให้คอนเทนเนอร์ทำงานต่อไป


94

ฉันต้องการเริ่มบริการด้วย Docker-compose และทำให้คอนเทนเนอร์ทำงานต่อไปเพื่อที่ฉันจะได้รับที่อยู่ IP ผ่าน 'นักเทียบท่าตรวจสอบ' อย่างไรก็ตามคอนเทนเนอร์มักจะออกทันทีหลังจากเริ่มต้นระบบ

ฉันพยายามเพิ่ม "command: [" sleep "," 60 "]" และอื่น ๆ ใน docker-compose.yml แต่เมื่อใดก็ตามที่ฉันเพิ่มบรรทัดด้วย "command: ... " ฉันไม่สามารถเรียก "docker-compose up" ได้ เนื่องจากฉันจะได้รับข้อความ "ไม่สามารถเริ่มคอนเทนเนอร์ ..... ข้อผิดพลาดของระบบ: อักขระที่ไม่ถูกต้อง 'k' กำลังมองหาจุดเริ่มต้นของค่า"

ฉันยังลองเพิ่ม "CMD sleep 60" และไม่มีอะไรใน Dockerfile แต่ดูเหมือนว่าคำสั่งเหล่านี้จะไม่ถูกเรียกใช้

มีวิธีง่ายๆในการทำให้คอนเทนเนอร์คงอยู่หรือแก้ปัญหาอย่างใดอย่างหนึ่งของฉันได้หรือไม่?

แก้ไข: นี่คือไฟล์เขียนที่ฉันต้องการเรียกใช้:

version: '2'
services:
  my-test:
    image: ubuntu
    command: bash -c "while true; do echo hello; sleep 2; done"

มันใช้งานได้ดีถ้าฉันเริ่มสิ่งนี้ด้วยนักเทียบท่าเขียนภายใต้ OS X แต่ถ้าฉันลองแบบเดียวกันภายใต้ Ubuntu 16.04 มันทำให้ฉันมีข้อความแสดงข้อผิดพลาดข้างต้น

หากฉันลองใช้วิธีนี้กับ Dockerfile Dockerfile จะมีลักษณะดังนี้:

FROM ubuntu:latest
CMD ["sleep", "60"]

ซึ่งดูเหมือนไม่ได้ทำอะไร

แก้ไข 2: ฉันต้องแก้ไขตัวเองปรากฎว่าเป็นปัญหาเดียวกันกับ Dockerfile และ docker-compose.yml: ทุกครั้งที่ฉันเพิ่ม "CMD ... " ลงใน Dockerfile หรือเพิ่ม "command ... " ลงใน ไฟล์เขียนฉันได้รับข้อผิดพลาดด้านบนด้วยอักขระที่ไม่ถูกต้อง ถ้าฉันลบทั้งสองคำสั่งมันก็ทำงานได้อย่างไม่มีที่ติ


1
โปรดรวม docker-compose.yml, Dockerfile และสคริปต์ใด ๆ ที่คุณกำลังพยายามดีบัก
BMitch

การอภิปรายที่เกี่ยวข้องสำหรับผู้ที่สนใจ: เวิร์กโฟลว์การพัฒนาสำหรับเซิร์ฟเวอร์และไคลเอนต์โดยใช้ Docker Compose?
blong

คำตอบ:


119

เพื่อให้คอนเทนเนอร์ทำงานต่อไปเมื่อคุณเริ่มต้นdocker-composeใช้งานให้ใช้คำสั่งต่อไปนี้

command: tail -F anything

ดังนั้น docker-compose.yml ของคุณจึงกลายเป็น

version: '2'
services:
  my-test:
    image: ubuntu
    command: tail -F anything

และคุณสามารถรันเชลล์เพื่อเข้าสู่คอนเทนเนอร์โดยใช้คำสั่งต่อไปนี้

docker exec -i -t composename_my-test_1 bash

ซึ่งcomposenameเป็นชื่อที่docker-composeprepends ตู้คอนเทนเนอร์ของคุณ


1
คุณจะหยุดภาชนะได้อย่างไรเมื่อทำเสร็จแล้ว? มีคำสั่งประเภท Ctrl + C, Ctrl + Z หรือไม่? ตอนนี้ฉันต้องปิดเครื่องเพื่อลาออก
mac10688

หากคุณอยู่ในคอนเทนเนอร์คุณสามารถพิมพ์exitเพื่อกลับไปที่เครื่องโฮสต์ของคุณ หากคุณอยู่ในโฮสต์ของคุณคุณสามารถหยุดคอนเทนเนอร์โดยใช้ Docker ( docker stop composename_my-test_1) หรือ Docker Compose ( docker-compose stop)
Nick Settje

2
@ Alexis.Rolland หากคุณยินดีที่จะถามคำถาม SO ใหม่และแบ่งปันรายละเอียดเพิ่มเติมฉันยินดีเป็นอย่างยิ่งที่จะดู ฉันเดาว่าข้อผิดพลาดของคุณมีบางอย่างเกี่ยวข้องกับภายในของคอนเทนเนอร์ใดคอนเทนเนอร์หนึ่งของคุณซึ่งต่างจากปัญหากับ Docker หรือระบบปฏิบัติการโฮสต์ของคุณ
Nick Settje

1
@ mac10688 หากไม่มีข้อความแจ้งในเซสชันคอนเทนเนอร์ที่แนบมาของคุณให้ลอง ctrl-d เพื่อแยกออก
Stark

5
/dev/nullจะดีกว่าสำหรับanythingการอ้างอิงคำสั่ง tail stackoverflow.com/a/48732671/248616
Nam G VU

80

คุณสามารถใช้ttyตัวเลือกการกำหนดค่า

version: '3'

services:
  app:
    image: node:8
    tty: true           # <-- This option

หมายเหตุ: หากคุณใช้ Dockerfile สำหรับรูปภาพและCMDใน Dockerfile ตัวเลือกนี้จะไม่ทำงาน อย่างไรก็ตามคุณสามารถใช้entrypointตัวเลือกในไฟล์เขียนซึ่งล้างCMDออกจาก Dockerfile


7
งานนี้และดูเหมือนว่า hacky tail -f /dev/nullน้อยกว่า ด้วยสิ่งนี้ฉันสามารถเรียกใช้สภาพแวดล้อม dev ที่มีคอนเทนเนอร์พร้อมกับฐานข้อมูล postgres ที่เชื่อมต่อผ่านdocker-compose upและเรียกใช้เชลล์ผ่านเทอร์มินัลอื่นโดยใช้docker exec.
Psiloc

1
ในขณะนี้ยังไม่ได้รับการบันทึกไว้อย่างดี นี่คือตัวเลือกอย่างเป็นทางการที่จะให้ผลเช่นเดียวกับtail -f /dev/nullหรือtail -f anythingดูที่นี่: docs.docker.com/compose/compose-file
b01

2
@ABMRuman & Psiloc ใช้งานได้เฉพาะเมื่อคุณไม่ได้ใช้ "command" ในไฟล์ docker-compose.yml เมื่อใช้ "คำสั่ง" คุณต้องแฮ็คอีกครั้งดังนั้นแฮ็ก tail -F จึงเหมาะอย่างยิ่ง
asafel

นี่ต้องเป็นคำตอบที่ดีที่สุดหากคุณใช้จุดเข้าใช้งานใน Dockerfile
DDKV587

53

จากความคิดเห็นของ @aanand บน GitHub 26 ส.ค. 2015หนึ่งสามารถใช้tail -f /dev/nullในการเขียนเทียบท่าเพื่อให้คอนเทนเนอร์ทำงานต่อไป

docker-compose.yml ตัวอย่าง

version: '3'
services:
  some-app:
    command: tail -f /dev/null

ทำไมต้องเป็นคำสั่งนี้

เหตุผลเดียวที่เลือกตัวเลือกนี้คือได้รับการยกนิ้วให้ GitHub เป็นจำนวนมาก แต่คำตอบที่ได้รับการโหวตสูงสุดไม่ได้หมายความว่าเป็นคำตอบที่ดีที่สุด เหตุผลประการที่สองเป็นข้อปฏิบัติเนื่องจากปัญหาต้องได้รับการแก้ไขโดยเร็วที่สุดเนื่องจากกำหนดเวลา


2
ทำไมถึงเป็นคำสั่งนี้? อะไรทำให้ดีกว่าคนอื่น ๆ ? ในกรณีของฉันเพิ่งเริ่มทุบตีก็เป็นเคล็ดลับเช่นกัน ...
N4ppeL

@ N4ppeL คำถามที่ดี เหตุผลเดียวที่ฉันเลือกตัวเลือกนี้คือได้รับการยกนิ้วให้ github เป็นจำนวนมาก แต่คำตอบที่ได้รับการโหวตสูงสุดไม่ได้หมายความว่าเป็นคำตอบที่ดีที่สุด เหตุผลประการที่สองเป็นข้อปฏิบัติเนื่องจากฉันต้องแก้ไขปัญหาโดยเร็วที่สุดเนื่องจากกำหนดเวลา
030

17
  • สร้างไฟล์ชื่อ docker-compose.yml
  • เพิ่มสิ่งต่อไปนี้ลงในไฟล์
version: "3"

services:
  ubuntu:
    image: ubuntu:latest
    tty: true
  • อยู่ในไดเร็กทอรีเดียวกันให้เรียกใช้docker-compose up -dจากเทอร์มินัล
  • เรียกใช้docker psเพื่อรับรหัสหรือชื่อคอนเทนเนอร์
  • คุณสามารถเรียกใช้ docker inspect $container_id
  • คุณสามารถเข้าสู่คอนเทนเนอร์และเรียกใช้ bash shell docker-compose exec ubuntu /bin/bashหรือdocker-compose exec ubuntu /bin/sh
  • เมื่อเสร็จแล้วตรวจสอบให้แน่ใจว่าคุณอยู่นอกคอนเทนเนอร์และเรียกใช้ docker-compose down

นี่คือสคริปต์ทุบตีขนาดเล็ก ( my-docker-shell.sh) เพื่อสร้างไฟล์เขียนนักเทียบท่าเรียกใช้คอนเทนเนอร์เข้าสู่ระบบคอนเทนเนอร์จากนั้นล้างข้อมูลคอนเทนเนอร์นักเทียบท่าและนักเทียบท่าเขียนไฟล์เมื่อคุณออกจากระบบ

#!/bin/bash

cat << 'EOF' > ./docker-compose.yml
---

version: "3"

services:
  ubuntu:
    image: ubuntu:latest
    command: /bin/bash
    # tty: true

...
EOF

printf "Now entering the container...\n"
docker-compose run ubuntu bash
docker-compose down

rm -v ./docker-compose.yml

1
แม้ว่านี่จะไม่ใช่คำตอบที่แท้จริงสำหรับคำถาม แต่ฉันก็พบว่ามันมีค่ามาก! ฉันไปใช้ฟังก์ชัน bashrc ทั่วโลกสำหรับแนวทางนี้ต่อไป: gist.github.com/loopmode/4d59a4e9a0a2ffacaec2dd14db4ae8bd
loopmode


2

ตามที่ผู้แสดงความคิดเห็นระบุเราจะต้องดู Dockerfile ที่เป็นปัญหาเพื่อให้คำตอบที่สมบูรณ์แก่คุณ แต่นี่เป็นข้อผิดพลาดทั่วไป ฉันค่อนข้างรับประกันได้ว่าคำสั่งที่คุณพยายามเรียกใช้กำลังเริ่มกระบวนการพื้นหลัง นี่อาจเป็นคำสั่งที่คุณใช้ในสถานการณ์ที่ไม่ใช่ Docker แต่เป็นสิ่งที่ผิดที่ต้องทำใน Dockerfile ตัวอย่างเช่นหากสิ่งที่คุณกำลังเรียกใช้โดยทั่วไปถูกกำหนดให้เป็นบริการระบบคุณอาจใช้คำว่า "systemctl start" นั่นจะเป็นการเริ่มกระบวนการในพื้นหลังซึ่งจะไม่ได้ผล คุณต้องเรียกใช้กระบวนการในเบื้องหน้าดังนั้นกระบวนการทั้งหมดจึงจะบล็อก


0

เพียงบันทึกสั้น ๆ

ฉันได้ทดสอบภาพเดี่ยวตามgolangดังนั้นเมื่อฉันเรียกdocker-compose downที่นี่สิ่งที่ฉันได้รับ:

version: "3.1"
...
command: tail -f /dev/null   # stopping container takes about 10 sec.
tty: true                    # stopping container takes about 2 sec.

ข้อมูลระบบของฉัน:

Ubuntu 18.04.4 LTS (64-bit)
Docker version 19.03.6, build 369ce74a3c
docker-compose version 1.26.0, build d4451659

-3

โอเคฉันพบข้อผิดพลาดของฉัน ใน Dockerfile สำหรับรูปภาพที่ใช้สำหรับเขียนฉันระบุว่าอิมเมจพื้นฐานควรเป็น ubuntu: ล่าสุด แต่ก่อนหน้านี้ฉันได้สร้างอิมเมจชื่อ ubuntu ด้วยตัวเองและรูปภาพนั้นใช้ไม่ได้ ดังนั้นฉันจึงไม่ได้ใช้อิมเมจอูบุนตูดั้งเดิม แต่เป็นอิมเมจของตัวเองที่เรียกว่าอูบุนตู

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