Πώς έτρεξα το Docker μέσα στο Docker και τι προέκυψε από αυτό

Γεια σε όλους! Στο δικό του προηγούμενο άρθρο, υποσχέθηκα να μιλήσω για την εκτέλεση του Docker στο Docker και τις πρακτικές πτυχές της χρήσης αυτού του μαθήματος. Ήρθε η ώρα να κρατήσετε την υπόσχεσή σας. Ένας έμπειρος προγραμματιστής πιθανότατα θα αντιταχθεί ότι όσοι χρειάζονται το Docker μέσα στο Docker απλώς προωθούν την υποδοχή δαίμονα Docker από τον κεντρικό υπολογιστή στο κοντέινερ και αυτό θα είναι αρκετό στο 99% των περιπτώσεων. Αλλά μην βιαστείτε να μου πετάξετε cookies, γιατί θα μιλήσουμε για την εκτέλεση του Docker μέσα στο Docker. Αυτή η λύση έχει πολλές πιθανές εφαρμογές και αυτό το άρθρο αφορά μία από αυτές, οπότε καθίστε αναπαυτικά και ισιώστε τα χέρια σας μπροστά σας.

Πώς έτρεξα το Docker μέσα στο Docker και τι προέκυψε από αυτό

ΑΡΧΙΚΗ

Όλα ξεκίνησαν ένα βροχερό απόγευμα Σεπτεμβρίου, όταν καθάριζα το μηχάνημα που νοίκιασα για 5 $ στο Digital Ocean, το οποίο ήταν παγωμένο λόγω του γεγονότος ότι το Docker είχε γεμίσει και τα 24 gigabyte του διαθέσιμου χώρου στο δίσκο με τις εικόνες και τα δοχεία του. Η ειρωνεία ήταν ότι όλες αυτές οι εικόνες και τα κοντέινερ ήταν παροδικά και χρειάζονταν μόνο για τη δοκιμή της απόδοσης της εφαρμογής μου κάθε φορά που κυκλοφόρησε μια νέα έκδοση μιας βιβλιοθήκης ή ενός πλαισίου. Προσπάθησα να γράψω σενάρια κελύφους και να δημιουργήσω ένα πρόγραμμα cron για να καθαρίσω τα σκουπίδια, αλλά δεν βοήθησε: κάθε φορά που αναπόφευκτα τελείωνε με τον χώρο του δίσκου του διακομιστή μου να καταναλώνεται και ο διακομιστής να κρέμεται (στην καλύτερη περίπτωση). Σε κάποιο σημείο, έπεσα πάνω σε ένα άρθρο σχετικά με τον τρόπο λειτουργίας του Jenkins σε ένα κοντέινερ και πώς μπορεί να δημιουργήσει και να διαγράψει αγωγούς κατασκευής μέσω μιας υποδοχής δαίμονα docker που προωθείται σε αυτό. Μου άρεσε η ιδέα, αλλά αποφάσισα να προχωρήσω παραπέρα και να δοκιμάσω να πειραματιστώ με την απευθείας εκτέλεση του 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 δεν τρέχει καν:

    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. Ας ξεκινήσουμε το bash. Επιτέλους επιστρέφουμε στο συνηθισμένο κέλυφος

  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. Πατήστε Enter. Επιστρέψαμε στο bash.

Από εδώ και στο εξής, μπορούμε να προσπαθήσουμε να εκτοξεύσουμε άλλα κοντέινερ μέσα στο κοντέινερ 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

    Μπαίνουμε στο bash, από όπου μπορούμε αμέσως να ξεκινήσουμε την εκτόξευση παιδικών κοντέινερ.

  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 βίντεο

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο