در این آموزش نحوه ساخت imageهای کم حجم Docker با استفاده از ساخت‌های داکر چند مرحله‌ای شرح داده شده است. با استفاده از این نوع داکرها می‌توانید در فضای دیسک و مصرف اینترنت خود صرفه جویی کنید.

 

در اینجا، برای ساخت‌های docker چند مرحله‌ای از یک alpine image به‌عنوان image ساخت برای دریافت وابستگی‌ها استفاده کرده، برنامه باینری go را می‌سازیم و از scratch image خود برای قرار دادن برنامه باینری ساخته‌شده روی image مورد نظر استفاده می‌نماییم تا image داکر کوچک‌تری داشته باشیم.

 

چرا اندازه مهم است؟

فرض کنید که شما یک ارکستراتور مانند ECS ،Swarm یا Kubernetes با 100 نود در پشت یک گروه مقیاس خودکار (Auto Scaling Group) دارید، که در آن تعداد نودهای کلاستری شما هنگام ترافیک کم 10 و هنگام ترافیک زیاد 100 است.

همانطور که ما مقیاس سرویس‌مان را کاهش می‌دهیم، ممکن است از 10 کپی به 500 کپی تغییر کند و فرض کنید image کانتینر ما 800 مگابایت است. وقتی یک node جدید به یک کلاستر می‌پیوندد، image کانتینر در cache نخواهد بود؛ بنابراین docker daemon باید آن image را از رجیستری docker دانلود کند.

با توجه به آنچه بیان شد، فرض کنید 100 نود به کلاستر ملحق می‌شوند و سرویس ما به 100 کپی مقیاس می‌شود. از آنجایی که هر نود باید 800 مگابایت از رجیستری داکر دانلود نماید؛ بدین معنی است که حدود 80 گیگابایت ظرفیت ورودی شبکه به کلاستر خواهد بود.

وقتی از ساخت‌های چند مرحله‌ای استفاده می‌کنیم (و در اینجا، با استفاده از Go)، می‌توانیم image کانتینر خود را به کمتر از 3 مگابایت کاهش دهیم. با این حساب، تنها کمتر از 300 مگابایت از توان عملیاتی خواهد بود و اگر یک نود جدید به یک کلاستر و image کانتینر بپیوندد، دانلود و اجرا شدن container حدود یک یا دو ثانیه طول می‌کشد (بسته به سرعت اینترنت) و بدیهی است که در فضای دیسک نیز صرفه جویی می‌شود.

 

برنامه Go

در اینجا از کتابخانه‌ای استفاده خواهیم کرد که داده‌های تصادفی را از go-randomdata در برنامه ما (app.go) تولید می‌کند:

package main

import (
    "fmt"
    "github.com/Pallinder/go-randomdata"
)

func main() {
    profile := randomdata.GenerateProfile(randomdata.Male | randomdata.Female | randomdata.RandomGender)
    fmt.Printf("The new profile's username is: %s and password (md5): %s\n", profile.Login.Username, profile.Login.Md5)
}

 

ساخت تک مرحله‌ای داکر

در این مثال از golang image برای دریافت برنامه‌های پیش نیاز و ساخت برنامه در یک image، (یعنی Dockerfile.single_stage) استفاده می‌نماییم:

FROM golang:latest as builder
RUN mkdir -p /go/src/github.com/ruanbekker
WORKDIR /go/src/github.com/ruanbekker
RUN useradd -u 10001 app
COPY . .
ENV GO111MODULE=auto
RUN go get
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
USER app
CMD ["/go/src/github.com/ruanbekker/main"]

ساخت image:

docker build -f Dockerfile.single_stage -t goapp:singlestage .

 

ساخت چند مرحله‌ای داکر

در ساخت چند مرحله‌ای داکر، مراحل شامل ساخت یک image است که در آن از golang image برای دریافت برنامه‌های پیش نیاز و ساخت برنامه خود استفاده می‌کنیم. پس از آن، از image به عنوان هدف برای کپی کردن برنامه binary کامپایل شده و اجرای کانتینر از image کم حجم، (یعنی Dockerfile.multi_stage ما) استفاده می‌نماییم:

FROM golang:latest as builder
RUN mkdir -p /go/src/github.com/ruanbekker
WORKDIR /go/src/github.com/ruanbekker
RUN useradd -u 10001 app
COPY . .
ENV GO111MODULE=auto
RUN go get
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

FROM scratch
COPY --from=builder /go/src/github.com/ruanbekker/main /main
COPY --from=builder /etc/passwd /etc/passwd
USER app
CMD ["/main"]

ساخت image:

docker build -f Dockerfile.multi_stage -t goapp:multistage .

 

مقایسه تفاوت حجم

وقتی تفاوت اندازه image داکر را بین یک ساخت معمولی و یک ساخت چند مرحله‌ای مقایسه می‌کنیم، می‌توانیم تفاوت بزرگی را ببینیم:

docker images | head -3
REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
goapp                             singlestage         0d0c1f4c98a2        54 seconds ago      896MB
goapp                             multistage          d74ac27a39c8        2 hours ago         2.75MB

و برای نشان دادن اینکه هر دو کانتینر از imageهای docker ساخته شده اجرا می‌شوند،

برای ساخت تک مرحله‌ای به صورت زیر عمل می‌کنیم:

docker run -it goapp:singlestage
The new profile's username is: Maregrass and password (md5): 56da7705b7648a38f539b043e6a494be


و برای ساخت چند مرحله‌ای نیز به صورت زیر انجام می‌دهیم:

docker run -it goapp:multistage
The new profile's username is: Shirtplaid and password (md5): 7d8606ee86f2da3ed12c595ab617bf4e

 

 

 

منبع:

dev