Віртуалізація на рівні операційної системи стає все більш популярним рішенням при розгортанні застосунків у різних середовищах. Чи не найбільш вдалим інструментом для цього є Docker.
У двох статтях на Highload я розповім про основні можливості інструменту. Ви дізнаєтесь, як встановити, налаштувати та запустити Docker, а також як працювати з його ключовими елементами: Dockerfile, Docker Image та Docker Container.
Віртуальна машина виступає як емулятор ПЗ. Припустимо, на комп’ютері вже є Windows і потрібно додатково встановити, наприклад, Ubuntu. Створюємо на тому ж комп’ютері віртуальну машину і вже на неї встановлюємо додаткову ОС. У результаті матимемо ніби два комп’ютери водночас. Однак для віртуальної машини потрібне місце на жорсткому диску, вдосталь оперативної пам’яті та ресурсів процесору.
На противагу цьому з’явився принцип контейнерів, на якому побудований Docker та інші схожі інструменти. Головна відмінність — у власній інфраструктурі та єдиній для всіх середовищ ОС. Зверху цієї основи встановлюється Docker, завдяки якому можна створювати безліч контейнерів, аплікацій тощо.
Docker розділяє єдине ядро ОС на окремі контейнери, під кожний із яких виділяється свій процес. Це набагато зручніше, ніж віртуальна машина. Вам не потрібно шукати ще й пам’ять, диск, оперативку, адже окремий процес витягає значно менше ресурсів.
Коли ви працюєте з багатьма віртуальними машинами, часто вони заважають одна одній. Docker же може запускати в ядрі будь-який застосунок, який буде повністю ізольований від інших. Окрім цього, на фоні конкурентів Docker виграє за рахунок простого синтаксису. Також його можна запустити на всіх популярних платформах: Linux, Windows, Mac.
Головний принцип роботи з Docker можна описати у вигляді гасла з трьох слів: Build, Ship, Run. Кожне з них означає певний етап та елемент системи:
Так все і працює: будуєте Dockerfile, з нього створюєте Docker Image, а на його основі запускаєте Docker Container. Далі про кожний елемент системи розповім окремо.
Dockerfile — це звичайний текстовий документ, який ми називаємо Dockerfile без усіляких крапок в кінці. Цей файл розміщується у папці з проєктом. У ньому ви записуєте команди, за якими буде створюватися Image, а потім — запускатися Container.
На ілюстрації нижче прописані наступні команди:
Таким чином ми прописуємо в Dockerfile команди одна за одною. Так само покроково вони будуть виконуватися автоматично згідно цієї інструкції. Як бачите, синтаксис дійсно дуже простий:
Може здатися, що вони однакові за функціоналом, та це не зовсім так. CMD — команда, яка прописується в консоль при запуску Dockerfile. Якщо повернутися до попереднього прикладу, то для запуску сервера потрібні python, manage.py, runserver, IP та порт. І все це прописується саме в CMD, після чого запускається сервер.
ENTRYPOINT так само запускає команду, яку ми хочемо прописати. Але він виконує це перед CMD, якщо ми використовуємо їх разом. Саме тому ENTRYPOINT і називається «точкою входу» — бо це буде перша команда.
Беремо Debian, копіюємо проєкт, запускаємо apt-get update
і зводимо CMD. Якщо нам потрібно змінити цю команду, то при запуску Docker можна прописати docker run image
. Тоді виконається команда, прописана в Dockerfile по дефолту.
Якщо ж ми хочемо виконати іншу команду, то пишемо docker run my-image
і вказуємо нову команду. Це може бути, наприклад, вказівка перевірити список усіх елементів на Ubuntu. У результаті попередня команда буде замінена в CMD на ту, яку ми вказали:
Якщо ENTRYPOINT та CMD використовувати разом, то перша завжди стартує швидше. Вона може знадобитися, коли до основних команд з CMD потрібно запустити ще якусь команду. До прикладу, певна перевірка проєкту. В такому разі ви прописуєте відповідну команду ENTRYPOINT, а потім — основні параметри в CMD. Цей процес наведений на ілюстрації нижче:
docker run my-container
запишуться параметри та ENTRYPOINT, які вже є в Dockerfile. А якщо потрібно запустити інші CMD-команди, то знадобиться docker run my-container cmd
:
docker run --entrypoint
і шлях до entrypoint.sh
(це entrypoint, який буде змінюватися), а також назву контейнера. Зверніть увагу: ви маєте вказати, що переписуєте саме ENTRYPOINT:
Розповідаючи про Dockerfile, варто згадати і про Dockerignore. Це аналог .gitignore
в Git. Завдяки цьому функціоналу при копіюванні проєкту в контейнер ви можете вказати певні файли, які не хочете переносити разом з іншими. Це може стосуватися pycache, логів, environments, docs тощо. У такому разі прописуєте назви файлів у dockerignore, і вони будуть просто ігноруватися при копіюванні проєкту.
Спочатку ви прописуєте основу майбутнього контейнера. Наприклад, при FROM python
це буде Python певної версії, і він стає на базовий рівень усієї схеми. У нашому випадку далі йде Django, але можуть бути й потрібні для проєкту бібліотеки, requirements.txt, залежності тощо. Все це формує середній шар документу. Наприкінці маємо верхній шар, який власне запускає застосунок — це CMD-команда:
Цей процес можна порівняти з будівництвом дому. У якості фундаменту виступає найбільша частина: Python, Ubuntu, Anaconda тощо. Далі йдуть основні поверхи, більш компактні за розміром — бібліотеки та залежності. І вже на горищі розміщується найменша та найлегша частина — run проєкту контейнера.
Щоб усі шари були зрозумілими, раджу ретельно прописувати Layers. Порівняйте на наступній ілюстрації приклади поганого та гарного виконання шарів у Dockerfile. Код у лівій та правій частинах зображення виконує по суті одне й те саме, проте розміри відрізняються чи не вдвічі. Розібратися складно, особливо якщо немає достатнього досвіду з Docker.
В іншому прикладі одразу зрозуміло, що й до чого. Тут чітко видно встановлені Python, Java та virtual environment, а також їх активацію. В поганому ж прикладі безліч записів про оновлення, інсталяцію та ребілд Python, встановлення залежностей, активацію virtual environments та багато іншого. Це не тільки важче читати. Це ще й складніше виконувати. Тому Dockerfile із безліччю шарів запускатиметься довше.
Docker Image — це блок, створений за інструкцією з Dockerfile, що виступає шаблоном запуску контейнерів. За допомогою цього документу можна побудувати безліч однакових контейнерів.
Припустимо, ви створюєте один шаблон, який має встановити Python і певні залежності на нього, і вам потрібно п’ять однакових контейнерів. У такому випадку не потрібно прописувати п’ять Dockerfile. Достатньо одного такого файлу для створення Docker Image, який ви будете ранити п’ять разів.
При роботі з Docker Image виділяють декілька найбільш використовуваних команд:
docker image --help
показує основні команди в Image з їх коротким описом.docker image build [OPTIONS] PATH
.
Білдить сам Image для подальшого запуску Container. За допомогою цієї команди ви можете назвати свій Image. Для цього додайте тег -t
, а за ним вкажіть бажану назву (у моєму прикладі test
). Вам залишається прописати шлях до директорії (крапка у наведеному прикладі означає поточну директорію). Після запуску команди і почне будуватися Image: від створення директорії, встановлення Django, whitenoise, gunicorn до копіювання.У моєму випадку Docker image збілджений на основі цього Dockerfile:
docker image inspect [OPTIONS] IMAGE
.
Ця команда видає всю інформацію про Image. Це можуть бути ID, дата створення, пов’язані контейнери та енвайроменти, версія Python, наявні pip і get pip, CMD і ENTRYPOINT, Volumes, директорії тощо. При запуску команди вказуйте назву Image, який вас цікавить.docker image ls
показує список усіх Image, які є в Docker. На прикладі зображено перелік із декількох тестових Docker Image:docker image rm [OPTIONS] IMAGE
призначена для видалення Image. Нижче на ілюстрації я зобразив типовий сценарій такої процедури. Спочатку за допомогою docker image ls
отримав перелік усіх Image. Далі прописав docker image rm
, зазначивши назву Image, який потрібно видалити — dockertest2
. Ще одна перевірка docker image ls
показала: того Image більше немає у Docker.docker image tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
.
За допомогою цієї команди ви можете затегати Docker Image. Це знадобиться при використанні Docker Hub, де всі зібрані Images мають теги. У наступній статті поговоримо про нього детальніше.Продовження статті про можливості Docker читайте згодом на Highload.
Читайте також: Робимо розробку зручною: як використовувати Docker у роботі з мікросервісами
Блогер та розробник Джозеф Круз розповів, чому не варто писати ідеальний код та чому це…
Днями я завзято нила про щось ChatGPT (експериментую між сеансами з живим терапевтом). І от…
«Крутіть колесо, щоб отримати знижку до 50%!» «Натисніть тут, щоб відкрити таємничу пропозицію!» «Зареєструйтесь зараз,…
Дуже хочеться робити якісь десктопні апки. Сумую за часами коли всі програми були offline-first, і…
Надсилаючи криптовалюту, багато новачків ставлять запитання: як працюють комісії та чому вони відрізняються в різних…
Нова афера набирає обертів — ось детальний розбір того, як фальшиві потенційні роботодавці намагаються вкрасти…