ตอนที่ฉันเรียนขับรถ ในบทเรียนแรกๆ ผู้สอนขับรถเข้าทางแยกแล้วบอกว่าอย่าทำอย่างนั้น ไม่เคยเลย ฉันจำกฎนี้ได้ทันทีและตลอดชีวิต
คุณอ่าน "Bad Advice" ของ Grigory Oster ให้เด็กๆ ฟัง และคุณจะเห็นว่าพวกเขาไม่ควรทำเช่นนี้ได้ง่ายและเป็นธรรมชาติเพียงใด
มีการเขียนบทความมากมายเกี่ยวกับวิธีเขียน Dockerfile อย่างถูกต้อง แต่ฉันไม่พบคำแนะนำในการเขียน Dockerfiles ที่ไม่ถูกต้อง ฉันกำลังเติมเต็มช่องว่างนี้ และบางทีในโครงการที่ฉันได้รับการสนับสนุนก็อาจมี dockerfiles ดังกล่าวน้อยลง
ตัวละคร สถานการณ์ และ Dockerfile ทั้งหมดเป็นสิ่งสมมติ ถ้ารู้จักตัวเองก็ขออภัยด้วย
การสร้าง Dockerfile เป็นลางร้ายและแย่มาก
Peter (นักพัฒนา Java/rubby/php อาวุโส): เพื่อนร่วมงาน Vasily คุณได้อัปโหลดโมดูลใหม่ไปยัง Docker แล้วหรือยัง?
Vasily (รุ่นน้อง): ไม่ ฉันไม่มีเวลา ฉันไม่เข้าใจนักเทียบท่าคนนี้ มีบทความมากมายเกี่ยวกับเรื่องนี้มันเวียนหัว
ปีเตอร์: เรามีกำหนดเส้นตายเมื่อปีที่แล้ว ให้ฉันช่วยคุณ เราจะคิดออกในกระบวนการนี้ บอกฉันว่าอะไรไม่ได้ผลสำหรับคุณ
Vasily: ฉันไม่สามารถเลือกภาพพื้นฐานเพื่อให้เป็นภาพมินิมอลได้ แต่มีทุกสิ่งที่คุณต้องการ
ปีเตอร์: ลองใช้อิมเมจของ Ubuntu มันมีทุกสิ่งที่คุณต้องการ และสิ่งที่ไม่จำเป็นมากมายจะมีประโยชน์ในภายหลัง และอย่าลืมใส่แท็กล่าสุดเพื่อให้เวอร์ชันล่าสุดอยู่เสมอ
และบรรทัดแรกปรากฏใน Dockerfile:
FROM ubuntu:latest
ปีเตอร์: อะไรต่อไป เราใช้อะไรในการเขียนโมดูลของเรา?
Vasily: ดังนั้น Ruby มีเว็บเซิร์ฟเวอร์และควรมีการเปิดตัวบริการดีมอนสองสามรายการ
Peter: ใช่แล้ว เราต้องการอะไร: ruby, Bundler, nodejs, imagemagick และอื่นๆ... และในขณะเดียวกันก็อัปเกรดเพื่อรับแพ็คเกจใหม่อย่างแน่นอน
Vasily: และเราจะไม่สร้างผู้ใช้เพื่อที่เราจะไม่รูตใช่ไหม?
ปีเตอร์: ให้ตายเถอะ แล้วคุณยังต้องเล่นตลกเรื่องสิทธิอีก
Vasily: ฉันต้องการเวลาประมาณ 15 นาทีเพื่อรวมทุกอย่างไว้ในคำสั่งเดียว ฉันอ่านเจอว่า...
(ปีเตอร์ขัดจังหวะรุ่นน้องที่พิถีพิถันและฉลาดมากอย่างหยาบคาย)
ปีเตอร์: เขียนคำสั่งแยกกันจะอ่านง่ายกว่า
Dockerfile เติบโตขึ้น:
FROM ubuntu:latest
RUN apt-get update
RUN apt-get upgrade
RUN apt-get -y install libpq-dev imagemagick gsfonts ruby-full
RUN gem install bundler
RUN curl -sL https://deb.nodesource.com/setup_9.x | sudo bash -
RUN apt-get install -y nodejs
RUN bundle install --without development test --path vendor/bundle
RUN rm -rf /usr/local/bundle/cache/*.gem
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
จากนั้น Igor Ivanovich, DevOps (แต่ Ops มากกว่า Dev) ก็บุกเข้าไปในห้องทำงานตะโกน:
AI: Petya นักพัฒนาของคุณทำลายฐานข้อมูลอาหารอีกครั้ง เมื่อไหร่จะจบลง...
หลังจากการปะทะกันเล็กน้อย Igor Ivanovich ก็เย็นลงและเริ่มค้นหาว่าเพื่อนร่วมงานของเขากำลังทำอะไรที่นี่
ไอ: คุณกำลังทำอะไรอยู่?
Vasily: Peter กำลังช่วยฉันสร้าง Dockerfile สำหรับโมดูลใหม่
AI: ขอฉันดูหน่อยสิ... คุณเขียนอะไรที่นี่ คุณล้างพื้นที่เก็บข้อมูลด้วยคำสั่งแยกต่างหาก นี่คือเลเยอร์เพิ่มเติม... แต่คุณจะติดตั้งการพึ่งพาได้อย่างไร หากคุณไม่ได้คัดลอก Gemfile! และโดยทั่วไปแล้วสิ่งนี้ไม่ดี
ปีเตอร์: กรุณาไปเกี่ยวกับธุรกิจของคุณเราจะคิดออกอย่างใด
Igor Ivanovich ถอนหายใจอย่างเศร้าและจากไปเพื่อดูว่าใครเป็นผู้ทำลายฐานข้อมูล
ปีเตอร์: ใช่ แต่เขาพูดถูกเกี่ยวกับโค้ด เราต้องใส่มันเข้าไปในภาพ และมาติดตั้ง ssh และ supervisor ทันที ไม่เช่นนั้นเราจะเริ่ม daemons
Vasily: จากนั้นฉันจะคัดลอก Gemfile และ Gemfile.lock ก่อน จากนั้นฉันจะติดตั้งทุกอย่าง จากนั้นฉันจะคัดลอกทั้งโครงการ หาก Gemfile ไม่เปลี่ยนแปลง เลเยอร์นั้นจะถูกนำออกจากแคช
ปีเตอร์: ทำไมคุณถึงมีเลเยอร์เหล่านี้ คัดลอกทุกอย่างพร้อมกัน คัดลอกได้ทันที บรรทัดแรกสุด
ขณะนี้ Dockerfile มีลักษณะดังนี้:
FROM ubuntu:latest
COPY ./ /app
WORKDIR /app
RUN apt-get update
RUN apt-get upgrade
RUN apt-get -y install libpq-dev imagemagick gsfonts ruby-full ssh supervisor
RUN gem install bundler
RUN curl -sL https://deb.nodesource.com/setup_9.x | sudo bash -
RUN apt-get install -y nodejs
RUN bundle install --without development test --path vendor/bundle
RUN rm -rf /usr/local/bundle/cache/*.gem
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
ปีเตอร์: แล้วไงต่อ? คุณมีการกำหนดค่าสำหรับหัวหน้างานหรือไม่?
วาซิลี: ไม่ ไม่ แต่ฉันจะทำมันอย่างรวดเร็ว
ปีเตอร์: แล้วคุณจะทำมัน ตอนนี้เรามาร่างสคริปต์เริ่มต้นที่จะเปิดตัวทุกอย่างกัน โอเค คุณเริ่ม ssh ด้วย nohup เพื่อให้เราสามารถเชื่อมต่อกับคอนเทนเนอร์และดูว่ามีอะไรผิดพลาด จากนั้นเรียกใช้ผู้บังคับบัญชาในลักษณะเดียวกัน ถ้าอย่างนั้นคุณก็เรียกใช้ผู้โดยสาร
ถาม: แต่ฉันอ่านเจอว่าควรมีกระบวนการหนึ่ง ดังนั้น Docker จะรู้ว่ามีบางอย่างผิดพลาดและสามารถรีสตาร์ทคอนเทนเนอร์ได้
ป: อย่าไปยุ่งกับเรื่องไร้สาระ และโดยทั่วไปเป็นอย่างไร? คุณจะดำเนินการทั้งหมดนี้ในกระบวนการเดียวได้อย่างไร? ให้ Igor Ivanovich คิดเกี่ยวกับความมั่นคงไม่ใช่เพื่ออะไรที่เขาได้รับเงินเดือน งานของเราคือการเขียนโค้ด โดยทั่วไปให้เขากล่าวขอบคุณที่เราเขียน Dockefile ให้เขา
10 นาทีกับสองวิดีโอเกี่ยวกับแมวต่อมา
ถาม: ฉันทำทุกอย่างแล้ว ฉันเพิ่มความคิดเห็นเพิ่มเติม
พ: แสดงให้ฉันดู!
Dockerfile เวอร์ชันล่าสุด:
FROM ubuntu:latest
# Копируем исходный код
COPY ./ /app
WORKDIR /app
# Обновляем список пакетов
RUN apt-get update
# Обновляем пакеты
RUN apt-get upgrade
# Устанавливаем нужные пакеты
RUN apt-get -y install libpq-dev imagemagick gsfonts ruby-full ssh supervisor
# Устанавливаем bundler
RUN gem install bundler
# Устанавливаем nodejs используется для сборки статики
RUN curl -sL https://deb.nodesource.com/setup_9.x | sudo bash -
RUN apt-get install -y nodejs
# Устанавливаем зависимости
RUN bundle install --without development test --path vendor/bundle
# Чистим за собой кэши
RUN rm -rf /usr/local/bundle/cache/*.gem
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Запускаем скрипт, при старте контейнера, который запустит все остальное.
CMD [“/app/init.sh”]
พี: เยี่ยมเลย ฉันชอบมัน และคอมเม้นท์เป็นภาษารัสเซีย สะดวก และอ่านง่าย ใครๆ ก็คงคิดแบบนั้น ฉันสอนคุณทุกอย่างแล้ว ที่เหลือคุณทำเองได้ ไปดื่มกาแฟกันเถอะ...
ตอนนี้เรามี Dockerfile ที่แย่มากการมองเห็นซึ่งจะทำให้ Igor Ivanovich ต้องการเลิกและดวงตาของเขาจะเจ็บไปอีกสัปดาห์ แน่นอนว่า Dockerfile อาจแย่ยิ่งกว่านั้นอีก ไม่มีข้อจำกัดในเรื่องความสมบูรณ์แบบ แต่สำหรับการเริ่มต้น สิ่งนี้จะทำ
ฉันอยากจะจบด้วยคำพูดจาก Grigory Oster:
หากคุณยังไม่แน่ใจ
เราเลือกเส้นทางชีวิต
และคุณไม่รู้ว่าทำไม
เริ่มต้นการเดินทางแรงงานของคุณ
ทำลายหลอดไฟในโถงทางเดิน -
ผู้คนจะพูดว่า "ขอบคุณ" กับคุณ
คุณจะช่วยเหลือผู้คน
ประหยัดไฟฟ้า.
ที่มา: will.com