Контейнеризация
Контейнеризация — распространённая техника разработки и развёртывания ПО, упаковывающая приложение с зависимостями в единый лёгкий контейнер. Контейнер можно развернуть на любой машине с поддержкой соответствующей технологии, например Docker , Kubernetes или Nanocl , без отдельной установки приложения и зависимостей.
Контейнеризация повышает переносимость и масштабируемость, упрощает развёртывание и управление. Изоляция приложения и зависимостей в контейнере также повышает безопасность и снижает вероятность конфликтов между компонентами ПО.
Контейнеризация стала важным инструментом современной разработки и развёртывания. Разработчикам, системным администраторам и ИТ-руководителям знание её основ помогает повышать эффективность и надёжность приложений.
Структура проекта
Перед началом установите Docker .
Способов установки несколько; здесь мы их не рассматриваем.
Если вы используете монорепозиторий, разместите файлы на GitHub или другой платформе хранения кода.
В руководстве используется следующая структура:
my_project/
├── my-app/ # Frontend app
└── my-api/ # APIФайлы этого руководства находятся на GitHub .
Если вы уже умеете собирать образы контейнеров, пропустите этот раздел и клонируйте репозиторий для следующих шагов.
Создайте основной каталог проекта и перейдите в него:
mkdir my_project
cd my_projectТакая структура разделяет интерфейс и серверную часть, позволяя разрабатывать их независимо. Это упрощает разработку, тестирование и развёртывание, повышает масштабируемость и удобство сопровождения приложения.
Создадим структуру проекта и начнём работу над интерфейсом и серверной частью!
Настройка простого интерфейса
Начнём с простого шаблона create-react-app .
Однако для React мы рекомендуем Next.js или Vite .
Если вы используете другой фреймворк, соберите интерфейс в каталог статических файлов.
Next.js и Vite упрощают разработку интерфейса, повышают производительность и масштабируемость. Рендеринг на сервере, генерация статических сайтов и другие возможности облегчают создание качественных современных веб-приложений.
Настроим простой интерфейс приложения и начнём сборку!
Создание проекта
Создайте каталог приложения интерфейса my-app следующими командами:
npx create-react-app my-app
cd my-app
npm run buildПростое приложение будет собрано в каталог my-app/build.
create-react-app выведет сообщение:
The build folder is ready to be deployed.
You may serve it with a static server:
npm install -g serve
serve -s buildОбслуживать интерфейс сервером Node, например serve, не рекомендуется из-за низкой производительности.
Вместо этого используем контейнер nginx.
Создание образа контейнера
Перейдите в my-app и создайте файл Dockerfile со следующим содержимым:
# stage 1 - Build our application
# From the latest nodejs lts version
FROM node:18.14.2-alpine AS BUILDER
# Create our app folder
RUN mkdir /app
# Set is as cwd
WORKDIR /app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+) doing this will cache this action untill package.json or package-lock.json is modified
COPY --chown=node package*.json ./
# Install dependencies
RUN npm install
# Bundle app source code
COPY --chown=node . .
RUN npm run build
# stage 2 - Create app image
# From latest nginx version on alpine to have a small image
FROM nginx:1.23.3-alpine
# Copy our build directory
COPY --from=BUILDER /app/build /app
# Copy our default nginx config
COPY ./server.nginx /etc/nginx/conf.d/default.confПеред сборкой образа создайте my-app/server.nginx со следующим содержимым:
server {
listen 80;
listen [::]:80;
## Auto index file in /app
autoindex on;
root /app;
try_files $uri/index.html $uri.html $uri/ $uri =404;
error_page 404 /404.html;
## Enable gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types image/webp image/png text/html text/plain text/css text/xml text/javascript application/x-javascript application/javascript application/xml font/eot font/otf font/ttf;
## Disable gzip for internet explorer compatibility..
gzip_disable "MSIE [1-6]\.";
## Cache all static files
location ~* ^.+\.(?:css|cur|js|jpe?g|gif|htc|ico|png|html|xml|otf|ttf|eot|woff|woff2|svg)$ {
access_log off;
expires 30d;
add_header Cache-Control public;
## No need to bleed constant updates. Send the all shebang in one fell swoop.
tcp_nodelay off;
## Set the OS file cache.
open_file_cache max=3000 inactive=120s;
open_file_cache_valid 45s;
open_file_cache_min_uses 2;
open_file_cache_errors off;
}
}Эта конфигурация nginx обслуживает статические файлы интерфейса для всех обрабатываемых запросов.
Добавьте .dockerignore в my-app, чтобы исключить node_modules и build из сборки. Содержимое my-app/.dockerignore:
node_modules
buildЭто ускорит сборку.
Создав server.nginx и .dockerignore, соберите образ Docker:
docker build -t my-frontend:0.0.1 -f ./Dockerfile .Используются следующие команды и параметры Docker:
build: сборка образа.-t: тег образа, обычно image_name:version.my-frontend:0.0.1: тег образа в этом руководстве.-f: путь Dockerfile../Dockerfile: файл для сборки образа..: контекст сборки.
Проверка образа контейнера
Для проверки образа интерфейса выполните:
docker run -it --rm -p 8080:80 my-frontend:0.0.1Контейнер запустится с сопоставлением порта 8080 хоста порту 80 контейнера.
Откройте http://localhost:8080 в браузере, чтобы увидеть приложение React.
Вы увидите страницу приложения React, как на изображении:
Настройка простого API
Настроим простой проект Node.js с Express .
Создание проекта
Создайте каталог my-api:
mkdir my_project/my-api
cd my-api
npm init
npm install --save expressСоздайте точку входа API в ./main.js:
const express = require('express');
const PORT = process.env.PORT || 3000;
const HOST = process.env.HOST || '127.0.0.1';
const app = express();
app.get('/', (req, res) => {
res.json({ message: 'Hello World' });
});
app.listen(PORT, HOST, () => {
console.log(`Server running on port ${PORT}`);
});Проверим запуском:
node main.jsСоздание образа контейнера
Для простого API теперь можно создать образ контейнера.
Вот Dockerfile:
# From the latest nodejs lts version
FROM node:18.14.2-alpine
# Create our app folder
RUN mkdir /app
# Set is as cwd
WORKDIR /app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+) doing this will cache this action untill package.json or package-lock.json is modified
COPY --chown=node package*.json ./
# Install dependencies
RUN npm install
COPY . .
# Set host to 0.0.0.0 to bind on all container network interfaces
# This is usefull because we will create a docker network and bind the container to it
ENV HOST=0.0.0.0
# Set the port of the our app to 80 (default http port)
ENV PORT=80
# Expose the port so we can see it during inspection
EXPOSE 80
CMD ["node", "main.js"]Не забудьте .dockerignore:
node_modulesТеперь соберём образ:
docker build -t my-api:0.0.1 -f ./Dockerfile .Проверка образа контейнера
Проверим образ контейнера API:
docker run -it --name my-api --rm -p 8081:80 my-api:0.0.1Откройте http://localhost:8081 в браузере, чтобы увидеть JSON-сообщение:
Вы увидите наше JSON-сообщение:
Поздравляем! Приложения контейнеризированы.
Теперь развернём их на VPS!