این مقاله بخشی از مجموعه پستهایی است که در آن تمام خطوط Dockerfile پیشفرض Rails را طی میکنم و بهترین روشها و بهینهسازیها را توضیح میدهم.
تصاویر Docker را میتوان به روشهای مختلفی بهینه کرد که شامل کاهش اندازه تصویر، بهینهسازی عملکرد ساخت، بهترین شیوههای امنیت و قابلیت نگهداری، و بهینهسازیهای ویژه برنامهها میشود، اما محدود به آن نمیشود. در مقاله اول، من فقط بهینه سازی کاهش اندازه تصویر را لمس می کنم و دلیل اهمیت آنها را توضیح می دهم.
مانند هر فرآیند دیگر توسعه نرمافزار، هر توسعهدهنده دلایل خود را فهرست میکند که چرا میخواهد ساختهای Docker خود را سریعتر کند. من دلایلی را که برای من مهم هستند فهرست می کنم.
تصاویر کوچکتر سریعتر ساخته می شوند زیرا فایل ها و لایه های کمتری باید پردازش شوند. این کار بهره وری توسعه دهندگان را به ویژه در طول چرخه های توسعه تکراری بهبود می بخشد. عکسهای کوچکتر زمان کمتری میبرند تا به رجیستری فشار داده شوند و در حین استقرار از آن خارج شوند. این امر به ویژه در خطوط لوله CI/CD که کانتینرها اغلب ساخته و مستقر می شوند بسیار مهم است.
تصاویر کوچکتر ذخیره کمتری را در رجیستری های کانتینر، ماشین های توسعه محلی و سرورهای تولید مصرف می کنند. این امر هزینه های زیرساختی را به ویژه برای استقرار در مقیاس بزرگ کاهش می دهد. تصاویر کوچکتر هنگام انتقال بین سرورها از پهنای باند کمتری استفاده می کنند، به ویژه زمانی که تصاویر را به صورت محلی یا در خطوط لوله CI/CD می سازید و آنها را به یک رجیستری فشار می دهید.
ما در سال 2022 3.2 میلیون دلار در فضای ابری خرج کردیم... میخواهیم حدود 7 میلیون دلار در هزینههای سرور در طول پنج سال پس از خروج از ابر صرفهجویی کنیم.» دیوید هاین مایر هانسون - HEY World
تصاویر کوچکتر برای بارگیری و اجرا به منابع کمتری (مثلاً CPU، RAM) نیاز دارند که عملکرد کلی برنامههای کانتینری را بهبود میبخشد. زمانهای راهاندازی سریعتر به این معنی است که خدمات شما سریعتر آماده میشوند، که برای مقیاسپذیری و سیستمهای در دسترس بسیار مهم است. تصاویر پایه حداقل مانند alpine
یا debian-slim
حاوی بستههای از پیش نصب شده کمتری هستند که خطر سوء استفاده از نرمافزارهای وصله نشده یا غیرضروری را کاهش میدهد.
علاوه بر همه موارد ذکر شده در بالا، حذف فایلها و ابزارهای غیرضروری حواسپرتی را هنگام تشخیص مشکلات به حداقل میرساند و منجر به نگهداری بهتر و کاهش بدهی فنی میشود.
برای دریافت پارامترهای مختلف تصویر، از جمله اندازه، میتوانید به Docker Desktop نگاه کنید یا دستور docker images
را در ترمینال اجرا کنید.
➜ docker images REPOSITORY TAG IMAGE ID CREATED SIZE kamal-dashboard latest 673737b771cd 2 days ago 619MB kamal-proxy latest 5f6cd8983746 6 weeks ago 115MB docs-server latest a810244e3d88 6 weeks ago 1.18GB busybox latest 63cd0d5fb10d 3 months ago 4.04MB postgres latest 6c9aa6ecd71d 3 months ago 456MB postgres 16.4 ced3ad69d60c 3 months ago 453MB
دانستن اندازه تصویر به شما تصویر کاملی نمی دهد. شما نمی دانید داخل تصویر چیست، چند لایه دارد یا هر لایه چقدر بزرگ است. لایه تصویر داکر یک لایه سیستم فایل غیرقابل تغییر و فقط خواندنی است که جزئی از تصویر داکر است. هر لایه نشان دهنده مجموعه ای از تغییرات ایجاد شده در سیستم فایل تصویر است، مانند افزودن فایل ها، تغییر تنظیمات یا نصب نرم افزار.
تصاویر Docker به صورت تدریجی، لایه به لایه ساخته می شوند و هر لایه مطابق با یک دستورالعمل در Dockerfile
است. برای دریافت لایه های تصویر، می توانید دستور docker history
را اجرا کنید.
➜ docker history kamal-dashboard:latest IMAGE CREATED CREATED BY SIZE COMMENT 673737b771cd 4 days ago CMD ["./bin/thrust" "./bin/rails" "server"] 0B buildkit.dockerfile.v0 <missing> 4 days ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0 <missing> 4 days ago ENTRYPOINT ["/rails/bin/docker-entrypoint"] 0B buildkit.dockerfile.v0 <missing> 4 days ago USER 1000:1000 0B buildkit.dockerfile.v0 <missing> 4 days ago RUN /bin/sh -c groupadd --system --gid 1000 … 54MB buildkit.dockerfile.v0 <missing> 4 days ago COPY /rails /rails # buildkit 56.2MB buildkit.dockerfile.v0 <missing> 4 days ago COPY /usr/local/bundle /usr/local/bundle # b… 153MB buildkit.dockerfile.v0 <missing> 4 days ago ENV RAILS_ENV=production BUNDLE_DEPLOYMENT=1… 0B buildkit.dockerfile.v0 <missing> 4 days ago RUN /bin/sh -c apt-get update -qq && apt… 137MB buildkit.dockerfile.v0 <missing> 4 days ago WORKDIR /rails 0B buildkit.dockerfile.v0 <missing> 3 weeks ago CMD ["irb"] 0B buildkit.dockerfile.v0 <missing> 3 weeks ago RUN /bin/sh -c set -eux; mkdir "$GEM_HOME";… 0B buildkit.dockerfile.v0 <missing> 3 weeks ago ENV PATH=/usr/local/bundle/bin:/usr/local/sb… 0B buildkit.dockerfile.v0 <missing> 3 weeks ago ENV BUNDLE_SILENCE_ROOT_WARNING=1 BUNDLE_APP… 0B buildkit.dockerfile.v0 <missing> 3 weeks ago ENV GEM_HOME=/usr/local/bundle 0B buildkit.dockerfile.v0 <missing> 3 weeks ago RUN /bin/sh -c set -eux; savedAptMark="$(a… 78.1MB buildkit.dockerfile.v0 <missing> 3 weeks ago ENV RUBY_DOWNLOAD_SHA256=018d59ffb52be3c0a6d… 0B buildkit.dockerfile.v0 <missing> 3 weeks ago ENV RUBY_DOWNLOAD_URL=https://cache.ruby-lan… 0B buildkit.dockerfile.v0 <missing> 3 weeks ago ENV RUBY_VERSION=3.4.1 0B buildkit.dockerfile.v0 <missing> 3 weeks ago ENV LANG=C.UTF-8 0B buildkit.dockerfile.v0 <missing> 3 weeks ago RUN /bin/sh -c set -eux; mkdir -p /usr/loca… 19B buildkit.dockerfile.v0 <missing> 3 weeks ago RUN /bin/sh -c set -eux; apt-get update; a… 43.9MB buildkit.dockerfile.v0 <missing> 3 weeks ago # debian.sh --arch 'arm64' out/ 'bookworm' '… 97.2MB debuerreotype 0.15
از آنجایی که من قبلاً نظریه ای در مورد تصاویر و لایه ها ارائه کرده ام، زمان آن رسیده است که Dockerfile
را بررسی کنیم. با شروع از Rails 7.1، Dockerfile
با برنامه جدید Rails تولید می شود. در زیر نمونه ای از آنچه ممکن است به نظر برسد آورده شده است.
# syntax=docker/dockerfile:1 # check=error=true # Make sure RUBY_VERSION matches the Ruby version in .ruby-version ARG RUBY_VERSION=3.4.1 FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base # Rails app lives here WORKDIR /rails # Install base packages # Replace libpq-dev with sqlite3 if using SQLite, or libmysqlclient-dev if using MySQL RUN apt-get update -qq && \ apt-get install --no-install-recommends -y curl libjemalloc2 libvips libpq-dev && \ rm -rf /var/lib/apt/lists /var/cache/apt/archives # Set production environment ENV RAILS_ENV="production" \ BUNDLE_DEPLOYMENT="1" \ BUNDLE_PATH="/usr/local/bundle" \ BUNDLE_WITHOUT="development" # Throw-away build stage to reduce size of final image FROM base AS build # Install packages needed to build gems RUN apt-get update -qq && \ apt-get install --no-install-recommends -y build-essential curl git pkg-config libyaml-dev && \ rm -rf /var/lib/apt/lists /var/cache/apt/archives # Install application gems COPY Gemfile Gemfile.lock ./ RUN bundle install && \ rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \ bundle exec bootsnap precompile --gemfile # Copy application code COPY . . # Precompile bootsnap code for faster boot times RUN bundle exec bootsnap precompile app/ lib/ # Precompiling assets for production without requiring secret RAILS_MASTER_KEY RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile # Final stage for app image FROM base # Copy built artifacts: gems, application COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}" COPY --from=build /rails /rails # Run and own only the runtime files as a non-root user for security RUN groupadd --system --gid 1000 rails && \ useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \ chown -R rails:rails db log storage tmp USER 1000:1000 # Entrypoint prepares the database. ENTRYPOINT ["/rails/bin/docker-entrypoint"] # Start server via Thruster by default, this can be overwritten at runtime EXPOSE 80 CMD ["./bin/thrust", "./bin/rails", "server"]
در زیر فهرستی از رویکردها و قوانینی را که در Dockerfile
بالا اعمال میشود تا اندازه تصویر نهایی کارآمد باشد، ارائه خواهم داد.
من مطمئن هستم که فقط نرم افزارهای مورد نیاز را در دستگاه توسعه محلی خود نگه می دارید. همین امر باید در مورد تصاویر داکر نیز اعمال شود. در مثالهای زیر، من دائماً Dockerfile استخراجشده از Rails Dockerfile بالا را بدتر میکنم. من آن را به عنوان نسخه اصلی Dockerfile
ارجاع خواهم داد.
FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base
تصویر پایه نقطه شروع Dockerfile
است. این تصویری است که برای ایجاد ظرف استفاده می شود. تصویر پایه اولین لایه در Dockerfile
است و تنها لایه ای است که توسط خود Dockerfile
ایجاد نشده است.
تصویر پایه با دستور FROM
و به دنبال آن نام و تگ تصویر مشخص می شود. تگ اختیاری است و اگر مشخص نشده باشد از latest
تگ استفاده می شود. تصویر پایه می تواند هر تصویر موجود در Docker Hub یا هر رجیستری دیگر باشد.
در Dockerfile
about، ما از تصویر ruby
با تگ 3.4.1-slim
استفاده می کنیم. تصویر ruby
، تصویر رسمی روبی موجود در داکر هاب است. تگ 3.4.1-slim
یک نسخه باریک از تصویر Ruby است که بر اساس تصویر debian-slim
ساخته شده است. در حالی که تصویر debian-slim
یک نسخه حداقلی از تصویر Debian Linux است که برای اندازه بهینه شده است. به جدول زیر نگاه کنید تا متوجه شوید که تصویر slim
چقدر کوچکتر است.
➜ docker images --filter "reference=ruby" REPOSITORY TAG IMAGE ID CREATED SIZE ruby 3.4.1-slim 0bf957e453fd 5 days ago 219MB ruby 3.4.1-alpine cf9b1b8d4a0c 5 days ago 99.1MB ruby 3.4.1-bookworm 1e77081540c0 5 days ago 1.01GB
از ژانویه 2024، نسخه فعلی دبیان کتاب کرم و نسخه قبلی bullseye نام دارد.
219 مگابایت به جای 1 گیگابایت - یک تفاوت بزرگ. اما اگر تصویر alpine
حتی کوچکتر باشد چه؟ تصویر alpine
بر اساس توزیع آلپاین لینوکس است که یک توزیع لینوکس فوق العاده سبک است که برای اندازه و امنیت بهینه شده است. Alpine از کتابخانه musl
(به جای glibc
) و busybox
(مجموعه فشرده ای از ابزارهای یونیکس) به جای همتایان GNU استفاده می کند. در حالی که از نظر فنی امکان استفاده از تصویر alpine
برای اجرای Rails وجود دارد، در این مقاله به آن نمی پردازم.
RUN apt-get update -qq && \ apt-get install --no-install-recommends -y curl libjemalloc2 libvips libpq-dev && \ rm -rf /var/lib/apt/lists /var/cache/apt/archives
هر دستور RUN
، COPY
و FROM
در Dockerfile
یک لایه جدید ایجاد می کند. هرچه لایه های بیشتری داشته باشید، اندازه تصویر بزرگتر است. به همین دلیل است که بهترین تمرین ترکیب چند دستور در یک دستورالعمل RUN
است. برای نشان دادن این موضوع، اجازه دهید به مثال زیر نگاه کنیم.
# syntax=docker/dockerfile:1 # check=error=true # Make sure RUBY_VERSION matches the Ruby version in .ruby-version ARG RUBY_VERSION=3.4.1 FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base RUN apt-get update -qq RUN apt-get install --no-install-recommends -y curl RUN apt-get install --no-install-recommends -y libjemalloc2 RUN apt-get install --no-install-recommends -y libvips RUN apt-get install --no-install-recommends -y libpq-dev RUN rm -rf /var/lib/apt/lists /var/cache/apt/archives CMD ["echo", "Whalecome!"]
من دستورالعمل RUN
را به چندین خط تقسیم کرده ام که بدیهی است آنها را برای انسان قابل خواندن تر می کند. اما چگونه بر اندازه تصویر تأثیر می گذارد؟ بیایید تصویر را بسازیم و آن را بررسی کنیم.
➜ time docker build -t no-minimize-layers --no-cache -f no-minimize-layers.dockerfile . 0.31s user 0.28s system 2% cpu 28.577 total
ساخت تصویر 28 ثانیه طول کشید، در حالی که ساخت نسخه اصلی با لایه های کمینه تنها 19 ثانیه طول می کشد ( تقریباً 33٪ سریعتر ).
➜ time docker build -t original --no-cache -f original.dockerfile . 0.25s user 0.28s system 2% cpu 19.909 total
بیایید اندازه تصاویر را بررسی کنیم.
➜ docker images --filter "reference=*original*" --filter "reference=*no-minimize*" REPOSITORY TAG IMAGE ID CREATED SIZE original latest f1363df79c8a 8 seconds ago 356MB no-minimize-layers latest ad3945c8a8ee 43 seconds ago 379MB
تصویر با لایه های کوچک شده 23 مگابایت کوچکتر از تصویر بدون لایه های کوچک است. این کاهش 6 درصدی در اندازه است. در حالی که به نظر می رسد یک تفاوت کوچک در این مثال باشد، اگر تمام دستورالعمل های RUN
را به چندین خط تقسیم کنید، تفاوت بسیار بزرگتر خواهد بود.
به طور پیشفرض، apt-get install
بستههای پیشنهادی و همچنین بستههایی را که از آن خواستهاید نصب کند، نصب میکند. گزینه --no-install-recommends
به apt-get
می گوید که فقط بسته هایی را که به صراحت مشخص شده اند و نه بسته های توصیه شده را نصب کند.
➜ time docker build -t without-no-install-recommends --no-cache -f without-no-install-recommends.dockerfile . 0.33s user 0.30s system 2% cpu 29.786 total ➜ docker images --filter "reference=*original*" --filter "reference=*recommends*" REPOSITORY TAG IMAGE ID CREATED SIZE without-no-install-recommends latest 41e6e37f1e2b 3 minutes ago 426MB minimize-layers latest dff22c85d84c 17 minutes ago 356MB
همانطور که می بینید، تصویر بدون --no-install-recommends
70 مگابایت بزرگتر از تصویر اصلی است. این افزایش 16 درصدی در اندازه است.
برای مشاهده فایل هایی که به تصویر اضافه شده اند از ابزار dive استفاده کنید - در پایان مقاله در مورد آن بیشتر بخوانید.
Dockerfile
اصلی شامل دستور rm -rf /var/lib/apt/lists/* /var/cache/apt/archives
بعد از دستور apt-get install
است. این دستور لیست های بسته و آرشیوهایی را که پس از نصب دیگر مورد نیاز نیستند حذف می کند. بیایید ببینیم که چگونه بر اندازه تصویر تأثیر می گذارد، برای رسیدن به آن، یک Dockerfile
جدید بدون دستور پاکسازی ایجاد می کنم.
RUN apt-get update -qq && \ apt-get install --no-install-recommends -y curl libjemalloc2 libvips libpq-dev
ساختن تصاویر تقریباً به همان زمان اولیه نیاز دارد که منطقی است.
➜ time docker build -t without-cleaning --no-cache -f without-cleaning.dockerfile . 0.28s user 0.30s system 2% cpu 21.658 total
بیایید اندازه تصاویر را بررسی کنیم.
➜ docker images --filter "reference=*original*" --filter "reference=*cleaning*" REPOSITORY TAG IMAGE ID CREATED SIZE without-cleaning latest 52884fe50773 2 minutes ago 375MB original latest f1363df79c8a 16 minutes ago 356MB
تصویر بدون تمیز کردن 19 مگابایت بزرگتر از تصویر با تمیز کردن است، این افزایش 5 درصدی در اندازه است.
اگر هر چهار بهینه سازی ذکر شده در بالا اعمال نشود چه؟ بیایید یک Dockerfile
جدید بدون هیچ بهینه سازی ایجاد کنیم و تصویر را بسازیم.
# syntax=docker/dockerfile:1 # check=error=true ARG RUBY_VERSION=3.4.1 FROM docker.io/library/ruby:$RUBY_VERSION AS base RUN apt-get update -qq RUN apt-get install -y curl RUN apt-get install -y libjemalloc2 RUN apt-get install -y libvips RUN apt-get install -y libpq-dev CMD ["echo", "Whalecome!"]
➜ time docker build -t without-optimizations --no-cache -f without-optimizations.dockerfile . 0.46s user 0.45s system 1% cpu 1:02.21 total
وای، بیش از یک دقیقه طول کشید تا تصویر ساخته شود.
➜ docker images --filter "reference=*original*" --filter "reference=*without-optimizations*" REPOSITORY TAG IMAGE ID CREATED SIZE without-optimizations latest 45671929c8e4 2 minutes ago 1.07GB original latest f1363df79c8a 27 hours ago 356MB
تصویر بدون بهینه سازی 714 مگابایت بزرگتر از تصویر اصلی است، این افزایش 200 درصدی در اندازه است. این به وضوح نشان میدهد که بهینهسازی Dockerfile
چقدر مهم است، تصاویر بزرگتر زمان بیشتری را برای ساختن و مصرف فضای دیسک بیشتر میبرند.
فایل .dockerignore
شبیه فایل .gitignore
است که توسط Git استفاده می شود. برای حذف فایل ها و دایرکتوری ها از متن ساخت استفاده می شود. Context مجموعه ای از فایل ها و دایرکتوری ها است که هنگام ساخت یک تصویر به Daemon Docker ارسال می شود. متن به صورت تاربال به داکر دیمون ارسال می شود، بنابراین مهم است که آن را تا حد امکان کوچک نگه دارید.
اگر به هر دلیلی فایل .dockerignore
را در پروژه خود ندارید، می توانید آن را به صورت دستی ایجاد کنید. پیشنهاد می کنم از الگوی رسمی فایل Rails .dockerignore
به عنوان نقطه شروع استفاده کنید. در زیر نمونه ای از آنچه ممکن است به نظر برسد آورده شده است.
# See https://docs.docker.com/engine/reference/builder/#dockerignore-file for more about ignoring files. # Ignore git directory. /.git/ /.gitignore # Ignore bundler config. /.bundle # Ignore all environment files. /.env* # Ignore all default key files. /config/master.key /config/credentials/*.key # Ignore all logfiles and tempfiles. /log/* /tmp/* !/log/.keep !/tmp/.keep # Ignore pidfiles, but keep the directory. /tmp/pids/* !/tmp/pids/.keep # Ignore storage (uploaded files in development and any SQLite databases). /storage/* !/storage/.keep /tmp/storage/* !/tmp/storage/.keep # Ignore assets. /node_modules/ /app/assets/builds/* !/app/assets/builds/.keep /public/assets # Ignore CI service files. /.github # Ignore development files /.devcontainer # Ignore Docker-related files /.dockerignore /Dockerfile*
وجود یک فایل .dockerfile
در پروژه نه تنها امکان حذف فایلها و دایرکتوریهای غیرضروری (مثلاً گردشهای کاری GitHub از پوشه .github
یا وابستگیهای جاوا اسکریپت از node_modules
) را از زمینه فراهم میکند. همچنین به جلوگیری از افزودن تصادفی اطلاعات حساس به تصویر کمک می کند. به عنوان مثال، فایل .env
که حاوی متغیرهای محیطی است یا فایل master.key
که برای رمزگشایی اعتبارنامه ها استفاده می شود.
همه بهینهسازیهای ذکر شده در بالا ممکن است هنگام توضیح واضح به نظر برسند. اگر از قبل تصویری عظیم دارید و نمی دانید از کجا شروع کنید، چه کاری باید انجام دهید؟
ابزار مورد علاقه و مفید من Dive است. Dive یک ابزار TUI برای کاوش تصویر Docker، محتویات لایه و کشف راههایی برای کوچک کردن اندازه تصویر است. Dive را می توان با مدیریت بسته سیستم خود نصب کرد، یا می توانید از تصویر رسمی Docker آن برای اجرای آن استفاده کنید. بیایید از تصویر بدترین سناریوی خود استفاده کنیم.
docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive:latest without-optimizations
در تصویر بالا، می توانید بررسی غیربهینه ترین تصویر ما را مشاهده کنید. Dive اندازه هر لایه، اندازه کلی تصویر و فایل هایی که در هر لایه تغییر کرده اند (اضافه شده، اصلاح یا حذف شده اند) را نشان می دهد. برای من، این مفیدترین ویژگی Dive است. با فهرست کردن فایلها در پنل سمت راست، میتوانید به راحتی فایلهایی را که مورد نیاز نیستند شناسایی کنید و دستوراتی را که آنها را به تصویر اضافه میکنند حذف کنید.
یکی از چیزهایی که من واقعاً در مورد Dive دوست دارم این است که علاوه بر داشتن رابط کاربری ترمینال، میتواند خروجی سازگار با CI را نیز ارائه دهد که میتواند در توسعه محلی نیز مؤثر باشد. برای استفاده از آن، Dive را با متغیر محیطی CI
روی true
اجرا کنید، خروجی دستور در تصویر زیر است.
docker run -e CI=true --rm -it -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive:latest without-optimizations
ترجیح شخصی من این است که از Dive به صورت برنامه ریزی شده استفاده کنم، به عنوان مثال، یک بار در هفته، تا مطمئن شوم که تصاویر شما هنوز در شکل خوبی هستند. در مقالههای آینده، گردشهای کاری خودکاری را که برای بررسی Dockerfile خود استفاده میکنم، شامل Dive و Hadolint پوشش خواهم داد.
یکی از روشهایی که برای به حداقل رساندن اندازه تصویر دیدهام، تلاش برای له کردن لایهها است. ایده این بود که چندین لایه را در یک لایه ترکیب کنیم تا اندازه تصویر کاهش یابد. Docker یک گزینه آزمایشی داشت --squash
، علاوه بر این، ابزارهای شخص ثالث مانند docker-squash وجود داشت.
در حالی که این رویکرد در گذشته کار می کرد، در حال حاضر منسوخ شده است و استفاده از آن توصیه نمی شود. له کردن لایه ها ویژگی اساسی Docker در کش کردن لایه ها را از بین برد. جدای از آن، هنگام استفاده از --squash
میتوانید ناخواسته فایلهای حساس یا موقتی از لایههای قبلی را در تصویر نهایی قرار دهید. این یک رویکرد همه یا هیچ است که فاقد کنترل دقیق است.
به جای له کردن لایه ها، توصیه می شود از ساخت های چند مرحله ای استفاده کنید. Rails Dockerfile
در حال حاضر از ساخت های چند مرحله ای استفاده می کند، در مقاله بعدی نحوه عملکرد آن را توضیح خواهم داد.
بهینه سازی تصاویر Docker، درست مانند هر بهینه سازی دیگری، یک بار انجام نمی شود و فراموش می شود . این یک فرآیند مداوم است که نیاز به بررسی و بهبود منظم دارد. من سعی کردم اصول اولیه را پوشش دهم، اما دانستن و درک آنها حیاتی است. در مقالههای بعدی، تکنیکها و ابزارهای پیشرفتهتری را پوشش خواهم داد که میتوانند به ساخت سریعتر و کارآمدتر Docker شما کمک کنند.