একাধিক আরএন বনাম বনাম একক শৃঙ্খলাবদ্ধ রুন ডকফাইফিলে, এর থেকে ভাল কী?


132

Dockerfile.1একাধিক চালায় RUN:

FROM busybox
RUN echo This is the A > a
RUN echo This is the B > b
RUN echo This is the C > c

Dockerfile.2 তাদের সাথে যোগ দেয়:

FROM busybox
RUN echo This is the A > a &&\
    echo This is the B > b &&\
    echo This is the C > c

প্রত্যেকটি RUNএকটি স্তর তৈরি করে, তাই আমি সর্বদা ধরে নিয়েছিলাম যে কম স্তরগুলি আরও ভাল এবং Dockerfile.2এটি আরও ভাল।

এটি স্পষ্টতই সত্য যখন কোনও RUNপূর্ববর্তী RUN(যেমন yum install nano && yum clean all) দ্বারা যুক্ত কিছু সরিয়ে দেয় , তবে যেখানে প্রতিটি RUNকিছু যুক্ত করে, সেখানে কয়েকটি বিষয় আমাদের বিবেচনা করা উচিত:

  1. স্তরগুলি পূর্ববর্তীটির চেয়ে কেবল একটি পৃথক যুক্ত করার কথা, সুতরাং যদি পরবর্তী স্তরটি পূর্বের কোনওটিতে যুক্ত কিছু সরিয়ে না দেয় তবে উভয় পদ্ধতির মধ্যে খুব বেশি ডিস্কের স্থান সাশ্রয় করার সুযোগ থাকা উচিত নয় ...

  2. ডকার হাব থেকে স্তরগুলি সমান্তরালভাবে টানা হয়, সুতরাং Dockerfile.1, সম্ভবত কিছুটা বড় হলেও তাত্ত্বিকভাবে দ্রুত ডাউনলোড হতে পারে।

  3. যদি চতুর্থ বাক্য যুক্ত করা হয় (অর্থাত্‍ echo This is the D > d) এবং স্থানীয়ভাবে পুনর্নির্মাণ, Dockerfile.1ক্যাশে দ্রুত ধন্যবাদ তৈরি Dockerfile.2করতে পারে তবে সমস্ত 4 টি কমান্ড আবার চালাতে হবে।

সুতরাং, প্রশ্ন: ডকফাইফিল করার আরও ভাল উপায় কোনটি?


1
পরিস্থিতি এবং চিত্রের ব্যবহারের উপর নির্ভর করে (সাধারণ আকার, ডাউনলোডের গতি বা বিল্ডিংয়ের গতির জন্য অনুকূলিত করুন)
হেনরি

উত্তর:


99

যখন সম্ভব হয়, আমি সর্বদা কমান্ডগুলিকে একত্রে মার্জ করি যা কমান্ডগুলির সাহায্যে ফাইল তৈরি করে যা একই ফাইলগুলিকে একক RUNলাইনে মুছে দেয় । এটি কারণ প্রতিটি RUNলাইন চিত্রটিতে একটি স্তর যুক্ত করে, আউটপুটটি আক্ষরিক অর্থে ফাইল সিস্টেম পরিবর্তন হয় যা আপনি দেখতে পেতেনdocker diff এটি তৈরি করেছিলেন অস্থায়ী ধারকটিতেআপনি যদি অন্য কোনও স্তরটিতে তৈরি হওয়া কোনও ফাইল মুছে ফেলেন তবে সমস্ত ইউনিয়ন ফাইল সিস্টেম একটি নতুন স্তরের ফাইল-সিস্টেম পরিবর্তনকে নিবন্ধিত করবে, ফাইলটি পূর্ববর্তী স্তরে এখনও বিদ্যমান রয়েছে এবং এটি নেটওয়ার্কওয়াকে চালিত হয়ে ডিস্কে সঞ্চিত হয়। সুতরাং আপনি যদি সোর্স কোডটি ডাউনলোড করেন, এটি এক্সট্রাক্ট করুন, এটি একটি বাইনারি মধ্যে সংকলন করুন এবং তারপরে tgz এবং উত্স ফাইলগুলি মুছুন, আপনি চিত্রটির আকার হ্রাস করার জন্য সত্যই এটি একটি লেয়ারে সম্পন্ন করতে চান।

এরপরে, আমি অন্যান্য চিত্রগুলিতে পুনরায় ব্যবহারের সম্ভাবনা এবং প্রত্যাশিত ক্যাশে ব্যবহারের ভিত্তিতে ব্যক্তিগতভাবে স্তরগুলি বিভক্ত করি। যদি আমার কাছে 4 টি চিত্র থাকে তবে সমস্ত একই বেস ইমেজ (যেমন ডেবিয়ান) সহ, আমি সেই চিত্রগুলির বেশিরভাগের কাছে সাধারণ ইউটিলিটিগুলির একটি সংগ্রহ প্রথম রান কমান্ডের মধ্যে টানতে পারি যাতে অন্যান্য চিত্রগুলি ক্যাশে হওয়া থেকে উপকৃত হয়।

চিত্রের ক্যাশে পুনরায় ব্যবহারের দিকে তাকানোর সময় ডকফাইলে অর্ডার দেওয়া গুরুত্বপূর্ণ। আমি এমন কোনও উপাদান দেখি যা খুব কমই আপডেট হবে, সম্ভবত তখনই যখন বেস ইমেজ আপডেট হয় এবং সেগুলি ডকফাইফিলের উপরে রাখে। ডকফাইফাইলের শেষের দিকে, আমি এমন কোনও কমান্ড অন্তর্ভুক্ত করেছি যা দ্রুত চলবে এবং ঘন ঘন পরিবর্তিত হতে পারে, যেমন একটি হোস্ট নির্দিষ্ট ইউআইডি সহ কোনও ব্যবহারকারী যুক্ত করা বা ফোল্ডার তৈরি করা এবং অনুমতি পরিবর্তন করা। যদি ধারকটিতে সক্রিয়ভাবে বিকশিত হওয়া ব্যাখ্যা করা কোড (যেমন জাভাস্ক্রিপ্ট) অন্তর্ভুক্ত থাকে তবে এটি যতটা সম্ভব দেরীতে যুক্ত হয়ে যায় যাতে পুনর্নির্মাণ কেবল সেই একক পরিবর্তন চালায়।

এই প্রতিটি পরিবর্তনের গোষ্ঠীতে আমি স্তরগুলি হ্রাস করার জন্য যথাসম্ভব সর্বোত্তমভাবে একীকরণ করি। সুতরাং যদি সেখানে 4 টি ভিন্ন উত্স কোড ফোল্ডার থাকে তবে সেগুলি একটি একক ফোল্ডারে রাখা হয় যাতে এটি একটি একক কমান্ডের সাহায্যে যুক্ত করা যায়। প্যাকেজ ম্যানেজারের ওভারহেডের পরিমাণ হ্রাস করতে (আপডেট করা এবং পরিষ্কার করা) সম্ভব হলে অ্যাপট-গেটের মতো কিছু থেকে যে কোনও প্যাকেজ ইনস্টল করা একটি একক আরআনগুলিতে মিশে যায়।


মাল্টি-স্টেজ বিল্ডগুলির জন্য আপডেট:

মাল্টি-স্টেজ বিল্ডের চূড়ান্ত পর্যায়ে চিত্রের আকার হ্রাস করার বিষয়ে আমি খুব কম উদ্বেগ প্রকাশ করি। যখন এই পর্যায়গুলি ট্যাগ করা হয় না এবং অন্য নোডে প্রেরণ করা হয় না, আপনি প্রতিটি কমান্ডকে আলাদা RUNলাইনে ভাগ করে ক্যাশে পুনরায় ব্যবহারের সম্ভাবনা সর্বাধিক করে তুলতে পারেন ।

যাইহোক, স্তরগুলি স্কোয়াশ করার কোনও সঠিক সমাধান নয় কারণ আপনি পর্যায়গুলির মধ্যে অনুলিপি করা সমস্তগুলি ফাইল এবং পরিবেশের পরিবর্তনশীল সেটিংস, এন্ট্রিপয়েন্ট এবং কমান্ডের মতো চিত্রের মেটা-ডেটা নয়। এবং আপনি যখন কোনও লিনাক্স বিতরণে প্যাকেজ ইনস্টল করেন, সমস্ত নির্ভরতার অনুলিপি তৈরি করে লাইব্রেরি এবং অন্যান্য নির্ভরতা ফাইল সিস্টেমের মধ্যে ছড়িয়ে দেওয়া হতে পারে।

এ কারণে, আমি সিআই / সিডি সার্ভারে বাইনারিগুলি তৈরির প্রতিস্থাপন হিসাবে মাল্টি-স্টেজ বিল্ডগুলি ব্যবহার করি, যাতে আমার সিআই / সিডি সার্ভারে কেবল চালনার জন্য docker buildসরঞ্জামিং থাকা দরকার, এবং জেডিকে, নোডেজগুলি না যায়, এবং অন্য কোনও সংকলন সরঞ্জাম ইনস্টল করা আছে।


30

তাদের সেরা অনুশীলনে তালিকাভুক্ত সরকারী উত্তর (অফিসিয়াল চিত্রগুলি এগুলি মেনে চলতে হবে)

স্তরের সংখ্যা হ্রাস করুন

আপনাকে ডকফাইফাইলের পঠনযোগ্যতার (এবং এভাবে দীর্ঘমেয়াদী রক্ষণাবেক্ষণের) মধ্যে ভারসাম্য খুঁজে বের করতে হবে এবং এটি ব্যবহার করে স্তরগুলির সংখ্যা হ্রাস করতে হবে। আপনি যে স্তরটি ব্যবহার করেন সে সম্পর্কে কৌশলগত এবং সতর্ক হন।

Docker 1.10 যেহেতু COPY, ADDএবং RUNবিবৃতি আপনার ইমেজ করার জন্য একটি নতুন লেয়ার যোগ করুন। এই বিবৃতি ব্যবহার করার সময় সতর্ক হন। একক RUNবিবৃতিতে আদেশগুলি একত্রিত করার চেষ্টা করুন । পাঠযোগ্যতার জন্য প্রয়োজন হলে এটি আলাদা করুন।

আরও তথ্য: https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#/minimize-the-number-of-layers

আপডেট: ডকারে মাল্টি স্টেজ> 17.05

মাল্টি-স্টেজ FROMবিল্ডসের সাহায্যে আপনি আপনার ডকফাইলে একাধিক বিবৃতি ব্যবহার করতে পারেন । প্রতিটি FROMবিবৃতি একটি পর্যায় এবং এটির নিজস্ব বেস চিত্র থাকতে পারে। চূড়ান্ত পর্যায়ে আপনি আলপাইন এর মতো ন্যূনতম বেস ইমেজ ব্যবহার করেন, পূর্ববর্তী স্তরগুলি থেকে বিল্ড আর্টফেসগুলি অনুলিপি করুন এবং রানটাইম প্রয়োজনীয়তা ইনস্টল করুন। এই পর্যায়ের শেষ ফলাফলটি আপনার চিত্র। সুতরাং আপনি এখানে বর্ণিত স্তরগুলি সম্পর্কে উদ্বিগ্ন হন।

যথারীতি ডকারের মাল্টি-স্টেজ বিল্ডগুলিতে দুর্দান্ত ডক্স রয়েছে। এখানে একটি দ্রুত উদ্ধৃতাংশ:

মাল্টি-স্টেজ বিল্ডগুলির সাথে, আপনি আপনার ডকফাইলে একাধিক FROM বিবৃতি ব্যবহার করেন। প্রতিটি FROM নির্দেশাবলী আলাদা বেস ব্যবহার করতে পারে এবং তাদের প্রত্যেকটি বিল্ডের একটি নতুন পর্যায়ে শুরু করে। আপনি চূড়ান্ত চিত্রটিতে যা চান না তার সমস্ত কিছুই রেখে, বাছাই করে এক পর্যায় থেকে অন্য পর্যায়ে অনুলিপিগুলি অনুলিপি করতে পারেন।

এ সম্পর্কে একটি দুর্দান্ত ব্লগ পোস্টটি এখানে পাওয়া যাবে: https://blog.alexellis.io/mutli-stage-docker-builds/

আপনার পয়েন্ট উত্তর দিতে:

  1. হ্যাঁ, স্তরগুলি বিভিন্ন ধরণের মতো হয়। আমি মনে করি না যে একেবারে শূন্য পরিবর্তন থাকলে সেখানে স্তরগুলি যুক্ত হয়েছে। সমস্যাটি হ'ল একবার আপনি স্তর # 2 তে কিছু ইনস্টল / ডাউনলোড করলে আপনি স্তর # 3 এ এটি মুছতে পারবেন না। সুতরাং একবার কোনও স্তরে কিছু লেখা হয়ে গেলে, চিত্রটি সরিয়ে দিয়ে চিত্রের আকার আর হ্রাস করা যায় না।

  2. যদিও স্তরগুলি সমান্তরালভাবে টানা যেতে পারে, এটি সম্ভাব্যতর দ্রুত তৈরি করে, প্রতিটি স্তর নিঃসন্দেহে চিত্রের আকার বাড়িয়ে দেয়, এমনকি তারা ফাইলগুলি সরিয়ে দিচ্ছে।

  3. হ্যাঁ, আপনি যদি আপনার ডকার ফাইল আপডেট করে থাকেন তবে ক্যাচিং কার্যকর। তবে এটি এক দিকে কাজ করে। আপনার যদি 10 স্তর থাকে এবং আপনি স্তর # 6 পরিবর্তন করেন তবে আপনাকে স্তর # 6- # 10 থেকে সমস্ত কিছু পুনর্নির্মাণ করতে হবে। সুতরাং এটি প্রায়শই নয় যে এটি বিল্ড প্রক্রিয়াটিকে ত্বরান্বিত করবে, তবে এটি আপনার চিত্রের আকার অকারণে বাড়ানোর গ্যারান্টিযুক্ত।


এই উত্তরটি আপডেট করার জন্য আমাকে স্মরণ করিয়ে দেওয়ার জন্য @ মোহনকে ধন্যবাদ ।


1
এটি এখন পুরানো - নীচের উত্তর দেখুন।
মোহন

1
@ মোহন মনে করিয়ে দেওয়ার জন্য ধন্যবাদ! আমি ব্যবহারকারীদের সাহায্যের জন্য পোস্ট আপডেট করেছি।
মেনজো উইজমেঙ্গা

19

দেখে মনে হচ্ছে উপরের উত্তরগুলি পুরানো। দস্তাবেজ নোট:

ডকার 17.05 এর আগে এবং আরও অনেক আগে ডকার 1.10 এর আগে আপনার ইমেজের স্তরগুলির সংখ্যা হ্রাস করা গুরুত্বপূর্ণ ছিল। নিম্নলিখিত উন্নতিগুলি এই প্রয়োজনীয়তা হ্রাস করেছে:

[...]

ডকার ১.0.০৫ এবং উচ্চতর মাল্টি-স্টেজ বিল্ডগুলির জন্য সমর্থন যোগ করে, যা আপনাকে কেবল চূড়ান্ত চিত্রটিতে অনুলিপি করতে সক্ষম করে। এটি আপনাকে চূড়ান্ত চিত্রের আকার না বাড়িয়ে আপনার মধ্যবর্তী বিল্ড পর্যায়ে সরঞ্জাম এবং ডিবাগ তথ্য অন্তর্ভুক্ত করার অনুমতি দেয়।

https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#minimize-the-number-of-layers

এবং

লক্ষ্য করুন যে চিত্রটিতে অতিরিক্ত স্তর তৈরি এড়াতে এই উদাহরণটি বাশ ও অ্যান্ড অপারেটর ব্যবহার করে দুটি আরএন কমান্ডকে কৃত্রিমভাবে সংকুচিত করে। এটি ব্যর্থতাপ্রবণ এবং বজায় রাখা শক্ত।

https://docs.docker.com/engine/userguide/eng-image/multistage-build/

সেরা অনুশীলনটি মাল্টিস্টেজ বিল্ডগুলি ব্যবহার করে এবং পাঠ্যযোগ্য রাখার জন্য পরিবর্তিত হয়েছে বলে মনে হয় Dockerfile


যদিও মাল্টিস্টেজ বিল্ডগুলি ভারসাম্য বজায় রাখার জন্য একটি ভাল বিকল্প বলে মনে হচ্ছে, docker image build --squashবিকল্পটি পরীক্ষামূলকভাবে বাইরে গেলে এই প্রশ্নের আসল ফিক্স আসবে ।
ইয়াজো

2
@ ইয়াজো - আমি squashঅতীত পরীক্ষামূলক হয়ে উঠতে সংশয়ী । এটিতে অনেকগুলি কল্পনা রয়েছে এবং বহু-পর্যায়ের বিল্ডিংয়ের আগে কেবল তা উপলব্ধি করা হয়েছে। মাল্টি স্টেজ বিল্ডসের সাথে আপনাকে কেবল চূড়ান্ত পর্যায়ে অনুকূলকরণ করতে হবে যা খুব সহজ।
মেনজো উইজমেঙ্গা

1
@ ইয়াজো এটি প্রসারণ করতে, কেবলমাত্র শেষ পর্যায়ে স্তরগুলি চূড়ান্ত চিত্রের আকারের সাথে কোনও পার্থক্য করে। সুতরাং আপনি যদি আপনার সমস্ত বিল্ডার গবিনগুলি পূর্বের পর্যায়ে রাখেন এবং চূড়ান্ত পর্যায়ে কেবল প্যাকেজ ইনস্টল করে এবং পূর্ববর্তী স্তরগুলি থেকে সমস্ত ফাইল জুড়ে অনুলিপি করা হয় তবে সবকিছু সুন্দরভাবে কাজ করে এবং স্কোয়াশের প্রয়োজন হয় না।
মোহন

3

এটি আপনার ইমেজ স্তরগুলিতে অন্তর্ভুক্ত ওয়াহতের উপর নির্ভর করে।

মূল বিষয়টি যথাসম্ভব অনেক স্তর ভাগ করা:

খারাপ উদাহরণ:

Dockerfile.1

RUN yum install big-package && yum install package1

Dockerfile.2

RUN yum install big-package && yum install package2

ভালো উদাহরণ:

Dockerfile.1

RUN yum install big-package
RUN yum install package1

Dockerfile.2

RUN yum install big-package
RUN yum install package2

যোগ করার / ইনস্টল করার ক্রিয়া হিসাবে একই স্তরে ঘটে তবেই মুছে ফেলা হচ্ছে অন্য একটি পরামর্শ।


এই 2 কি সত্যিই RUN yum install big-packageক্যাশে থেকে ভাগ করে নেবে ?
ইয়াজো

হ্যাঁ, তারা একই স্তরটি ভাগ করে নেবে, তবে তারা একই ভিত্তি থেকে শুরু করে।
ওন্দ্রা Žižka
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.