داکر برای برنامه‌نویس‌ها: قسمت یازدهم - best practices (ادامه)

مقدمهقسمت قبلی با تعدادی از best practiceهای دنیای کانتینرها و داکر آشنا شدیم. در این قسمت می‌خوایم به تعدادی دیگه‌ از این‌ نکات بپردازیم. این نوشته برای برنامه‌نویس‌ها و مهندسان DevOps مفید می‌تونه باشه.فرض بر این هست که شما سابقه برنامه‌نویسی دارید و با کانتینرها و داکر هم کار کردید.استفاده از dockerignore. وقتی در یک پوشه دستور docker build رو اجرا می‌کنیم کل محتوای پوشه به عنوان build context به حساب میان و اگر کل پوشه رو کپی کنیم همه‌شون میرن به ایمیج. بعضی از فایل‌ها یا پوشه‌ها ممکنه داخل ایمیج لازم نباشن. چجوری اینا رو حذف کنیم؟ مثل gitignore. داکر هم یه فایل dockerignore. داره که با اون می‌تونیم هر چیزی که نمی‌خوایم رو حذف کنیم. این شکلی بدون این که دست به ساختار پوشه بزنیم یه چیزایی رو کنار می‌ذاریم. مثلا ممکنه یک سری README.md نوشته باشید و نخواید تو ایمیج بذارید. این جاست که dockerignore. به دردتون می‌خوره. برای آشنایی با نحوه‌ی استفاده از الگوهای مختلف در این فایل می‌تونید این لینک رو ببینید.بیلد چند مرحله‌ایبعضی از برنامه‌ها هستن که برای بیلد شدن باید کامپایل بشن و برای این کامپایل شدن باید تعدادی ابزار وجود داشته باشه. این ابزارها برای اجرای نهایی برنامه لازم نیستن و باعث میشن حجم ایمیج زیاد بشه. این جور مواقع از بیلد چند مرحله‌ای استفاده می‌کنیم. به عنوان مثال زبان گو رو در نظر بگیرید. وقتی برنامه‌ای به این زبان کامپایل میشه یک فایل باینری به دست میاد که فقط باید دسترسی execute بهش بدیم تا بتونیم اجراش کنیم. چیز دیگه‌ای لازم نیست. یک داکرفایل به عنوان مثال آوردم: FROM golang:1.7.3 AS builder WORKDIR /go/src/github.com/alexellis/href-counter/ RUN go get -d -v golang.org/x/net/html COPY app.go . RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=builder /go/src/github.com/alexellis/href-counter/app . CMD [&quot./app&quot]این مثال تو این لینک آورده شده. دقت کنید دو تا FROM داریم. یعنی دو تا مرحله داریم و دو تا ایمیج قراره ساخته بشه. تو مرحله اول از ایمیج رسمی golang استفاده شده و برنامه رو بیلد کرده. خروجی بیلد به یک فایل به نام app میره. چیزی که احتمالا بهش توجه کردید AS builder در انتهای خط اوله. AS یکی از keywordهای داکرفایل هست و یک اسم به ایمیجی که ساخته میشه میده. این اسم رو گذاشتیم تا در مرحله دوم ازش استفاده کنیم.حالا بریم سراغ FROM دوم. می‌بینید که از alpine استفاده کرده که حجم خیلی کوچیکی داره. این همون چیزیه که این روش رو خیلی جذاب می‌کنه. تنها کافیه فایل باینری رو از ایمیج قبلی کپی کنیم. تو دستور COPY یک آپشن استفاده شده و اون from-- هست. با این آپشن اسم ایمیجی که ازش کپی می‌کنیم تعیین میشه. یعنی دیگه از سیستم خودمون کپی نمی‌کنیم. تو این مورد اسم ایمیج قبلی builder است. آخر سر هم app رو اجرا می‌کنیم. با این روش به جای استفاده از ایمیج golang که بیش از ۲۰۰ مگابایت حجم داره رسیدیم به alpine (با تنها چند مگابایت حجم) به علاوه فایل باینری.استفاده از non root userدستوراتی که توی داکرفایل برای RUN و ENTRYPOINT و CMD می‌نویسیم با کاربر root اجرا میشن. اما این از لحاظ امنیتی ممکنه خطرساز بشه؛ چون دسترسی بالایی داره. برای این که این اتفاق نیفته از USER استفاده می‌کنیم: FROM python:3.7 ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code COPY requirements.txt /code/ RUN pip install -r requirements.txt COPY . /code/ RUN useradd nonroot USER nonroot ENTRYPOINT [&quot/bin/bash&quot, &quotstart.sh&quot]خط یکی مونده به آخر ازش استفاده کردم. جلوی USER نام کاربر رو می‌ذاریم. قبلش یادتون باشه باید کاربر تو سیستم ساخته بشه. خط قبلیش من useradd رو اجرا کردم. میشه بعد از نام دو نقطه بذاریم و گروهش رو هم مشخص کنیم. گروه هم باید قبلش ساخته بشه. هر چی دستور بعد از اون اجرا بشه رو این کاربر انجام میده. اگر توی شل کانتینر ساخته شده از این ایمیج هم بریم باز همون کاربر هستیم و نه root: تو تصویر بالا (به شل کانتینری که از داکرفایل قبلی ساخته شده رفتم) که به خروجی دستور id نشون میده نام کاربری من nonroot هست و گروهم هم nonroot. چرا گروه nonroot وجود داره؟ من که نساخته بودمش. به این فکر کنید و اگر جواب رو پیدا کردید تو نظرات بگید.جمع بندیدر این مطلب با یک سری دیگه از best practiceها برای برنامه‌نویس‌ها در دنیای کانتینرها و داکر آشنا شدیم. اگر نکات دیگه‌ای هم سراغ دارید معرفی کنید تا همه استفاده کنیم. اگر هم سوال یا نظری دارید این پایین بفرمایید.قسمت قبلیقسمت بعدی