Alpine คอมไพล์ Docker builds สำหรับ Python ช้าลง 50 เท่า และรูปภาพหนักกว่า 2 เท่า

Alpine คอมไพล์ Docker builds สำหรับ Python ช้าลง 50 เท่า และรูปภาพหนักกว่า 2 เท่า

มักแนะนำให้ใช้ Alpine Linux เป็นอิมเมจพื้นฐานสำหรับ Docker คุณได้รับแจ้งว่าการใช้ Alpine จะทำให้งานสร้างของคุณเล็กลงและกระบวนการสร้างของคุณเร็วขึ้น

แต่ถ้าคุณใช้ Alpine Linux สำหรับแอปพลิเคชัน Python มันจะ:

  • ทำให้งานสร้างของคุณช้าลงมาก
  • ทำให้ภาพของคุณใหญ่ขึ้น
  • เสียเวลาของคุณ
  • และสุดท้ายก็อาจทำให้เกิดข้อผิดพลาดในรันไทม์ได้


มาดูกันว่าเหตุใดจึงแนะนำให้ใช้ Alpine แต่ทำไมคุณถึงยังไม่ควรใช้กับ Python

ทำไมผู้คนถึงแนะนำอัลไพน์?

สมมติว่าเราต้องการ gcc เป็นส่วนหนึ่งของอิมเมจของเรา และเราต้องการเปรียบเทียบ Alpine Linux กับ Ubuntu 18.04 ในแง่ของความเร็วในการสร้างและขนาดรูปภาพสุดท้าย

ขั้นแรก ให้ดาวน์โหลดภาพสองภาพและเปรียบเทียบขนาด:

$ docker pull --quiet ubuntu:18.04
docker.io/library/ubuntu:18.04
$ docker pull --quiet alpine
docker.io/library/alpine:latest
$ docker image ls ubuntu:18.04
REPOSITORY          TAG        IMAGE ID         SIZE
ubuntu              18.04      ccc6e87d482b     64.2MB
$ docker image ls alpine
REPOSITORY          TAG        IMAGE ID         SIZE
alpine              latest     e7d92cdc71fe     5.59MB

อย่างที่คุณเห็น รูปภาพพื้นฐานของ Alpine นั้นเล็กกว่ามาก ตอนนี้เรามาลองติดตั้ง gcc และเริ่มต้นด้วย Ubuntu:

FROM ubuntu:18.04
RUN apt-get update && 
    apt-get install --no-install-recommends -y gcc && 
    apt-get clean && rm -rf /var/lib/apt/lists/*

การเขียน Dockerfile ที่สมบูรณ์แบบนั้นอยู่นอกเหนือขอบเขตของบทความนี้

มาวัดความเร็วในการประกอบกัน:

$ time docker build -t ubuntu-gcc -f Dockerfile.ubuntu --quiet .
sha256:b6a3ee33acb83148cd273b0098f4c7eed01a82f47eeb8f5bec775c26d4fe4aae

real    0m29.251s
user    0m0.032s
sys     0m0.026s
$ docker image ls ubuntu-gcc
REPOSITORY   TAG      IMAGE ID      CREATED         SIZE
ubuntu-gcc   latest   b6a3ee33acb8  9 seconds ago   150MB

เราทำซ้ำเช่นเดียวกันกับ Alpine (Dockerfile):

FROM alpine
RUN apk add --update gcc

เราประกอบ ดูเวลาและขนาดของการประกอบ:

$ time docker build -t alpine-gcc -f Dockerfile.alpine --quiet .
sha256:efd626923c1478ccde67db28911ef90799710e5b8125cf4ebb2b2ca200ae1ac3

real    0m15.461s
user    0m0.026s
sys     0m0.024s
$ docker image ls alpine-gcc
REPOSITORY   TAG      IMAGE ID       CREATED         SIZE
alpine-gcc   latest   efd626923c14   7 seconds ago   105MB

ตามที่สัญญาไว้ รูปภาพบนเทือกเขาแอลป์จะถูกรวบรวมเร็วขึ้นและมีขนาดเล็กลง: 15 วินาทีจากเดิม 30 วินาที และขนาดรูปภาพคือ 105MB เทียบกับ 150MB มันค่อนข้างดี!

แต่ถ้าเราเปลี่ยนมาสร้างแอปพลิเคชั่น Python ทุกอย่างก็จะไม่ดูสดใสนัก

ภาพหลาม

แอปพลิเคชัน Python มักใช้ pandas และ matplotlib ดังนั้นทางเลือกหนึ่งคือการถ่ายภาพที่ใช้ Debian อย่างเป็นทางการโดยใช้ Dockerfile นี้:

FROM python:3.8-slim
RUN pip install --no-cache-dir matplotlib pandas

มารวบรวมกันเถอะ:

$ docker build -f Dockerfile.slim -t python-matpan.
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM python:3.8-slim
 ---> 036ea1506a85
Step 2/2 : RUN pip install --no-cache-dir matplotlib pandas
 ---> Running in 13739b2a0917
Collecting matplotlib
  Downloading matplotlib-3.1.2-cp38-cp38-manylinux1_x86_64.whl (13.1 MB)
Collecting pandas
  Downloading pandas-0.25.3-cp38-cp38-manylinux1_x86_64.whl (10.4 MB)
...
Successfully built b98b5dc06690
Successfully tagged python-matpan:latest

real    0m30.297s
user    0m0.043s
sys     0m0.020s

เราได้รับรูปภาพขนาด 363MB
เราจะทำดีกว่ากับอัลไพน์หรือไม่? มาลองกัน:

FROM python:3.8-alpine
RUN pip install --no-cache-dir matplotlib pandas

$ docker build -t python-matpan-alpine -f Dockerfile.alpine .                                 
Sending build context to Docker daemon  3.072kB                                               
Step 1/2 : FROM python:3.8-alpine                                                             
 ---> a0ee0c90a0db                                                                            
Step 2/2 : RUN pip install --no-cache-dir matplotlib pandas                                                  
 ---> Running in 6740adad3729                                                                 
Collecting matplotlib                                                                         
  Downloading matplotlib-3.1.2.tar.gz (40.9 MB)                                               
    ERROR: Command errored out with exit status 1:                                            
     command: /usr/local/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/
tmp/pip-install-a3olrixa/matplotlib/setup.py'"'"'; __file__='"'"'/tmp/pip-install-a3olrixa/matplotlib/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'rn'"'"', '"'"'n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-install-a3olrixa/matplotlib/pip-egg-info                              

...
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
The command '/bin/sh -c pip install matplotlib pandas' returned a non-zero code: 1

สิ่งที่เกิดขึ้น?

อัลไพน์ไม่รองรับล้อ

หากคุณดูที่บิลด์ซึ่งใช้ Debian คุณจะเห็นว่ามันดาวน์โหลด matplotlib-3.1.2-cp38-cp38-manylinux1_x86_64หว.

นี่คือไบนารี่สำหรับวงล้อ Alpine ดาวน์โหลดซอร์ส `matplotlib-3.1.2.targz` เนื่องจากมันไม่รองรับมาตรฐาน ล้อ.

ทำไม ลีนุกซ์ส่วนใหญ่ใช้เวอร์ชัน GNU (glibc) ของไลบรารีมาตรฐาน C ซึ่งจริงๆ แล้วจำเป็นสำหรับทุกโปรแกรมที่เขียนด้วยภาษา C รวมถึง Python ด้วย แต่ Alpine ใช้ `musl` และเนื่องจากไบนารีเหล่านั้นได้รับการออกแบบมาสำหรับ `glibc` พวกมันจึงไม่ใช่ตัวเลือก

ดังนั้น หากคุณใช้ Alpine คุณจะต้องคอมไพล์โค้ดทั้งหมดที่เขียนด้วยภาษา C ในแต่ละแพ็คเกจ Python

โอ้ ใช่แล้ว คุณจะต้องค้นหารายการการขึ้นต่อกันทั้งหมดที่จำเป็นต้องรวบรวมด้วยตัวเอง
ในกรณีนี้เราได้รับสิ่งนี้:

FROM python:3.8-alpine
RUN apk --update add gcc build-base freetype-dev libpng-dev openblas-dev
RUN pip install --no-cache-dir matplotlib pandas

และใช้เวลาในการสร้าง...

... 25 นาที 57 วินาที! และขนาดภาพคือ 851MB

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

นั่นไม่ใช่ทั้งหมด!

อัลไพน์อาจทำให้เกิดข้อบกพร่องที่ไม่คาดคิดในรันไทม์

  • ตามทฤษฎีแล้ว musl เข้ากันได้กับ glibc แต่ในทางปฏิบัติความแตกต่างอาจทำให้เกิดปัญหามากมาย และถ้าเป็นเช่นนั้นพวกเขาก็คงจะไม่เป็นที่พอใจ นี่คือปัญหาบางอย่างที่อาจเกิดขึ้น:
  • Alpine มีขนาดเธรดที่เล็กกว่าตามค่าเริ่มต้น ซึ่งอาจนำไปสู่ปัญหาได้ ข้อผิดพลาดใน Python
  • ผู้ใช้บางคนพบว่า แอปพลิเคชัน Python ทำงานช้าลง เนื่องจากวิธีที่ musl จัดสรรหน่วยความจำ (แตกต่างจาก glibc)
  • หนึ่งในผู้ใช้ พบข้อผิดพลาดเมื่อจัดรูปแบบวันที่

แน่นอนว่าข้อผิดพลาดเหล่านี้ได้รับการแก้ไขแล้ว แต่ใครจะรู้ว่าจะมีอีกกี่ครั้ง

อย่าใช้อิมเมจ Alpine สำหรับ Python

หากคุณไม่ต้องการกังวลกับบิลด์ที่มีขนาดใหญ่และยาว ค้นหาการขึ้นต่อกันและข้อผิดพลาดที่อาจเกิดขึ้น อย่าใช้ Alpine Linux เป็นอิมเมจพื้นฐาน การเลือกภาพฐานที่ดี.

ที่มา: will.com

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