Skip to content

Docker

Docker and docker-compose

Що таке контейнеризація? Навіщо вона потрібна?

Контейнеризація - це технологія упаковки та виконання програмного забезпечення разом із всіма його залежностями та середовищем відокремлено від інших додатків. Вона потрібна для полегшення розгортання, масштабування та управління додатками, забезпечуючи консистентність між середовищами розробки та виробництва.

Контейнер - це ізольований процес, який використовує основне ядро операційної системи, який працює зі своїм шматочком файлової системи, пам'яті, ядром та іншими ресурсами. При цьому він думає, що всі ресурси належать йому.

Робота з контейнерами допомагає вирішити наступні проблеми

  • ефективного використання ресурсів (на одному сервері можна запустити кілька контейнерів);
  • ізоляції додатків;
  • установки операційної системи (фактично, ми використовуємо хост-операційну систему);
  • налаштування середовища для додатка (можна один раз налаштувати середовище і швидко клонувати його між контейнерами).

Чим контейнер відрізняється від віртуальної машини?

Контейнер відрізняється від віртуальної машини тим, що він ділиться операційною системою з хостом та використовує власний ізольований простір для виконання додатку. На відміну від віртуальних машин, які потребують окремої гостьової ОС для кожного екземпляра, контейнери легше та швидше запускаються, ефективніше використовують ресурси та забезпечують більшу гнучкість.

Що таке Docker?

Docker - це інструмент для для створення, розгортання та управління контейнерами, який дозволяє упаковувати додаток і всі його залежності в єдиний контейнер, який може бути запущений на будь-якій платформі, що підтримує Docker, забезпечуючи ізоляцію, переносимість та консистентність роботи додатків у різних середовищах.

Контейнери не знають, що поруч розгорнуті інші контейнери з додатками, вони повністю ізольовані один від одного. У кожному контейнері можна налаштувати середовище, необхідне саме для цього додатка.

Контейнери Docker засновані на образах, які включають все необхідне для запуску програми: код, бібліотеки, системні інструменти та налаштування.

Docker надає наступні переваги в процесі розробки

  • Підвищення портативності додатків. Docker дозволяє упаковувати додаток і всі його залежності в єдиний контейнер, який може бути запущений на будь-якій платформі, що підтримує Docker. Це підвищує портативність додатків і прискорює їх розгортання.
  • Прискорення процесу розробки. Docker дозволяє швидко створювати та запускати контейнери, що прискорює процес розробки та тестування додатків.
  • Покращення безпеки. Docker забезпечує ізоляцію контейнерів, що дозволяє уникнути конфліктів між додатками та покращує безпеку додатків.
  • Збільшення масштабованості. Docker дозволяє швидко масштабувати додатки, додаючи нові контейнери при необхідності.

Docker Image (образ)

Docker Image - це шаблон для створення контейнерів . Він містить усі необхідні компоненти для запуску контейнера, включаючи операційну систему, програму, бібліотеки та залежності, а також конфігураційні файли. Він використовується для створення контейнерів та розгортання контейнерів з ідентичним середовищем виконання, та забезпечує консистентність усіх середовищ, де запускається додаток.

У Image описано, що повинно бути встановлено в контейнері та які дії потрібно виконати при запуску контейнера.

Образи Docker створюються на основі Dockerfile, в якому задається послідовність команд для встановлення та налаштування всіх необхідних компонентів. Dockerfile містить інструкції для збирання образу.

Dockerfile з образом простого веб-додатку на Python

FROM python:3.8-slim
WORKDIR /app
COPY. /app
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

У цьому Dockerfile використовуються команди для вказівки базового образу Python, установки робочого каталогу, копіювання файлів програми, встановлення залежностей та завдання за промовчанням для запуску програми.

Кешування в образах

Образ Docker складається зі шарів (layers), кожен з яких представляє собою окремий набір змін у файловій системі. Коли Docker збирає образ, кожний шар кешується окремо. Якщо певний шар вже був побудований та не зазнав змін у Dockerfile, Docker використовує його з кешу, замість того, щоб будувати його знову. Це забезпечує ефективність та прискорює процес збірки образів.

Docker використовує унікальні ідентифікатори (hashes) для кожного шару образу, засновані на вмісті цього шару. Ці ідентифікатори використовуються для порівняння і визначення, чи є шар в кеші. Якщо ідентифікатори шарів у Dockerfile змінилися, Docker перебудовує лише ті шари, які мають нові зміни, зберігаючи старі шари з кешу.

# Example Dockerfile where the layer with dependencies installation is cached
FROM python:3.8-slim

# Copy files into the working directory
COPY . /app

# Install dependencies, this layer will be cached if requirements.txt remains unchanged
RUN pip install --no-cache-dir -r /app/requirements.txt

# Command to run the application
CMD ["python", "/app/app.py"]

У цьому прикладі pip install кешується, якщо requirements.txt залишається незмінним, забезпечуючи швидку збірку образу в майбутньому. Це особливо корисно при розробці, коли ви часто змінюєте код, але залежності залишаються сталими.

Docker Container (контейнер)

Контейнер - це виконуваний екземпляр Docker образу. Його можна створювати, запускати, зупиняти та видаляти. Також можна приєднувати до контейнера сховище, об'єднувати контейнери однією чи кількома мережами та взаємодіяти з контейнерами, використовуючи Docker API або CLI. Контейнер являє собою ізольоване оточення, в якому виконується програма разом з усіма його залежностями, бібліотеками та конфігураціями, використовуючи ресурси операційної системи.

Для перегляду списку запущених контейнерів можна використовувати команду docker ps.

Cтани контейнера Docker

  • Created – контейнер створений, але не активний.
  • Restarting – контейнер у процесі перезапуску.
  • Running - контейнер працює.
  • Paused - контейнер призупинено.
  • Exited – контейнер закінчив свою роботу.
  • Dead – контейнер, який сервіс спробував зупинити, але не зміг.

Docker Volume (том)

Docker Volume - це механізм у Docker, що дозволяє зберігати та управляти даними поза контейнером (на жорсткому диску сервера, а не всередині контейнера). Він надає зручний спосіб зберігання та обміну даними між контейнерами, а також зберігання даних після видалення контейнера. volumes завжди використовуються при запуску баз даних у контейнері.

Коли контейнер знищується, то знищуються усі дані, які були всередині. Docker Volume натомість відключає прив'язку даних до життєвого циклу контейнера, дозволяючи отримати доступ до даних контейнера у будь-який момент. Таким чином, записи, зроблені в контейнерах, залишаються доступними після знищення контейнера, що їх містив, і можуть бути повторно використані в інших контейнерах.

Docker Volumes працюють так - на сервері створюється каталог, який потім приєднується до одного або декількох контейнерів. При цьому каталог є незалежним, оскільки не включається до структури шарів образу Docker. Це дозволяє обійти обмеження read only для створюваних контейнерів з таким каталогом всередині.

Створення volume у Docker виконується за допомогою команди docker volume create <volume_name>, після чого volume можна використовувати для монтування у контейнери. Монтування volume у контейнер здійснюється під час запуску контейнера з використанням опції -v або --mount. Наприклад, команда docker run -v my-volume:/path/to/mount my-image монтує volume з ім'ям my-volume у контейнері за вказаним шляхом.

Docker Network (мережа)

Мережа контейнера в Docker - це віртуальна мережа, яка забезпечує зв'язок між контейнерами та зовнішніми ресурсами. Вона дозволяє контейнерам спілкуватися та обмінюватися даними, а також надає можливість наділити контейнери окремими мережевими ресурсами.

Які типи мереж існують в Docker?

У Docker існують такі типи мереж

  • "bridge" (внутрішня мережа)
  • "host" (мережа хоста),
  • "overlay" (накладна мережа) Вони дозволяють контролювати спосіб зв'язку між контейнерами та гнучко налаштовувати мережеві параметри.

Dockerfile

Dockerfile - це текстовий файл, який містить набір інструкцій для автоматизованого створення Docker образу. Цей файл містить інструкції про те, як конфігурувати базовий образ, додавати потрібні залежності, копіювати файли та налаштовувати середовище для додатка.

Кожна інструкція в Dockerfile додає новий шар у кінцевий образ, що дозволяє точно визначити, які кроки та компоненти необхідні для створення контейнера. Це забезпечує відтворюваність та консистентність оточення, в якому виконуватиметься додаток.

Основні інструкції в Dockerfile включають FROM, COPY, RUN, CMD, ENTRYPOINT та EXPOSE. Інструкція FROM задає базовий образ, на основі якого будуватиметься новий образ. COPY копіює файли та каталоги з локальної машини в образ. RUN виконує команди в процесі збирання образу, такі як встановлення залежностей. CMD та ENTRYPOINT задають команди, які будуть виконані під час запуску контейнера. EXPOSE вказує, які порти використовуватимуться контейнером.

FROM python:3.8-slim  # Use the official Python base image with version 3.8
WORKDIR /app  # Set the working directory in the container
COPY . /app  # Copy files from the current directory to the container
RUN pip install --no-cache-dir -r requirements.txt  # Install necessary packages via pip
CMD ["python", "app.py"]  # Run the application upon container start

Чим відрізняється ENTRYPOINT від CMD?

CMD та ENTRYPOINT використовуються для визначення команд, які повинні виконуватися при запуску контейнера.

ENTRYPOINT визначає основну команду, яка буде виконуватися завжди, і дозволяє передавати додаткові аргументи. Якщо вказаний ENTRYPOINT, аргументи, передані при запуску контейнера, додаються як аргументи до цієї команди. Не замінюється - якщо контейнер запускається з додатковими аргументами, вони додаються до ENTRYPOINT замість його заміни.

CMD задає команду за замовчуванням, яка може бути замінена аргументами, вказаними під час запуску контейнера. Якщо контейнер запускається з додатковими аргументами, вони замінюють CMD.

Тобто, ENTRYPOINT вказує на основну команду, яка має бути завжди виконана, тоді як CMD вказує на аргументи, які можуть бути змінені при запуску контейнера. Якщо ENTRYPOINT не вказано, CMD може вказати основну команду для виконання контейнера за замовчуванням. Якщо контейнер запускається з іншими аргументами, CMD буде перевизначена.

Обидві директиви можуть використовуватися разом для гнучкої конфігурації поведінки контейнера.

Multi Stage Building

Multi Stage Building - це техніка у Docker, яка дозволяє створювати оптимізовані та менш розміром образи за допомогою кількох стадій збірки.

Замість одного Dockerfile, який містить всі кроки збірки, створюється кілька стадій. Кожна стадія може використовувати окремий базовий образ та виконувати певні дії, наприклад, встановлення залежностей, компіляцію коду або копіювання файлів. Після завершення роботи кожної стадії вибирають лише необхідні файли або бінарні дані та використовують їх у наступній стадії. Це дозволяє уникнути занадто великого образу, оскільки лише необхідні компоненти переходять до наступних етапів збірки.

# First stage: Compiling code using a compiler
FROM compiler-base-image AS compiler
WORKDIR /app
COPY source-code /app
RUN compile-command

# Second stage: Creating an image with only the compiled output
FROM runtime-base-image
WORKDIR /app
COPY --from=compiler /app/compiled-binary /app/
CMD ["./compiled-binary"]

У цьому прикладі перша стадія використовує compiler-base-image для компіляції вихідного коду та створює компільований бінарний файл. Друга стадія використовує runtime-base-image та копіює лише необхідний бінарний файл з першої стадії для створення кінцевого образу. Це зменшує розмір кінцевого образу.

dockerignore

.dockerignore - це текстовий файл, який вказує Docker, які файли і директорії необхідно ігнорувати під час створення образу. Це дозволяє зменшити обсяг контексту, який відправляється до Docker демона під час збірки образу, тим самим прискорюючи процес збірки та зменшуючи розмір образу.

.dockerignore подібний до .gitignore в системі контролю версій Git і визначає, які файли та директорії повинні бути виключені з контексту збірки образу.

Приклад dockerignore файлу

*.tmp  # Ignore temporary files
config.ini  # Ignore configuration files
build/  # Ignore directories with build artifacts
logs/*  # Ignore all files in the logs directory

Docker Daemon

Docker-демон (dockerd) - це фоновий процес в операційній системі, який обробляє запити Docker API і керує об'єктами Docker: образами, контейнерами, мережами та томами.

Docker Client

Docker-клієнт - це інструмент командного рядка (Comand Line Interface — CLI), через який користувач взаємодіє з демоном.

Коли використовуєтться команда docker run, то Docker-клієнт відправляє команду dockerd. Аналогічна історія із іншими командами docker <команда>.

Docker Hub

Docker Hub - це відкритий Docker реєстр, тобто сховище всіх доступних Docker-образів. Дозволяє користувачам завантажувати (push) та скачувати (pull) образи. Воно необхідне для організації, розподілу та версіонування Docker-образів у різних середовищах розробки.

При необхідності можна розгортати свої приватні Docker реєстри, розміщувати власні реєстри Docker і використовувати їх для витягування образів.

Основні команди для роботи з Docker

Створення та Робота з Контейнерами

  • docker run <ім'я_образу>: Створює новий контейнер на основі вказаного образу та запускає його.
  • docker start <ім'я_контейнера>: Запускає зупинений контейнер.
  • docker stop <ім'я_контейнера>: Зупиняє працюючий контейнер.
  • docker restart <ім'я_контейнера>: Перезапускає контейнер.
  • docker rm <ім'я_контейнера>: Видаляє контейнер.

Робота з Образами

  • docker build -t <ім'я_образу> .: Збирає Docker образ із поточної директорії та присвоює йому ім'я.
  • docker pull <ім'я_образу>: Завантажує Docker образ із реєстру.
  • docker push <ім'я_образу>: Відсилає Docker образ до реєстру для зберігання та подібного використання іншими користувачами.
  • docker rmi <ім'я_образу>: Видаляє Docker образ.

Системні Команди

  • docker ps: Показує список запущених контейнерів.
  • docker images: Показує список доступних образів.
  • docker volume ls: Показує список томів (вузлів даних).
  • docker network ls: Показує список мереж, створених Docker.
  • docker info: Показує інформацію про систему Docker.

docker-compose

Docker Compose - це інструмент визначення та запуску багатоконтейнерних додатків з використанням Docker. Він дозволяє визначити конфігурацію програми у YAML-форматі, у файлі docker-compose.yml, включаючи контейнери, мережі, об'єкти образів та інші ресурси, та запустити всі контейнери, необхідні для роботи програми, однією командою. Це спрощує розгортання та керування складними додатками, що складаються з декількох компонентів.

Docker Compose використовується для розгортання, наприклад, веб-сервера, бази даних та інших програм. Він дозволяє визначити конфігурацію кожного сервісу окремо, включаючи образ, порти, змінні оточення та інші параметри та зв'язати їх між собою, замість запуску та керування кожним контейнером окремо.

Для використання Docker Compose необхідно визначити конфігурацію програми у файлі docker-compose.yml, який містить опис кожного сервісу та його залежностей. Потім можна використовувати команду docker-compose up для запуску всіх контейнерів, необхідних для роботи програми.

Приклад docker-compose.yml

version: '3'  # Docker Compose version

services:
  web:  # Service name for the web application
    image: flask-app:latest  # Using a custom Docker image for the Flask application
    ports:
      - "5000:5000"  # Mapping port 5000 from the container to the host
    depends_on:
      - db  # Indicating that this service depends on the "db" service

  db:  # Service name for the PostgreSQL database
    image: postgres:latest  # Using the official Docker image for PostgreSQL
    environment:
      POSTGRES_PASSWORD: examplepassword  # Password for accessing the database
      POSTGRES_DB: exampledb  # Database name

Основні команди для роботи з docker-compose

  • docker-compose up - Запускає контейнери згідно з файлом docker-compose.yml.
  • docker-compose down - Зупиняє та видаляє всі контейнери, мережі та томи, створені docker-compose up.
  • docker-compose ps - Показує статус контейнерів, вказаних у docker-compose.yml.
  • docker-compose build - Будує або перебудовує сервіси з файлу docker-compose.yml.
  • docker-compose logs - Виводить логи сервісів, вказаних у docker-compose.yml.
  • docker-compose exec <service_name> <command> - Виконує команду в сервісі, вказаному у docker-compose.yml.
  • docker-compose restart <service_name> - Перезапускає конкретний сервіс, вказаний у docker-compose.yml.
  • docker-compose pause - Призупиняє виконання команд для всіх сервісів у docker-compose.yml.
  • docker-compose unpause - Відновлює виконання команд для всіх призупинених сервісів у docker-compose.yml.
  • docker-compose config - Перевіряє конфігураційний файл docker-compose.yml на коректність та виводить його зміст.