เคล็ดลับนักเทียบท่า: ล้างเครื่องของคุณจากขยะ

เคล็ดลับนักเทียบท่า: ล้างเครื่องของคุณจากขยะ

เฮ้ ฮับ! ฉันขอเสนอการแปลบทความให้คุณทราบ "เคล็ดลับนักเทียบท่า: ทำความสะอาดเครื่องท้องถิ่นของคุณ" นักบิน ลุค จั๊กเกอรี่.

วันนี้เราจะพูดถึงวิธีที่ Docker ใช้พื้นที่ดิสก์ของเครื่องโฮสต์ และเราจะทราบวิธีเพิ่มพื้นที่นี้จากเศษรูปภาพและคอนเทนเนอร์ที่ไม่ได้ใช้


เคล็ดลับนักเทียบท่า: ล้างเครื่องของคุณจากขยะ

การบริโภคทั้งหมด

นักเทียบท่าเป็นสิ่งที่ยอดเยี่ยม อาจมีเพียงไม่กี่คนที่สงสัยในทุกวันนี้ เมื่อไม่กี่ปีที่ผ่านมา ผลิตภัณฑ์นี้ทำให้เรามีวิธีใหม่ในการสร้าง ส่งมอบ และรันสภาพแวดล้อมใดๆ ซึ่งช่วยให้เราสามารถประหยัดทรัพยากร CPU และ RAM ได้อย่างมาก นอกเหนือจากนี้ (และสำหรับบางอย่าง นี่จะเป็นสิ่งสำคัญที่สุด) Docker ยังช่วยให้เราลดความซับซ้อนและรวมการจัดการวงจรชีวิตของสภาพแวดล้อมการผลิตของเราได้อย่างเหลือเชื่อ

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

หากคุณไม่เคยคิดเลยว่า Docker จะกินพื้นที่ในเครื่องของคุณมากขนาดไหน คุณอาจประหลาดใจกับผลลัพธ์ของคำสั่งนี้:

$ docker system df

เคล็ดลับนักเทียบท่า: ล้างเครื่องของคุณจากขยะ

นี่แสดงการใช้งานดิสก์ของ Docker ในบริบทที่แตกต่างกัน:

  • รูปภาพ – ขนาดรวมของรูปภาพที่ดาวน์โหลดจากคลังรูปภาพและสร้างบนระบบของคุณ
  • คอนเทนเนอร์ – จำนวนพื้นที่ดิสก์ทั้งหมดที่ใช้โดยการรันคอนเทนเนอร์ (หมายถึงปริมาตรรวมของเลเยอร์การอ่าน-เขียนของคอนเทนเนอร์ทั้งหมด)
  • วอลุ่มในเครื่อง – ปริมาตรของที่จัดเก็บในเครื่องที่ติดตั้งกับคอนเทนเนอร์
  • build cache – ไฟล์ชั่วคราวที่สร้างโดยกระบวนการสร้างอิมเมจ (โดยใช้เครื่องมือ BuildKit ซึ่งเริ่มตั้งแต่ Docker เวอร์ชัน 18.09)

ฉันพนันได้เลยว่าหลังจากการถ่ายโอนง่ายๆ นี้ คุณคงอยากจะทำความสะอาดดิสก์ขยะและทำให้กิกะไบต์อันมีค่ากลับมามีชีวิตอีกครั้ง (หมายเหตุ: โดยเฉพาะอย่างยิ่งหากคุณจ่ายค่าเช่าสำหรับกิกะไบต์เหล่านี้ทุกเดือน)

การใช้งานดิสก์ตามคอนเทนเนอร์

ทุกครั้งที่คุณสร้างคอนเทนเนอร์บนเครื่องโฮสต์ ไฟล์และไดเร็กทอรีหลายรายการจะถูกสร้างขึ้นในไดเร็กทอรี /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 ไบต์อย่างไร้สาระ

$ 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 ไบต์นั้นไม่สำคัญเลย ลองจินตนาการว่า NGINX ของเราเขียนข้อมูลขนาด 100 เมกะไบต์โดยไม่คาดคิด และสร้างไฟล์ test.img ที่มีขนาดนี้อยู่ภายในตัวมันเอง

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

มาตรวจสอบการใช้พื้นที่ดิสก์บนโฮสต์อีกครั้ง เราจะเห็นว่าคอนเทนเนอร์ (คอนเทนเนอร์) มีพื้นที่ 100 เมกะไบต์นั่นเอง

$ 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 เมกะไบต์โดยการลบคอนเทนเนอร์ แต่เนื่องจากเราไม่ได้ใช้ภาพที่ดาวน์โหลดก่อนหน้านี้อีกต่อไป มันจึงกลายเป็นตัวเลือกสำหรับการลบและเพิ่มทรัพยากรของเรา:

$ 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

หมายเหตุ: ตราบใดที่รูปภาพถูกใช้งานโดยคอนเทนเนอร์อย่างน้อยหนึ่งรายการ คุณจะไม่สามารถใช้เคล็ดลับนี้ได้

คำสั่งย่อย prune ที่เราใช้ข้างต้นมีผลกับคอนเทนเนอร์ที่หยุดทำงานเท่านั้น หากเราต้องการลบไม่เพียงแต่หยุดทำงานแต่ยังใช้งานคอนเทนเนอร์อยู่ด้วย เราควรใช้คำสั่งใดคำสั่งหนึ่งต่อไปนี้:

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

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

หมายเหตุด้านข้าง: หากคุณใช้พารามิเตอร์ -rm เมื่อเริ่มต้นคอนเทนเนอร์ เมื่อคอนเทนเนอร์หยุด พื้นที่ดิสก์ทั้งหมดที่คอนเทนเนอร์นั้นว่างจะถูกทำให้ว่าง

การใช้ดิสก์อิมเมจ

ไม่กี่ปีที่ผ่านมา ขนาดรูปภาพหลายร้อยเมกะไบต์ถือเป็นเรื่องปกติ โดยรูปภาพของ Ubuntu มีน้ำหนัก 600 เมกะไบต์ และรูปภาพของ Microsoft .Net มีน้ำหนักหลายกิกะไบต์ ในวันที่ยุ่งวุ่นวายเหล่านั้น การดาวน์โหลดเพียงภาพเดียวอาจใช้พื้นที่ว่างในดิสก์ของคุณอย่างมาก แม้ว่าคุณจะแชร์ระดับระหว่างภาพก็ตาม วันนี้ - ขอสรรเสริญผู้ยิ่งใหญ่ - รูปภาพมีน้ำหนักน้อยกว่ามาก แต่ถึงกระนั้นคุณก็สามารถเติมทรัพยากรที่มีอยู่ได้อย่างรวดเร็วหากคุณไม่ใช้ความระมัดระวัง

มีรูปภาพหลายประเภทที่ผู้ใช้ปลายทางไม่สามารถมองเห็นได้โดยตรง:

  • รูปภาพระดับกลางซึ่งมีการรวบรวมรูปภาพอื่น ๆ - ไม่สามารถลบได้หากคุณใช้คอนเทนเนอร์ตามรูปภาพ "อื่น ๆ " เหล่านี้
  • รูปภาพห้อยเป็นรูปภาพระดับกลางที่ไม่ได้อ้างอิงโดยคอนเทนเนอร์ใดๆ ที่ทำงานอยู่ - สามารถลบรูปภาพเหล่านั้นได้
  • ด้วยคำสั่งต่อไปนี้ คุณสามารถตรวจสอบอิมเมจที่ค้างอยู่บนระบบของคุณได้:

$ 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 เก็บข้อมูลไว้ตามค่าเริ่มต้น) จึงถูกกำหนดให้เป็นโวลุ่ม

เคล็ดลับนักเทียบท่า: ล้างเครื่องของคุณจากขยะ

หมายเหตุด้านข้าง: รูปภาพจำนวนมากที่ต้องสร้างข้อมูลต้องใช้ปริมาณในการจัดเก็บข้อมูลนั้น

เมื่อเราเล่นกับ 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 .

หากเราตรวจสอบการใช้งานดิสก์ เราจะเห็นว่า build cache (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 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 การรันคำสั่งนี้เป็นระยะ ๆ ก็จะกลายเป็นนิสัย

ที่มา: will.com

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