Συμβουλές Docker: Καθαρίστε το μηχάνημά σας από σκουπίδια

Συμβουλές Docker: Καθαρίστε το μηχάνημά σας από σκουπίδια

Γεια σου Χαμπρ! Σας παρουσιάζω τη μετάφραση του άρθρου "Συμβουλές Docker: Καθαρίστε το τοπικό σας μηχάνημα" ο συγγραφέας Luc Juggery.

Σήμερα θα μιλήσουμε για το πώς το Docker χρησιμοποιεί το χώρο στο δίσκο του κεντρικού υπολογιστή και θα καταλάβουμε επίσης πώς να ελευθερώσουμε αυτόν τον χώρο από τα υπολείμματα αχρησιμοποίητων εικόνων και κοντέινερ.


Συμβουλές Docker: Καθαρίστε το μηχάνημά σας από σκουπίδια

Συνολική κατανάλωση

Το Docker είναι ένα ωραίο πράγμα, πιθανότατα λίγοι άνθρωποι το αμφιβάλλουν σήμερα. Μόλις πριν από λίγα χρόνια, αυτό το προϊόν μας έδωσε έναν εντελώς νέο τρόπο δημιουργίας, παράδοσης και εκτέλεσης οποιουδήποτε περιβάλλοντος, επιτρέποντάς μας να εξοικονομήσουμε σημαντικά πόρους CPU και RAM. Εκτός από αυτό (και για κάποιους αυτό θα είναι το πιο σημαντικό πράγμα) το Docker μας επέτρεψε να απλοποιήσουμε και να ενοποιήσουμε απίστευτα τη διαχείριση του κύκλου ζωής των περιβαλλόντων παραγωγής μας.

Ωστόσο, όλες αυτές οι απολαύσεις της σύγχρονης ζωής έχουν ένα τίμημα. Όταν τρέχουμε κοντέινερ, κατεβάζουμε ή δημιουργούμε τις δικές μας εικόνες και αναπτύσσουμε πολύπλοκα οικοσυστήματα, πρέπει να πληρώσουμε. Και πληρώνουμε, μεταξύ άλλων, με χώρο στο δίσκο.

Εάν δεν έχετε σκεφτεί ποτέ πόσο χώρο καταλαμβάνει το Docker στον υπολογιστή σας, μπορεί να εκπλαγείτε δυσάρεστα από την έξοδο αυτής της εντολής:

$ docker system df

Συμβουλές Docker: Καθαρίστε το μηχάνημά σας από σκουπίδια

Αυτό δείχνει τη χρήση του δίσκου του Docker σε διαφορετικά περιβάλλοντα:

  • εικόνες – το συνολικό μέγεθος των εικόνων που λήφθηκαν από αποθετήρια εικόνων και ενσωματώθηκαν στο σύστημά σας.
  • κοντέινερ – η συνολική ποσότητα χώρου στο δίσκο που χρησιμοποιείται από τα κοντέινερ που τρέχουν (που σημαίνει τον συνολικό όγκο των επιπέδων ανάγνωσης-εγγραφής όλων των κοντέινερ).
  • τοπικοί όγκοι – ο όγκος της τοπικής αποθήκευσης που τοποθετείται σε δοχεία.
  • build cache – προσωρινά αρχεία που δημιουργούνται από τη διαδικασία δημιουργίας εικόνων (χρησιμοποιώντας το εργαλείο BuildKit, διαθέσιμο ξεκινώντας από την έκδοση Docker 18.09).

Στοιχηματίζω ότι μετά από αυτή την απλή μεταφορά θέλετε να καθαρίσετε τον δίσκο σας από τα σκουπίδια και να επαναφέρετε στη ζωή πολύτιμα gigabyte (σημείωση: ειδικά αν πληρώνετε ενοίκιο για αυτά τα gigabyte κάθε μήνα).

Χρήση δίσκου από κοντέινερ

Κάθε φορά που δημιουργείτε ένα κοντέινερ στον κεντρικό υπολογιστή, δημιουργούνται πολλά αρχεία και κατάλογοι στον κατάλογο /var/lib/docker, μεταξύ των οποίων αξίζει να σημειωθούν τα ακόλουθα:

  • Κατάλογος /var/lib/docker/containers/container_ID – όταν χρησιμοποιείτε το τυπικό πρόγραμμα οδήγησης καταγραφής, εδώ αποθηκεύονται τα αρχεία καταγραφής συμβάντων σε μορφή JSON. Τα υπερβολικά λεπτομερή αρχεία καταγραφής, καθώς και τα αρχεία καταγραφής που κανείς δεν διαβάζει ή δεν επεξεργάζεται με άλλο τρόπο, συχνά προκαλούν γέμισμα των δίσκων.
  • Ο κατάλογος /var/lib/docker/overlay2 περιέχει τα επίπεδα ανάγνωσης-εγγραφής κοντέινερ (το overlay2 είναι το προτιμώμενο πρόγραμμα οδήγησης στις περισσότερες διανομές Linux). Εάν το κοντέινερ αποθηκεύει δεδομένα στο σύστημα αρχείων του, τότε θα τοποθετηθεί σε αυτόν τον κατάλογο.

Ας φανταστούμε ένα σύστημα στο οποίο είναι εγκατεστημένο ένα παρθένο Docker, το οποίο δεν έχει εμπλακεί ποτέ στην εκτόξευση κοντέινερ ή στην κατασκευή εικόνων. Η αναφορά χρήσης του χώρου στο δίσκο του θα μοιάζει με αυτό:

$ docker system df
TYPE           TOTAL      ACTIVE     SIZE       RECLAIMABLE
Images         0          0          0B         0B
Containers     0          0          0B         0B
Local Volumes  0          0          0B         0B
Build Cache    0          0          0B         0B

Ας ξεκινήσουμε κάποιο κοντέινερ, για παράδειγμα, το NGINX:

$ docker container run --name www -d -p 8000:80 nginx:1.16

Τι συμβαίνει στο δίσκο:

  • Οι εικόνες καταλαμβάνουν 126 MB, αυτό είναι το ίδιο NGINX που κυκλοφορήσαμε στο κοντέινερ.
  • τα δοχεία καταλαμβάνουν γελοία 2 byte.

$ docker system df
TYPE           TOTAL      ACTIVE     SIZE       RECLAIMABLE
Images         1          1          126M       0B (0%)
Containers     1          1          2B         0B (0%)
Local Volumes  0          0          0B         0B
Build Cache    0          0          0B         0B

Κρίνοντας από το συμπέρασμα, δεν έχουμε ακόμη χώρο που θα μπορούσαμε να ελευθερώσουμε. Επειδή τα 2 byte είναι εντελώς επιπόλαια, ας φανταστούμε ότι το NGINX μας έγραψε απροσδόκητα κάπου 100 Megabyte δεδομένων και δημιούργησε ένα αρχείο test.img αυτού του μεγέθους ακριβώς μέσα του.

$ docker exec -ti www 
  dd if=/dev/zero of=test.img bs=1024 count=0 seek=$[1024*100]

Ας εξετάσουμε ξανά τη χρήση του χώρου στο δίσκο στον κεντρικό υπολογιστή. Θα δούμε ότι το δοχείο (containers) καταλαμβάνει 100 Megabyte εκεί.

$ docker system df
TYPE           TOTAL      ACTIVE     SIZE       RECLAIMABLE
Images         1          1          126M       0B (0%)
Containers     1          1          104.9MB    0B (0%)
Local Volumes  0          0          0B         0B
Build Cache    0          0          0B         0B

Νομίζω ότι ο περίεργος εγκέφαλός σας αναρωτιέται ήδη πού βρίσκεται το αρχείο test.img μας. Ας το ψάξουμε:

$ find /var/lib/docker -type f -name test.img
/var/lib/docker/overlay2/83f177...630078/merged/test.img
/var/lib/docker/overlay2/83f177...630078/diff/test.img

Χωρίς να υπεισέλθουμε σε λεπτομέρειες, μπορούμε να σημειώσουμε ότι το αρχείο test.img βρίσκεται σε βολική τοποθεσία στο επίπεδο ανάγνωσης-εγγραφής, που ελέγχεται από το πρόγραμμα οδήγησης overlay2. Εάν σταματήσουμε το κοντέινερ μας, ο οικοδεσπότης θα μας πει ότι αυτός ο χώρος μπορεί, καταρχήν, να ελευθερωθεί:

# Stopping the www container
$ docker stop www

# Visualizing the impact on the disk usage
$ docker system df
TYPE           TOTAL      ACTIVE     SIZE       RECLAIMABLE
Images         1          1          126M       0B (0%)
Containers     1          0          104.9MB    104.9MB (100%)
Local Volumes  0          0          0B         0B
Build Cache    0          0          0B         0B

Πώς μπορούμε να το κάνουμε αυτό; Διαγράφοντας το κοντέινερ, το οποίο συνεπάγεται εκκαθάριση του αντίστοιχου χώρου στο επίπεδο ανάγνωσης-εγγραφής.

Με την ακόλουθη εντολή, μπορείτε να αφαιρέσετε όλα τα εγκατεστημένα κοντέινερ με μια γρήγορη κίνηση και να καθαρίσετε τον δίσκο σας από όλα τα αρχεία ανάγνωσης-εγγραφής που δημιουργήθηκαν από αυτά:

$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
5e7f8e5097ace9ef5518ebf0c6fc2062ff024efb495f11ccc89df21ec9b4dcc2

Total reclaimed space: 104.9MB

Έτσι, ελευθερώσαμε 104,9 Megabyte διαγράφοντας το κοντέινερ. Αλλά επειδή δεν χρησιμοποιούμε πλέον την εικόνα που λάβαμε προηγουμένως, γίνεται επίσης υποψήφια για διαγραφή και απελευθέρωση των πόρων μας:

$ docker system df
TYPE           TOTAL      ACTIVE     SIZE       RECLAIMABLE
Images         1          0          126M       126M (100%)
Containers     0          0          0B         0B
Local Volumes  0          0          0B         0B
Build Cache    0          0          0B         0B

Σημείωση: Εφόσον η εικόνα χρησιμοποιείται από τουλάχιστον ένα κοντέινερ, δεν θα μπορείτε να χρησιμοποιήσετε αυτό το τέχνασμα.

Η υποεντολή δαμάσκηνου που χρησιμοποιήσαμε παραπάνω έχει επίδραση μόνο στα σταματημένα δοχεία. Εάν θέλουμε να διαγράψουμε όχι μόνο σταματημένα αλλά και εκτελούμενα κοντέινερ, θα πρέπει να χρησιμοποιήσουμε μία από αυτές τις εντολές:

# Historical command
$ docker rm -f $(docker ps –aq)

# More recent command
$ docker container rm -f $(docker container ls -aq)

Πλευρικές σημειώσεις: εάν χρησιμοποιήσετε την παράμετρο -rm κατά την εκκίνηση ενός κοντέινερ, τότε όταν σταματήσει, όλος ο χώρος στο δίσκο που καταλάμβανε θα ελευθερωθεί.

Χρήση εικόνων δίσκου

Πριν από μερικά χρόνια, ένα μέγεθος εικόνας πολλών εκατοντάδων megabyte ήταν απολύτως φυσιολογικό: μια εικόνα Ubuntu ζύγιζε 600 megabyte και μια εικόνα Microsoft .Net ζύγιζε αρκετά gigabyte. Σε αυτές τις δύσκολες μέρες, η λήψη μόνο μιας εικόνας θα μπορούσε να έχει μεγάλο αντίτιμο στον ελεύθερο χώρο στο δίσκο σας, ακόμα κι αν μοιράζεστε επίπεδα μεταξύ εικόνων. Σήμερα - δόξα στους μεγάλους - οι εικόνες ζυγίζουν πολύ λιγότερο, αλλά ακόμα κι έτσι, μπορείτε να γεμίσετε γρήγορα τους διαθέσιμους πόρους αν δεν λάβετε κάποιες προφυλάξεις.

Υπάρχουν διάφοροι τύποι εικόνων που δεν είναι άμεσα ορατές στον τελικό χρήστη:

  • ενδιάμεσες εικόνες, βάσει των οποίων συλλέγονται άλλες εικόνες - δεν μπορούν να διαγραφούν εάν χρησιμοποιείτε κοντέινερ που βασίζονται σε αυτές τις «άλλες» εικόνες.
  • Οι κρέμονται εικόνες είναι ενδιάμεσες εικόνες που δεν αναφέρονται από κανένα από τα κοντέινερ που τρέχουν - μπορούν να διαγραφούν.
  • Με την ακόλουθη εντολή μπορείτε να ελέγξετε για κρέμονται εικόνες στο σύστημά σας:

$ docker image ls -f dangling=true
REPOSITORY  TAG      IMAGE ID         CREATED             SIZE
none      none   21e658fe5351     12 minutes ago      71.3MB

Μπορείτε να τα αφαιρέσετε με τον ακόλουθο τρόπο:

$ docker image rm $(docker image ls -f dangling=true -q)

Μπορούμε επίσης να χρησιμοποιήσουμε την υποεντολή prune:

$ docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Deleted Images:
deleted: sha256:143407a3cb7efa6e95761b8cd6cea25e3f41455be6d5e7cda
deleted: sha256:738010bda9dd34896bac9bbc77b2d60addd7738ad1a95e5cc
deleted: sha256:fa4f0194a1eb829523ecf3bad04b4a7bdce089c8361e2c347
deleted: sha256:c5041938bcb46f78bf2f2a7f0a0df0eea74c4555097cc9197
deleted: sha256:5945bb6e12888cf320828e0fd00728947104da82e3eb4452f

Total reclaimed space: 12.9kB

Εάν ξαφνικά θέλουμε να διαγράψουμε όλες τις εικόνες εντελώς (και όχι μόνο να κρέμονται) με μία εντολή, τότε μπορούμε να κάνουμε το εξής:

$ docker image rm $(docker image ls -q)

Χρήση δίσκου ανά όγκους

Οι τόμοι χρησιμοποιούνται για την αποθήκευση δεδομένων εκτός του συστήματος αρχείων του κοντέινερ. Για παράδειγμα, αν θέλουμε να αποθηκεύσουμε τα αποτελέσματα μιας εφαρμογής για να τα χρησιμοποιήσουμε με κάποιον άλλο τρόπο. Ένα συνηθισμένο παράδειγμα είναι οι βάσεις δεδομένων.

Ας εκκινήσουμε ένα κοντέινερ MongoDB, προσαρτήσουμε έναν τόμο έξω από το κοντέινερ και ας επαναφέρουμε ένα αντίγραφο ασφαλείας βάσης δεδομένων από αυτό (το έχουμε διαθέσιμο στο αρχείο bck.json):

# Running a mongo container
$ docker run --name db -v $PWD:/tmp -p 27017:27017 -d mongo:4.0

# Importing an existing backup (from a huge bck.json file)
$ docker exec -ti db mongoimport 
  --db 'test' 
  --collection 'demo' 
  --file /tmp/bck.json 
  --jsonArray

Τα δεδομένα θα βρίσκονται στον κεντρικό υπολογιστή στον κατάλογο /var/lib/docker/volumes. Αλλά γιατί όχι στο επίπεδο ανάγνωσης-εγγραφής του κοντέινερ; Επειδή στο Dockerfile της εικόνας MongoDB, ο κατάλογος /data/db (όπου το MongoDB αποθηκεύει τα δεδομένα του από προεπιλογή) ορίζεται ως τόμος.

Συμβουλές Docker: Καθαρίστε το μηχάνημά σας από σκουπίδια

Πλευρική σημείωση: πολλές εικόνες που πρέπει να παράγουν δεδομένα χρησιμοποιούν τόμους για την αποθήκευση αυτών των δεδομένων.

Όταν παίζουμε αρκετά με το MongoDB και σταματήσουμε (ή ίσως και διαγράψουμε) το κοντέινερ, ο τόμος δεν θα διαγραφεί. Θα συνεχίσει να καταλαμβάνει τον πολύτιμο χώρο στο δίσκο μας μέχρι να τον διαγράψουμε ρητά με μια εντολή όπως αυτή:

$ docker volume rm $(docker volume ls -q)

Λοιπόν, ή μπορούμε να χρησιμοποιήσουμε την υποεντολή prune που είναι ήδη γνωστή σε εμάς:

$ docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
d50b6402eb75d09ec17a5f57df4ed7b520c448429f70725fc5707334e5ded4d5
8f7a16e1cf117cdfddb6a38d1f4f02b18d21a485b49037e2670753fa34d115fc
599c3dd48d529b2e105eec38537cd16dac1ae6f899a123e2a62ffac6168b2f5f
...
732e610e435c24f6acae827cd340a60ce4132387cfc512452994bc0728dd66df
9a3f39cc8bd0f9ce54dea3421193f752bda4b8846841b6d36f8ee24358a85bae
045a9b534259ec6c0318cb162b7b4fca75b553d4e86fc93faafd0e7c77c79799
c6283fe9f8d2ca105d30ecaad31868410e809aba0909b3e60d68a26e92a094da

Total reclaimed space: 25.82GB
luc@saturn:~$

Χρήση δίσκου για την κρυφή μνήμη δημιουργίας εικόνων

Στο Docker 18.09, η διαδικασία δημιουργίας εικόνας έχει υποστεί κάποιες αλλαγές χάρη στο εργαλείο BuildKit. Αυτό το πράγμα αυξάνει την ταχύτητα της διαδικασίας και βελτιστοποιεί την αποθήκευση δεδομένων και τη διαχείριση της ασφάλειας. Εδώ δεν θα εξετάσουμε όλες τις λεπτομέρειες αυτού του υπέροχου εργαλείου· θα εστιάσουμε μόνο στο πώς αντιμετωπίζει ζητήματα χρήσης του χώρου στο δίσκο.

Ας υποθέσουμε ότι έχουμε μια εντελώς απλή εφαρμογή Node.Js:

  • το αρχείο index.js ξεκινά έναν απλό διακομιστή HTTP που απαντά με μια γραμμή σε κάθε αίτημα που λαμβάνεται:
  • το αρχείο package.json ορίζει τις εξαρτήσεις, από τις οποίες μόνο το expressjs χρησιμοποιείται για την εκτέλεση του διακομιστή HTTP:

$ cat index.js
var express = require('express');
var util    = require('util');
var app = express();
app.get('/', function(req, res) {
  res.setHeader('Content-Type', 'text/plain');
  res.end(util.format("%s - %s", new Date(), 'Got Request'));
});
app.listen(process.env.PORT || 80);

$ cat package.json
    {
      "name": "testnode",
      "version": "0.0.1",
      "main": "index.js",
      "scripts": {
        "start": "node index.js"
      },
      "dependencies": {
        "express": "^4.14.0"
      }
    }

Το Dockerfile για τη δημιουργία της εικόνας μοιάζει με αυτό:

FROM node:13-alpine
COPY package.json /app/package.json
RUN cd /app && npm install
COPY . /app/
WORKDIR /app
EXPOSE 80
CMD ["npm", "start"]

Ας δημιουργήσουμε την εικόνα με τον συνηθισμένο τρόπο, χωρίς να χρησιμοποιήσουμε το BuildKit:

$ docker build -t app:1.0 .

Εάν ελέγξουμε τη χρήση χώρου στο δίσκο, μπορούμε να δούμε ότι μόνο η εικόνα βάσης (node:13-alpine) και η εικόνα προορισμού (app:1.0) καταλαμβάνουν χώρο:

TYPE           TOTAL      ACTIVE     SIZE       RECLAIMABLE
Images         2          0          109.3MB    109.3MB (100%)
Containers     0          0          0B         0B
Local Volumes  0          0          0B         0B
Build Cache    0          0          0B         0B

Ας δημιουργήσουμε τη δεύτερη έκδοση της εφαρμογής μας, χρησιμοποιώντας το BuildKit. Για να γίνει αυτό, πρέπει απλώς να ορίσουμε τη μεταβλητή DOCKER_BUILDKIT σε 1:

$ DOCKER_BUILDKIT=1 docker build -t app:2.0 .

Εάν ελέγξουμε τώρα τη χρήση του δίσκου, θα δούμε ότι η προσωρινή μνήμη κατασκευής (buid-cache) εμπλέκεται τώρα εκεί:

$ docker system df
TYPE           TOTAL      ACTIVE     SIZE       RECLAIMABLE
Images         2          0          109.3MB    109.3MB (100%)
Containers     0          0          0B         0B
Local Volumes  0          0          0B         0B
Build Cache    11         0          8.949kB    8.949kB

Για να το διαγράψετε, χρησιμοποιήστε την ακόλουθη εντολή:

$ docker builder prune
WARNING! This will remove all dangling build cache.
Are you sure you want to continue? [y/N] y
Deleted build cache objects:
rffq7b06h9t09xe584rn4f91e
ztexgsz949ci8mx8p5tzgdzhe
3z9jeoqbbmj3eftltawvkiayi

Total reclaimed space: 8.949kB

Τα καθαρίζω όλα!

Έτσι, εξετάσαμε τον καθαρισμό του χώρου στο δίσκο που καταλαμβάνεται από κοντέινερ, εικόνες και τόμους. Η υποεντολή prune μας βοηθά σε αυτό. Αλλά μπορεί επίσης να χρησιμοποιηθεί σε επίπεδο συστήματος docker και θα καθαρίσει ό,τι μπορεί:

$ docker system prune
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all dangling images
  - all dangling build cache

Are you sure you want to continue? [y/N]

Εάν για κάποιο λόγο εξοικονομείτε χώρο στο δίσκο σε ένα μηχάνημα που εκτελεί Docker, τότε η περιοδική εκτέλεση αυτής της εντολής θα πρέπει να γίνει συνήθεια.

Πηγή: www.habr.com

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