ฉันรัน Docker ภายใน Docker ได้อย่างไร และสิ่งที่ออกมา

สวัสดีทุกคน! ในตัวเขา บทความก่อนหน้านี้ฉันสัญญาว่าจะพูดคุยเกี่ยวกับการใช้งาน Docker ใน Docker และแง่มุมเชิงปฏิบัติของการใช้บทเรียนนี้ ถึงเวลาที่จะรักษาสัญญาของคุณ Devopser ที่มีประสบการณ์อาจจะคัดค้านว่าผู้ที่ต้องการ Docker ภายใน Docker เพียงส่งต่อซ็อกเก็ต Docker daemon จากโฮสต์ไปยังคอนเทนเนอร์ และจะเพียงพอใน 99% ของกรณี แต่อย่ารีบโยนคุกกี้ใส่ฉัน เพราะเราจะพูดถึงการใช้งาน Docker ภายใน Docker วิธีแก้ไขนี้มีการใช้งานที่เป็นไปได้มากมาย และบทความนี้ก็เกี่ยวกับหนึ่งในนั้น ดังนั้นให้เอนหลังและเหยียดแขนตรงหน้า

ฉันรัน Docker ภายใน Docker ได้อย่างไร และสิ่งที่ออกมา

การเริ่มต้น

ทุกอย่างเริ่มต้นในเย็นวันที่ฝนตกของเดือนกันยายน ตอนที่ฉันทำความสะอาดเครื่องที่ฉันเช่าในราคา 5 ดอลลาร์บน Digital Ocean ซึ่งถูกแช่แข็งเนื่องจาก Docker ได้เติมพื้นที่ว่างในดิสก์ทั้งหมด 24 กิกะไบต์ด้วยอิมเมจและคอนเทนเนอร์ สิ่งที่น่าขันคืออิมเมจและคอนเทนเนอร์ทั้งหมดนี้เป็นแบบชั่วคราวและจำเป็นสำหรับการทดสอบประสิทธิภาพของแอปพลิเคชันของฉันทุกครั้งที่มีการเปิดตัวไลบรารีหรือเฟรมเวิร์กเวอร์ชันใหม่เท่านั้น ฉันพยายามเขียนเชลล์สคริปต์และตั้งค่าตารางเวลา cron เพื่อล้างขยะ แต่มันก็ไม่ได้ช่วยอะไร: ทุกครั้งที่มันจบลงด้วยการที่พื้นที่ดิสก์ของเซิร์ฟเวอร์ของฉันถูกกินและเซิร์ฟเวอร์หยุดทำงานอย่างหลีกเลี่ยงไม่ได้ (อย่างดีที่สุด) เมื่อถึงจุดหนึ่ง ฉันเจอบทความเกี่ยวกับวิธีรัน Jenkins ในคอนเทนเนอร์ และวิธีสร้างและลบ build ไปป์ไลน์ผ่านซ็อกเก็ต docker daemon ที่ส่งต่อเข้าไป ฉันชอบแนวคิดนี้ แต่ฉันตัดสินใจไปไกลกว่านี้และลองทดลองใช้งาน Docker โดยตรงใน Docker ในเวลานั้น สำหรับฉันแล้วดูเหมือนว่าโซลูชันที่สมเหตุสมผลในการดาวน์โหลดอิมเมจ Docker และสร้างคอนเทนเนอร์สำหรับแอปพลิเคชันทั้งหมดที่ฉันต้องการสำหรับการทดสอบภายในคอนเทนเนอร์อื่น (ขอเรียกว่าคอนเทนเนอร์ชั่วคราว) แนวคิดก็คือการเริ่มต้นคอนเทนเนอร์การแสดงละครด้วยแฟล็ก -rm ซึ่งจะลบคอนเทนเนอร์ทั้งหมดและเนื้อหาทั้งหมดโดยอัตโนมัติเมื่อหยุดทำงาน ฉันปรับแต่งอิมเมจ Docker จาก Docker เอง (https://hub.docker.com/_/docker) แต่มันกลายเป็นเรื่องยุ่งยากเกินไป และฉันก็ไม่สามารถทำให้มันทำงานได้ตามที่ฉันต้องการ และฉันก็อยากจะไปจนสุดทางด้วยตัวฉันเอง

ฝึกฝน. โคน

ฉันตั้งใจที่จะทำให้คอนเทนเนอร์ทำงานตามที่ฉันต้องการและทำการทดลองต่อ ซึ่งส่งผลให้มีตามากมาย ผลลัพธ์ของการทรมานตัวเองของฉันคืออัลกอริทึมต่อไปนี้:

  1. เราเปิดตัวคอนเทนเนอร์ Docker ในโหมดโต้ตอบ

    docker run --privileged -it docker:18.09.6

    ให้ความสนใจกับเวอร์ชันของคอนเทนเนอร์ ไปทางขวาหรือซ้าย จากนั้น DinD ของคุณจะกลายเป็นฟักทอง ในความเป็นจริง สิ่งต่างๆ มักจะพังบ่อยครั้งเมื่อมีการเปิดตัวเวอร์ชันใหม่
    เราต้องเข้าไปในเปลือกทันที

  2. เรากำลังพยายามค้นหาว่าคอนเทนเนอร์ใดกำลังทำงานอยู่ (คำตอบ: ไม่มี) แต่ให้เรารันคำสั่งต่อไป:

    docker ps

    คุณจะประหลาดใจเล็กน้อย แต่ปรากฎว่า Docker daemon ไม่ทำงานด้วยซ้ำ:

    error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 
    192.168.65.1:53: no such host

  3. เรามาดำเนินการกันเอง:

    dockerd &

    ความประหลาดใจอันไม่พึงประสงค์อีกอย่าง:

    failed to start daemon: Error initializing network controller: error obtaining controller instance: failed 
    to create NAT chain DOCKER: Iptables not found

  4. ติดตั้งแพ็คเกจ iptables และ bash (ทุกอย่างน่าทำงานมากกว่าใน bash มากกว่าใน sh):

    apk add --no-cache iptables bash

  5. มาเปิดตัวทุบตีกันเถอะ ในที่สุดเราก็กลับมาอยู่ในเปลือกปกติ

  6. ลองเปิด Docker อีกครั้ง:

    dockerd &

    เราควรเห็นบันทึกแผ่นยาวที่ลงท้ายด้วย:

    INFO[2019-11-25T19:51:19.448080400Z] Daemon has completed initialization          
    INFO[2019-11-25T19:51:19.474439300Z] API listen on /var/run/docker.sock

  7. กดปุ่มตกลง. เรากลับมาทุบตีแล้ว

จากนี้ไป เราสามารถลองเปิดตัวคอนเทนเนอร์อื่นๆ ภายในคอนเทนเนอร์ Docker ของเราได้ แต่จะเป็นอย่างไรหากเราต้องการเปิดตัวคอนเทนเนอร์ Docker อื่นภายในคอนเทนเนอร์ Docker ของเรา หรือมีบางอย่างผิดพลาดและคอนเทนเนอร์ขัดข้อง เริ่มต้นใหม่ทั้งหมดอีกครั้ง

เป็นเจ้าของคอนเทนเนอร์ DinD และการทดลองใหม่

ฉันรัน Docker ภายใน Docker ได้อย่างไร และสิ่งที่ออกมา
เพื่อหลีกเลี่ยงการทำซ้ำขั้นตอนข้างต้นซ้ำแล้วซ้ำอีก ฉันจึงสร้างคอนเทนเนอร์ DinD ของตัวเองขึ้นมา:

https://github.com/alekslitvinenk/dind

โซลูชัน DinD ที่ใช้งานได้ทำให้ฉันสามารถเรียกใช้ Docker ภายใน Docker แบบวนซ้ำและทำการทดลองที่ท้าทายมากขึ้น
ฉันจะอธิบายการทดลองหนึ่ง (ที่ประสบความสำเร็จ) กับการรัน MySQL และ Nodejs ทันที
คนที่ใจร้อนที่สุดก็สามารถมองเห็นได้ว่าที่นี่เป็นอย่างไร

ดังนั้นมาเริ่มกันเลย:

  1. เราเปิดตัว DinD ในโหมดโต้ตอบ ใน DinD เวอร์ชันนี้ เราจำเป็นต้องแมปพอร์ตทั้งหมดที่คอนเทนเนอร์ย่อยของเราสามารถใช้ได้ด้วยตนเอง (ฉันกำลังดำเนินการในส่วนนี้อยู่แล้ว)

    docker run --privileged -it 
    -p 80:8080 
    -p 3306:3306 
    alekslitvinenk/dind

    เราเข้าสู่การทุบตีซึ่งเราสามารถเริ่มเปิดตัวคอนเทนเนอร์ย่อยได้ทันที

  2. เปิดตัว MySQL:

    docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysql

  3. เราเชื่อมต่อกับฐานข้อมูลในลักษณะเดียวกับที่เราเชื่อมต่อกับฐานข้อมูลภายในเครื่อง ตรวจสอบให้แน่ใจว่าทุกอย่างทำงานได้

  4. เปิดตัวคอนเทนเนอร์ที่สอง:

    docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-server

    โปรดทราบว่าการแมปพอร์ตจะเป็นเช่นนั้นทุกประการ 8080:8080เนื่องจากเราได้แมปพอร์ต 80 จากโฮสต์ไปยังคอนเทนเนอร์หลักกับพอร์ต 8080 แล้ว

  5. เราไปที่ localhost ในเบราว์เซอร์ ตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ตอบสนอง "Hello World!"

ในกรณีของฉัน การทดลองกับคอนเทนเนอร์ Docker ที่ซ้อนกันกลับกลายเป็นผลดีทีเดียว และฉันจะพัฒนาโปรเจ็กต์ต่อไปและใช้สำหรับการแสดงละคร สำหรับฉันดูเหมือนว่านี่เป็นโซลูชันที่เบากว่า Kubernetes และ Jenkins X มาก แต่นี่คือความเห็นส่วนตัวของฉัน

ฉันคิดว่านั่นคือทั้งหมดสำหรับบทความของวันนี้ ในบทความถัดไป ผมจะอธิบายการทดลองโดยละเอียดเพิ่มเติมด้วยการรัน Docker แบบวนซ้ำใน Docker และการติดตั้งไดเรกทอรีลึกลงในคอนเทนเนอร์ที่ซ้อนกัน

PS หากคุณพบว่าโปรเจ็กต์นี้มีประโยชน์ โปรดติดดาวบน GitHub และแยกมันออกและบอกต่อเพื่อนของคุณ

Edit1 แก้ไขข้อผิดพลาดโดยเน้นที่วิดีโอ 2 รายการ

ที่มา: will.com

เพิ่มความคิดเห็น