ویژگی ساخت چند مرحله ای در Dockerfiles شما را قادر می سازد تا تصاویر بزرگتر کانتینر را با ذخیره بهتر و ردپای امنیتی کوچکتر ایجاد کنید. در این پست وبلاگ ، من الگوهای پیشرفته تری را نشان می دهم که فراتر از کپی کردن پرونده ها بین مرحله ساخت و زمان اجرا هستند و امکان استفاده از این ویژگی را دارند. اگر در ساخت های چند مرحله ای جدید هستید ، احتمالاً می خواهید با خواندن راهنمای استفاده ابتدا شروع کنید.
توجه به BuildKit
جدیدترین نسخه های Docker با سازنده جدید انتخاب در پس زمینه BuildKit است. در حالی که همه الگوهای موجود در اینجا با سازنده قدیمی تر نیز کار می کنند ، بسیاری از آنها هنگام فعال کردن باطن BuildKit بسیار کارآمدتر عمل می کنند. به عنوان مثال ، BuildKit به طور موثری مراحل استفاده نشده را رد می کند و در صورت امکان مراحل را بصورت همزمان می سازد. من این موارد را در زیر نمونه های فردی مشخص کرده ام. اگر از این الگوهای استفاده می کنید ، فعال کردن BuildKit به شدت توصیه می شود. سایر سازندگان مبتنی بر BuildKit از این الگوهای نیز پشتیبانی می کنند.
• • •
وراثت از یک مرحله
ساختهای چند مرحله ای چند مفهوم جدید نحوی را به آن اضافه کردند. اول از همه ، می توانید مرحله ای را نامگذاری کنید که با یک دستور FROM
با AS namename
AS شروع شود و از استفاده کنید - از = namename name
در یک کپی
دستور داد تا پرونده ها را از آن مرحله کپی کنید. در واقع ، از دستور
و - از
پرچم چیزهای مشترک دیگری دارند و تصادفی نیست که آنها به همین صورت نامگذاری شوند. آنها هر دو همان استدلال را می گیرند ، آن را حل می کنند و سپس مرحله جدیدی را از آن نقطه شروع می کنند یا از آن به عنوان منبع برای کپی پرونده استفاده می کنند.
این بدان معنی است که به همان روش که می توانید از استفاده کنید - از = نام مرحله
همچنین می توانید از FROM namename
استفاده کنید تا از مرحله قبلی به عنوان تصویر منبع برای مرحله فعلی خود استفاده کنید. این کار زمانی مفید است که چندین دستور در Dockerfile قسمتهای مشترک یکسان را به اشتراک بگذارید. نگه داشتن کد مشترک کوچکتر و آسان تر در حالی که مراحل کودک را جدا نگه می دارد ، به طوری که وقتی یکی از آنها دوباره ساخته شد ، حافظه نهان را برای دیگران بی اعتبار نمی کند. هر مرحله همچنین می تواند بصورت جداگانه با استفاده از پرچم – هدف ساخته شود ، در حالی که با استفاده از docker build docker build
را بنا کنید. آپدیت مناسب و دریافت و نصب git
از پایه پایه AS src1
RUN git clon…
FROM base AS src2
RUN git clon …
در BuildKit ، مرحله دوم و سوم در این مثال به طور هم زمان ساخته می شود.
با استفاده از تصاویر مستقیم
به طور مشابه با استفاده از نام های مرحله ساخت در از
فرمان مي دهد كه قبلاً فقط از منابع تصويري پشتيباني مي كرد ، ما مي توانيم اين موضوع را بچرخانيم و مستقيماً با استفاده از - از پرچم
استفاده كنيم. این اجازه می دهد تا کپی کردن فایل ها به طور مستقیم از تصاویر دیگر انجام شود. به عنوان مثال ، در کد زیر می توانید از linuxkit / ca-گواهی
تصویر استفاده کنیم تا مستقیماً ریشه های TLS CA را در مرحله فعلی خود کپی کنیم.
از alpine
COPY –from = linuxkit / ca-گواهی نامه / /
نام مستعار برای تصویر مشترک
یک مرحله ساخت نیاز به دستورات ندارد – ممکن است فقط یک خط از
باشد. هنگامی که از یک تصویر در مکان های مختلف استفاده می کنید ، این می تواند برای بهبود خوانایی مفید باشد و اطمینان حاصل شود که وقتی یک تصویر به اشتراک گذاشته شده نیاز به بروزرسانی دارد ، فقط باید یک خط تغییر یابد.
FROM alpine: 3.6 AS alpine
FROM alpine
RUN …
FROM alpine
RUN RUN
] در این مثال آلپ
در واقع به آلپ ثابت شده است: 3.6
نه آلپ: آخرین
. وقتی نوبت به روزرسانی alpine: 3.7
رسید ، فقط یک خط باید تغییر کند و می توانیم مطمئن باشیم که هم اکنون تمام قسمت های ساخت در حال استفاده از نسخه به روز شده هستند.
این حتی بیشتر است هنگامی که یک استدلال ساخت در نام مستعار استفاده می شود قدرتمند است. مثال زیر برابر است با مثال قبلی ، اما به شما امکان می دهد تا با تنظیم گزینه - build-arg ALPINE_VERSION = مقدار
– از همه مواردی که تصویر الپی در این ساختمان استفاده می شود ، غافل شود. به یاد داشته باشید که هر آرگومان مورد استفاده در دستورات از لازم است قبل از اولین مرحله ساخت تعریف شود.
ARG ALPINE_VERSION = 3.6
FROM alpine: {ALPINE_VERSION] [1945AS alpine
FROM alpine
RUN …
با استفاده از آرگومان های ساختاری در `- از"
مقدار مشخص شده در - از
پرچم دستور COPY
ممکن است حاوی آرگومان های ساختاری نباشد. به عنوان مثال ، مثال زیر معتبر نیست:
// این نمونه به صورت Invalidally Invalid
از alpine AS build-stage0
RUN …
FRO alpine
ARG src = stage0
COPY -from = build – $ {src.
این به این دلیل است که قبل از شروع ساخت ، باید وابستگی بین مراحل مشخص شود ، بنابراین لازم نیست هر بار دستورات را ارزیابی کنیم. به عنوان مثال ، یک متغیر محیطی تعریف شده در تصویر alpine
می تواند در ارزیابی مقدار - از
تأثیر داشته باشد. دلیل اینکه می توانیم استدلالهای مربوط به فرمان FROM
را ارزیابی کنیم این است که این آرگومان ها قبل از شروع هر مرحله در سطح جهانی تعریف می شوند. خوشبختانه ، همانطور که قبلاً آموخته ایم ، می توانیم فقط یک مرحله نام مستعار را با یک فرمان از
تعریف کنیم و در عوض آن را ذکر کنیم.
ARG src = stage0
FPM alpine ] AS build-stage0
RUN …
FROM build – $ {src} AS cop-src
FROM alp COPY – از = copy-src.
غلبه بر استدلال ساخت src
اکنون می تواند مرحله منبع را برای عنصر نهایی COPY
تغییر دهد. توجه داشته باشید که اگر این باعث عدم استفاده از برخی مراحل شود ، فقط سازندگان مبتنی بر BuildKit توانایی این را دارند که به طور مؤثر از این مراحل بگذرند تا هرگز اجرا نشوند.
شرایط استفاده از آرگومانهای ساخت
درخواستهایی برای اضافه کردن IF / ELSE وجود دارد.
شرایط پشتیبانی از سبک در Dockerfiles. هنوز مشخص نیست که آیا چیزی شبیه به این در آینده اضافه می شود – با کمک پشتیبانی از جلوی سفارشی در BuildKit ممکن است این کار را در آینده انجام دهیم. در همین حال ، با برخی برنامه ریزی ها ، می توانید از مفاهیم چند مرحله ای فعلی برای به دست آوردن یک رفتار مشابه استفاده کنید.
// این نمونه به صورت غیرعادی است
از alpine
RUN …
ARG BUILD_VERSION = 1
IF $ BUILD_VERSION == 1
RUN version touch 1
ELSE IF $ BUILD_VERSION == 2 [19659019نسخه[RUN نسخه ] RUN …
مثال قبلی نشان می دهد که شبه کد چگونه می تواند با IF / ELSE
نوشته شود. برای داشتن رفتار یکسان با ساختهای چند مرحله فعلی ، باید شرایط شعبه های مختلف را به عنوان مراحل جداگانه تعریف کنید و برای انتخاب مسیر وابستگی صحیح از آرگومان استفاده کنید.
ARG BUILD_VERSION = 1
FROM alpine AS base
RUN …
FROM base AS شعبه-نسخه-1
RUN نسخه لمسی 1
] base AS branch-version-2
RUN version touch 2
FROM شعبه-نسخه – $ {BUILD_VERSION} AS AS پس از شرط [19659] از پس از شرط
RUN …
آخرین مرحله در این Dockerfile براساس مرحله پس از
مرحله است که نام مستعار تصویری است که توسط [حل می شود] BUILD_VERSION
استدلال ساخت. بسته به مقدار BUILD_VERSION
، یک مرحله از بخش میانی متفاوت انتخاب می شود.
توجه داشته باشید که فقط سازندگان مبتنی بر BuildKit می توانند از شاخه های بلااستفاده رد شوند. در سازندگان قبلی ، تمام مراحل هنوز ساخته خواهد شد ، اما نتایج آنها قبل از ایجاد تصویر نهایی دور ریخته می شود.
یاور توسعه / آزمایش برای مرحله تولید حداقل
بیایید با نمونه ای از ترکیب الگوهای قبلی پایان دهیم تا نشان دهیم چگونه برای ایجاد یک Dockerfile که یک تصویر تولیدی حداقل تولید می کند و می تواند از محتویات آن برای اجرای تست ها یا ایجاد یک تصویر توسعه استفاده کند. با یک نمونه اولیه Dockerfile شروع کنید:
از golang: alpine AS stage0
…
FROM golang: alpine AS] …
FROM خراش
COPY -from = stage0 / binary0 / bin
COPY -from = stage1 / binary1 / bin
این کاملاً متداول است هنگام ایجاد تصویر تولید حداقل. اما اگر می خواهید در مرحله آخر یک تصویر توسعه دهنده جایگزین نیز بدست آورید یا آزمایش هایی را با این باینری ها انجام دهید؟ یک راه واضح فقط کپی کردن همان باینرها در مراحل تست و توسعه دهنده نیز خواهد بود. مشکلی که در آن وجود دارد این است که هیچ ضمانتی وجود ندارد که شما تمام باینری های تولید را در یک ترکیب آزمایش کنید. ممکن است در مرحله آخر چیزی تغییر کند و ممکن است فراموش کنید که در مراحل دیگر تغییرات یکسان انجام دهید یا در مسیری که باینری ها کپی می شوند اشتباه کنید. از این گذشته ، ما می خواهیم تصویر نهایی را آزمایش کنیم نه یک باینری فردی.
یک الگوی جایگزین این است که یک مرحله توسعه دهنده و تست را بعد از مرحله تولید تعریف کنیم و کل محتویات مرحله تولید را کپی کنیم. از دستورات FROM
با مرحله تولید استفاده می شود تا مرحله تولید دوباره به عنوان آخرین مرحله پیش فرض قرار گیرد.
از golang: alpine AS AS0
]…
از خراش AS انتشار
COPY –from = stage0 / binary0 / bin
COPY -from = stage1 / binary1 / bin [ ] از golang: alpine AS dev-env
COPY –from = انتشار / /
ENTRYPOINT
FROM alpine AS test
COPY –from = release / /
RUN test go…
FROM انتشار
به طور پیش فرض ، این Dockerfile ادامه خواهد یافت ساختن تصویر به طور پیش فرض ، در حالی که مثلاً با
- target = dev-env
می توانید تصویری با پوسته بسازید که همیشه شامل باینری های کامل انتشار باشد.
• •
من امیدوارم که این مفید بود و برخی از ایده برای ایجاد Dockerfiles چند مرحله ای کارآمد تر به شما. شما می توانید از مخزن BuildKit برای پیگیری تحولات جدید برای ساختهای کارآمدتر و ویژگی های جدید Dockerfile استفاده کنید. در صورت نیاز به کمک ، می توانید به کانال #buildkit در Docker Community Slack بپیوندید.