Пошук уроків, статей та іншого контенту
Розглянемо призначення Docker, проблему узгодження середовищ і переваги контейнеризації для розробки.
Під час розробки застосунок працює не сам по собі. Йому потрібні:
операційна система;
певна версія мови програмування;
бібліотеки та їхні версії;
системні залежності;
змінні середовища;
налаштування мережі або бази даних.
Наприклад, застосунок може працювати на комп’ютері розробника, але не запускатися на сервері. Причина часто описується фразою:
«У мене все працює».
Можливі причини проблеми:
на комп’ютерах встановлені різні версії Node.js, Python або іншої мови;
відрізняються версії бібліотек;
відсутні системні пакети;
різні налаштування операційної системи;
розробник забув описати частину залежностей;
сервер має іншу файлову структуру або змінні середовища.
Якщо налаштовувати кожне середовище вручну, це займає час і часто призводить до помилок.
Docker — це платформа для створення, запуску та поширення контейнерів.
Контейнер — це ізольоване середовище, у якому застосунок запускається разом із потрібними файлами, бібліотеками та налаштуваннями.
Замість того щоб передавати іншому розробнику довгу інструкцію:
встановіть певну версію Node.js;
встановіть такі-то системні пакети;
налаштуйте змінні середовища;
виконайте ще кілька команд;
можна описати середовище в конфігураційному файлі Docker. Інший розробник створить контейнер за цим описом і запустить застосунок у такому самому середовищі.
Docker не пакує весь комп’ютер у буквальному сенсі. Контейнер використовує ядро операційної системи хоста, але має ізольовані процеси, файлову систему та мережеве оточення.
Образ (image) — це підготовлений шаблон для створення контейнера.
Образ може містити:
базову операційну систему або її частину;
середовище виконання, наприклад Node.js;
файли застосунку;
встановлені залежності;
команду запуску.
Образ є незмінним шаблоном. На його основі можна створити один або кілька контейнерів.
Контейнер — це запущений екземпляр образу.
Один і той самий образ можна використовувати для запуску кількох однакових контейнерів. Наприклад, з одного образу можна запустити окремі контейнери для розробки, тестування та іншої частини системи.
Dockerfile — це текстовий файл з інструкціями для створення образу.
У ньому описують:
базовий образ;
копіювання файлів;
встановлення залежностей;
порт застосунку;
команду запуску.
Docker Engine — це програмне забезпечення, яке створює та запускає контейнери. Користувач взаємодіє з ним через команду docker.
Створімо мінімальний застосунок, який повертає текст у відповідь на HTTP-запит.
server.jsconst http = require("http");
const port = process.env.PORT || 3000;
const server = http.createServer((request, response) => {
response.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
response.end("Застосунок працює в Docker-контейнері!");
});
server.listen(port, "0.0.0.0", () => {
console.log(`Сервер запущено на порту ${port}`);
});Адреса 0.0.0.0 потрібна, щоб сервер був доступний не лише всередині контейнера, а й через опублікований порт хоста.
package.json{
"name": "docker-example",
"version": "1.0.0",
"private": true,
"scripts": {
"start": "node server.js"
}
}Цьому прикладу не потрібні зовнішні npm-залежності, але package.json показує, як зазвичай описують команду запуску застосунку.
Dockerfile# Використовуємо офіційний образ Node.js
FROM node:22-alpine
# Встановлюємо робочу директорію всередині контейнера
WORKDIR /app
# Спочатку копіюємо опис проєкту
COPY package*.json ./
# Встановлюємо залежності
RUN npm install
# Копіюємо файли застосунку
COPY . .
# Документуємо порт, який використовує застосунок
EXPOSE 3000
# Запускаємо застосунок
CMD ["npm", "start"]Тут використовується образ node:22-alpine. Він містить Node.js і мінімальне середовище на базі Alpine Linux.
У директорії, де розташовані Dockerfile, server.js і package.json, виконайте:
docker build -t docker-example .Команда складається з таких частин:
docker build — створити образ;
-t docker-example — надати образу ім’я;
. — використовувати поточну директорію як контекст збірки.
docker run --name docker-example-container -p 3000:3000 docker-exampleПараметр -p 3000:3000 пов’язує порти:
перший 3000 — порт на комп’ютері;
другий 3000 — порт усередині контейнера.
Після запуску застосунок буде доступний за адресою http://localhost:3000.
Щоб зупинити контейнер, натисніть Ctrl+C у терміналі, де він запущений.
Запустити контейнер у фоновому режимі можна з параметром -d:
docker run -d --name docker-example-container -p 3000:3000 docker-exampleПереглянути запущені контейнери:
docker psЗупинити контейнер за його іменем:
docker stop docker-example-containerВидалити зупинений контейнер:
docker rm docker-example-containerDocker дає змогу описати середовище застосунку у вигляді файлів і команд. Завдяки цьому:
усі розробники використовують однакову базову версію середовища;
залежності встановлюються однаковим способом;
процес запуску можна повторити на іншому комп’ютері;
новому учаснику команди простіше почати роботу;
тестове та робоче середовища можуть бути ближчими одне до одного;
налаштування середовища можна зберігати разом із кодом.
Важливо розділяти код застосунку та опис його середовища. Код може змінюватися часто, а Dockerfile фіксує правила, за якими це середовище створюється.
Контейнер містить визначену версію середовища та залежностей. Це зменшує кількість відмінностей між комп’ютерами розробників і сервером.
Застосунок у контейнері працює окремо від інших процесів. Різні контейнери можуть використовувати різні версії інструментів і не заважати один одному.
Наприклад, один проєкт може працювати з однією версією Node.js, а інший — з іншою.
Після створення образу контейнер можна запускати повторно без ручного налаштування всіх залежностей.
Опис у Dockerfile можна використати повторно на іншому комп’ютері або під час автоматичної збірки.
З одного образу можна запускати кілька однакових контейнерів. Це корисно, коли застосунок має обробляти більше запитів.
Docker-контейнер і віртуальна машина вирішують схожу проблему ізоляції, але працюють по-різному.
Віртуальна машина містить повну гостьову операційну систему. Через це вона зазвичай потребує більше дискового простору та пам’яті.
Контейнер використовує ядро операційної системи хоста й ізолює процеси застосунку. Тому контейнери зазвичай:
запускаються швидше;
займають менше ресурсів;
зручні для пакування та запуску застосунків.
Docker не є повною заміною віртуальним машинам у всіх сценаріях. На початковому етапі важливо запам’ятати головне: контейнер — це легке ізольоване середовище для запуску застосунку та його залежностей.
Docker не робить застосунок безпомилковим і не налаштовує всю інфраструктуру автоматично.
Зокрема:
помилки в коді залишаються;
неправильні залежності не виправляються самі;
дані контейнера можуть бути втрачені після його видалення, якщо не налаштувати окреме збереження;
секрети не варто безпосередньо записувати в Dockerfile;
сам Docker не замінює тестування.
Docker допомагає стандартизувати середовище, але якість застосунку все одно залежить від його коду та конфігурації.
Базовий цикл роботи з Docker виглядає так:
Створити або отримати Dockerfile.
Побудувати образ командою docker build.
Запустити контейнер командою docker run.
Перевірити роботу застосунку.
За потреби зупинити або видалити контейнер.
Після змін у Dockerfile або файлах застосунку знову побудувати образ.
Образ і контейнер — не одне й те саме:
образ — шаблон;
контейнер — запущений екземпляр цього шаблону.
Образ створюють під час docker build, а контейнер запускають під час docker run.
Зміни в запущеному контейнері не змінюють Dockerfile та початковий образ. Якщо потрібно зібрати нову версію застосунку, зазвичай слід змінити файли й повторно виконати docker build.
Якщо запустити контейнер без -p, застосунок може працювати всередині контейнера, але бути недоступним через localhost на комп’ютері.
docker run -p 3000:3000 docker-examplelocalhostСервер, який слухає тільки 127.0.0.1 усередині контейнера, може бути недоступним ззовні. Для простого контейнерного вебзастосунку сервер зазвичай має слухати 0.0.0.0.
Якщо змінено Dockerfile або файли, які копіюються під час збірки, старий контейнер не оновиться автоматично. Потрібно повторно створити образ:
docker build -t docker-example .Формат параметра:
-p ПОРТ_ХОСТА:ПОРТ_КОНТЕЙНЕРАНаприклад, -p 8080:3000 означає, що застосунок буде доступний на порту 8080 комп’ютера, хоча всередині контейнера він працює на порту 3000.
Docker — платформа для створення та запуску контейнерів.
Контейнер ізолює застосунок разом із його середовищем і залежностями.
Образ є шаблоном, а контейнер — запущеним екземпляром образу.
Dockerfile описує, як створити образ.
Контейнеризація зменшує відмінності між середовищами розробки, тестування та запуску.
Команда docker build створює образ.
Команда docker run запускає контейнер.
Параметр -p публікує порт контейнера на комп’ютері.
Docker не виправляє помилки застосунку, але робить його середовище більш передбачуваним і відтворюваним.