محیط توسعه دهنده برو خود را Containerize کنید – قسمت 2


این دومین قسمت از مجموعه ای از ارسال ها است که نشان می دهد چگونه می توان از Docker برای تعریف محیط توسعه Go خود به صورت کد استفاده کرد. هدف از این کار این است که اطمینان حاصل کنید که شما ، تیم خود و CI همه از یک محیط یکسان استفاده می کنید. در قسمت 1 ، ما توضیح دادیم كه چگونه می توان از محیط توسعه محتوا برای توسعه محلی Go استفاده كرد ، یك ابزار CLI نمونه برای سیستم عامل های مختلف و كاهش زمینه ساخت برای سرعت بخشیدن به ساخت. اکنون ما می خواهیم یک قدم جلوتر برویم و یاد بگیریم که چگونه می توان وابستگی ها را اضافه کرد تا پروژه واقع بینانه تر شود ، حافظه پنهان سازی را سریعتر می کند و آزمایش های واحد را انجام می دهد.

افزودن وابستگی

برنامه از قسمت 1 بسیار ساده است و هیچگونه وابستگی به Go وابستگی ندارد. بیایید یک وابستگی ساده اضافه کنیم – بسته معمول استفاده شده github.com/pkg/errors :

بسته اصلی

اصلی

واردات (
"fmt"
"os"
"strings"
"github.com/pkg/errors"ociation19659006 معروف) موفق19659005ihenfuncociation19659008 موسخوآهنگ 19459013((args [] رشته )
] خطا {
if len (args) <2 {
برگشت خطا. جدید ] (] " هیچ پیامی برای echo ")
}
_، err: = fmt. Println (رشته ها. بپیوندید (args [1:]، " "))
Return err
}

Func main main ()
if err: = ] echo (os.Args)؛ err! = nil {
fmt. Fprintf (os.Stderr، "٪ + v n" ، err)
os.Exit (1)
}
}

برنامه مثال ما اکنون یک برنامه echo ساده است که استدلال هایی را مبنی بر ورود کاربر یا "پیغام برای مداخله" یا "بدون پیام برای echo" و اثری از پشته در صورت مشخص نبودن ، می نویسد. [19659014] ما برای حل این وابستگی از ماژول های Go استفاده خواهیم کرد. اجرای دستورات زیر پرونده های go.mod و go.sum پرونده ها را ایجاد می کند:

 $ go mod mod 
$ go mod tidy

اکنون وقتی ما اجرا می کنیم ساخت ، خواهیم دید که هر بار که ساختیم ، وابستگی ها بارگیری می شوند

 $ make 
[+] Building 8.2s (7/9)
=> [internal] تعریف ساخت بار از Dockerfile
...
0.0s
=> [build 3/4] کپی. .
0.1s
=> [build 4/4] RUN GOOS = darwin GOARCH = amd64 go build -o / out / مثال.
7.9s
=> => # go: بارگیری github.com/pkg/errors v0.9.1

این به وضوح ناکارآمد است و سرعت را کاهش می دهد. ما می توانیم این مسئله را با بارگیری وابستگی های خود به عنوان یک گام جداگانه در Dockerfile خود حل کنیم:

FROM - platform = $ {BUILDPLATFORM} golang : 1.14.3-alpine AS ] build
WORKDIR / src
ENV CGO_ENABLED = 0
COPY بروید. .
ARG TARGETOS
ARG TARGETARCH
RUN GOOS = $ {TARGETOS O GOARCH = $ {TARGETARCH} go--/ / out [1933] 19659022] خراش
AS بن یونیکس
COPY - از = build / out / مثال / موفق19659006 غلطیدن19459015 دوست داشته باشید ... فایلهای go. * را اضافه کرده و ماژول ها را قبل از اضافه کردن منبع دیگر بارگیری کنید. این به داکر اجازه می دهد تا ماژول ها را ذخیره کند زیرا در صورت حرکت مجدداً این مراحل را دوباره انجام می دهد. * پرونده ها تغییر می کنند.

ذخیره سازی

جدا کردن بارگیری وابستگی های ما از ساخت ما یک پیشرفت عالی است اما هر بار ساخت را اجرا می کنیم ، ما کامپایل را از ابتدا شروع می کنیم. برای پروژه های کوچک ممکن است این مسئله مشکلی نداشته باشد ، اما با بزرگتر شدن پروژه شما می خواهید از حافظه نهان کامپایلر Go استفاده کنید.

برای انجام این کار ، باید از FrontDock Dockerfile BuildKit استفاده کنید (https://github.com/moby/ buildkit / blob / master / frontend / dockerfile / docs / Experiment.md). Dockerfile به روز شده ما به شرح زیر است:

# syntax = docker / dockerfile: 1-Experiment

FROM - platform = $ {BUILDPLATFORM} [196590229] golang ]: 1.14.3-alpine AS build
ARG TARGETOS
ARG TARGETARCH
WORKDIR / src
END [C3D]
COPY بروید. *.
RUN go mod download
COPY . .
RUN --mount = type = cache، target = / root / .cache / go-build
GOOS = $ {TARGETOS} GOARCH = $ {TARGETARCH} ساخت -o / out / به عنوان مثال.

از خراش AS بن یونیکس
COPY - از = ساخت / بیرون / مثال /
... [19659013] به نحو # در بالای Dockerfile توجه کنید که جلوی آزمایشی Dockerfile و گزینه - مقدار متصل به فرمان run را انتخاب کنید. این گزینه mount به این معنی است که هر بار اجرای دستور go build ، کانتینر کش را روی پوشه حافظه نهان کامپایلر Go نصب کند. ساخت کد برای ساختن بدون حافظه پنهان 11 ثانیه طول می کشد و کمتر از 2 ثانیه با آن ایجاد می شود. این یک پیشرفت بزرگ است!

افزودن تست واحد

همه پروژه ها به آزمایش نیاز دارند! ما یک تست ساده برای عملکرد echo خود را در پرونده [ main_test.go پرونده اضافه می کنیم:

بسته اصلی

اصلی

واردات (
"تست"
"github.com/stretchr/testify/require"ociation19659006 معروف) موفق19659005 موسسات فنآوری19659008bowTestEchoroulette19459013((t * test.T) {
// Test مسیر مبارک
err: = echo ([] string { "bin-name" ، "hello" ، "world!" [1945901]}) به
نیاز دارند. / تست آرگومان های خالی

err: = echo ([] string {})
نیاز دارند. خطا (t، err)
} [19659013] این تست اطمینان می دهد که اگر عملکرد echo از لیست استدلال ها خارج شود ، خطایی می گیریم. erfile کنید تا بتوانیم تست ها را اجرا کنیم و باینری را بطور جداگانه بسازیم. این کار به یک refactor در مرحله پایه و سپس مرحله آزمایش و ساخت واحد نیاز دارد:

# syntax = docker / dockerfile: 1-Experiment

FROM - platform = $ {BUILDPLATFORM} golang : 1.14.3-alpine AS base
WORKDIR / src
ENV CGO_ENABD
بروید. *.
RUN go mod download
COPY . .

از پایه AS ساخت
ARG TARGETOS
ARG TARGETARCH
RUN --mount = type = cache، target = /root/.cache/go-build
GOOS = $ {TARGETOS} GOARCH = $ {TARGETARCH} go build -o / out / مثال.

FROM base AS واحد -test
RUN - mount = type = cache، target = / root / .cache / go-build
go test -v.

FROM خراش AS bin-unix
COPY - از = build / out / مثال / قرارداد19659006 غلتک19459015۵۵......19609013 غلط19659013 نشان می دهد که Go test از همان حافظه پنهانی مانند ساخت استفاده می کند بنابراین ما کش را برای این مرحله نیز سوار کنید. این اجازه می دهد تا فقط در صورت وجود تغییر کد ، تست ها را انجام دهیم که باعث می شود تست ها سریعتر اجرا شوند.

ما می توانیم Makefile را نیز به روز کنیم تا یک هدف آزمایشی اضافه شود:

همه: bin / مثال
test : lint unit-test

PLATFORM = local

.PHONY : bin / shembull
bin / مثال :
@ docker build. --target bin
- binput input /
--platform $ { PLATFORM }

] PHONY [19459:unit-test
واحد-آزمون :
@ docker build. --ttt واحد واحد آزمون

بعدی چیست؟

در این پست ما مشاهده کردیم که چگونه وابستگی های Go را به صورت کارآمد اضافه کنیم ، با ذخیره سازی برای ساخت سریع تر و آزمایش های واحد به محیط توسعه یافته خود برویم. در پست بعدی و آخر سریال ، قصد داریم سفر خود را به اتمام برسانیم و یاد بگیریم که چگونه یک آستر اضافه کنیم ، رابط کاربری GitHub Actions CI و برخی بهینه سازی های ساخت اضافی ایجاد کنیم.

شما می توانید منبع نهایی این مثال را در اینجا پیدا کنید. GitHub من: https://github.com/chris-crone/containerized-go-devociation19659014 45 شما می توانید اطلاعات بیشتر در مورد نحو تجربی Dockerfile را اینجا بخوانید: https://github.com/moby/buildkit/blob/master/ frontend / dockerfile / docs / experimental.md

اگر به ساخت Docker علاقه دارید ، نگاهی بیندازید به مخزن Buildx: https://github.com/docker/buildxociation19659014- کل سری پست های وبلاگ را مرور کنید