Что такое Контейнеры в облачных вычислениях?
С тех пор, как в 2013 году на сцене появились Docker, контейнеры стали пользоваться огромной популярностью. Многие компании уже интегрировали контейнеры в свои рабочие процессы, поскольку они позволяют легко развертывать, распространять, управлять и масштабировать программное обеспечение.
В этой статье мы объясним, что такое контейнеры в облачных вычислениях. Мы расскажем о преимуществах использования контейнеров, о случаях их применения, сравним их с виртуальными машинами, рассмотрим Dockerи Kubernetes. И, наконец, мы научим вас кодировать, “докеризировать” и развернуть веб-приложение на Back4appContainers – абсолютно бесплатно!
Contents
- 1 Что такое Контейнер
- 2 Преимущества использования Контейнеров
- 3 Случаи Использования Контейнеров
- 4 Контейнеры и Виртуальные Машины
- 5 Docker и Kubernetes
- 6 Разработка Приложения с Использованием Архитектуры на Основе Контейнеров
- 7 Заключение
- 8 ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ
- 9 Что такое контейнер?
- 10 Каковы преимущества использования контейнеров?
- 11 В чем разница между контейнерами и виртуальными машинами?
- 12 В чем разница между Docker и Kubernetes?
- 13 Как разработать приложение с использованием контейнерной архитектуры?
Что такое Контейнер
Контейнер – это отдельный исполняемый пакет, который включает в себя все необходимое для запуска приложения: код, время выполнения, библиотеки, переменные окружения и файлы конфигурации. Самое замечательное в контейнерных приложениях то, что они могут работать где угодно – от вашей локальной среды разработки до публичных облаков и так далее. Контейнеры имеют небольшой размер, эффективны и обеспечивают эффективную изоляцию.
Преимущества использования Контейнеров
Использование контейнеров имеет ряд преимуществ. Давайте рассмотрим некоторые из них.
Эффективность
Контейнеры требуют меньше системных ресурсов, чем традиционные серверы или виртуальные машины, поскольку они не включают образ операционной системы. Это делает их чрезвычайно эффективными, небольшими по размеру (обычно измеряется в мегабайтах) и позволяет запускать значительное количество приложений на одном сервере.
Изоляция Приложения
Контейнеры изолируют приложение и его зависимости от хост-системы. В то же время они могут совместно использовать ядро ОС и системные ресурсы, такие как процессор, память, хранилище и сеть.
Портативность
Контейнерное программное обеспечение может работать и вести себя одинаково практически на любой машине, на которой установлен контейнерный движок. Это упрощает развертывание и перемещение приложений между различными средами и устраняет проблему, что это приложение “работает только на моей машине”.
Разделение Ответственности
Контейнеры позволяют разделить ответственность, распределяя задачи и обязанности между разработчиками и командами ИТ-операторов. Разработчики отвечают за создание и поддержку кода приложения и зависимостей, в то время как команды IT-операторов сосредоточены на развертывании и управлении контейнерами и базовой инфраструктурой.
Ускоренная Разработка Приложений
Контейнеризация упрощает разработку, тестирование, управление и распространение программного обеспечения. Контейнеры легко интегрируются с системами CI/CD, что позволяет значительно ускорить процесс разработки и доставки программного обеспечения.
Простое Масштабирование
Контейнерные приложения в сочетании с такой платформой для управления, как Kubernetes, могут легко масштабироваться по запросу. Это позволяет вашему бизнесу выдерживать высокие рабочие нагрузки при минимизации затрат.
Случаи Использования Контейнеров
Технология контейнеров имеет множество вариантов использования как для разработчиков, так и для команд IT-операторов.
Контейнерно-нативная Разработка
Контейнерно-нативная разработка – это подход к разработке программного обеспечения, использующий контейнеры в качестве основного строительного блока. При контейнерно-нативной разработке приложения упаковываются в контейнеры и запускаются в контейнерной среде. Этот подход к разработке дает вам все преимущества, которые могут предложить контейнеры.
Непрерывная Интеграция и Непрерывная Доставка (CI/CD)
В конвейере CI/CD контейнеры используются для упаковки приложений и запуска автоматизированных тестов, что позволяет тестировать и развертывать приложения последовательным и повторяемым образом. Контейнеры можно легко создавать, тестировать и развертывать в рамках конвейера CI/CD, что снижает риск ошибок и повышает общую эффективность процесса разработки программного обеспечения.
Микросервисы
Контейнеры можно использовать для разработки приложений, которые поддерживают микросервисную архитектуру. С помощью контейнеров вы можете легко разделить монолитное приложение на набор слабосвязанных, тонко детализированных сервисов, которые выполняются в разных контейнерах.
Среда Разработки
Контейнеры облегчают командам разработчиков быструю настройку среды разработки. Они обеспечивают согласованную среду разработки независимо от операционной системы и библиотек хоста.
Пакетные Процессы
Пакетные процессы можно легко контейнеризировать и развернуть в облаке. Каждая задача упаковывается в отдельный контейнерный образ и выполняется как отдельный контейнерный экземпляр. Это позволяет эффективно использовать ресурсы, поскольку каждая задача выполняется в своем собственном окружении и не мешает другим задачам.
Контейнеры и Виртуальные Машины
Контейнеры и виртуальные машины – это два разных подхода к виртуализации. Хотя они имеют некоторые сходства, они совершенно разные.
Виртуальные машины (ВМ) – это абстракция физического оборудования. Они позволяют превратить один сервер в несколько серверов. Каждая из ВМ имеет свою собственную операционную систему и обычно управляется гипервизором. ВМ подходят для запуска нескольких приложений (на одном сервере), монолитных приложений и приложений, требующих высокой степени изоляции и безопасности. Их недостатком является то, что они занимают много места и могут загружаться довольно медленно.
С другой стороны, контейнеры виртуализируются на уровне операционной системы. Они занимают меньше места, поскольку используют одно и то же ядро Linux, более эффективны, быстрее загружаются, обладают высокой масштабируемостью и могут работать с большим количеством приложений. Контейнеры управляются движком Container Engine. Их основное применение в отличие от виртуальных машин – это микросервисы и приложения, которые должны быть переносимыми, легкими и масштабируемыми.
Также можно комбинировать контейнеры и виртуальные машины, чтобы получить преимущества обоих.
Docker и Kubernetes
Два самых популярных инструмента для работы с контейнерами – это Docker и Kubernetes. Давайте объясним, как они работают, и рассмотрим их различия.
Docker – это проект с открытым исходным кодом на базе Linux, который используется для автоматизации развертывания и управления приложениями в легких контейнерах. Это позволяет контейнеризированным приложениям эффективно работать в различных средах. В наши дни Docker можно найти практически везде – от Linux-машин до крупных облачных провайдеров и так далее.
Наиболее популярными альтернативами Docker являются Podman, LXD и containerd.
Kubernetes (K8s) – это система управления контейнерами с открытым исходным кодом для автоматизации развертывания, масштабирования и управления контейнеризированными приложениями. С момента своего выпуска в 2014 году она стала стандартом индустрии для развертывания и эксплуатации контейнерных приложений в облачных средах. К преимуществам Kubernetes относятся масштабируемость, высокая доступность, автоматизация операций, абстракция инфраструктуры и мониторинг состояния.
К другим платформам оркестровки относятся: AWSECS, Nomad и RedHatOpenShift.
В чем же разница между Docker и Kubernetes? Проще говоря, Docker позволяет нам упаковывать и распространять приложения внутри контейнеров, а Kubernetes облегчает взаимодействие нескольких контейнеров друг с другом.
Разработка Приложения с Использованием Архитектуры на Основе Контейнеров
В этом разделе руководства мы создадим, “докеризуем” и развернем простой REST API с помощью контейнеров Back4appContainers.
Что такое Back4appContainers?
Back4app Containers – это бесплатная платформа с открытым исходным кодом для развертывания и масштабирования приложений на глобально распределенных контейнерах в облачной инфраструктуре.
Она позволяет вам сосредоточиться на своем программном обеспечении и быстрее развертывать его, не тратя силы на DevOps (интеграция разработки и эксплуатации программного обеспечения). Платформа тесно интегрирована с GitHub, имеет встроенную систему CI/CD и позволяет запустить ваше приложение за считанные минуты!
Почему стоит использовать Back4app Containers?
- Отлично интегрируется с GitHub
- Нулевое время простоя при развертывании
- Простота в использовании и наличие бесплатного уровня
- Отличная поддержка клиентов
Введение в Проект
Мы создадим простой REST API, который будет служить в качестве списка просмотра фильмов. Веб-приложение позволит выполнять основные CRUD-операции, такие как добавление фильма, удаление фильма и так далее. Для создания API мы будем использовать фреймворк Flask. Наконец, мы Докеризуем проект и продемонстрируем, как легко развернуть его на Back4app Containers.
Необходимые условия
- Опыт работы с фреймворком Flask
- Базовое понимание Docker и контейнеров
- Умение пользоваться Git и GitHub
Код Приложения
Следующие шаги потребуют, чтобы у вас был установлен Python. Если у вас еще не установлен Python, загрузите его.
Инициализация проекта
Сначала создайте специальный каталог для вашего приложения и перейдите в него:
$ mkdir flask-watchlist
$ cd flask-watchlist
Затем создайте новую виртуальную среду и активируйте ее:
$ python3 -m venv venv && source venv/bin/activate
Поскольку мы будем использовать Flask в качестве фреймворка, мы должны установить его:
$ (venv) pip install Flask==2.2.2
Создайте app.py со следующим содержимым:
# app.py
from flask import Flask
app = Flask(__name__)
app.config['JSON_SORT_KEYS'] = False
@app.route('/')
def index_view():
return {
'detail': 'Hello world!'
}
Этот код инициализирует Flask и создает простую конечную точку, которая возвращает сообщение.
Запустите сервер с помощью:
$ flask run
Перейдите по адресу http://localhost:5000/ и вы должны увидеть сообщение Helloworld!
.
База данных
Для базы данных мы будем использовать SQLite. SQLite – это встроенная, бессерверная система управления реляционными базами данных. Чтобы упростить работу с базой данных, мы установим Flask-SQLAlchemy — расширение для Flask, которое добавит поддержку SQLAlchemy для вашего приложения.
Установите его, выполнив следующие действия:
$ (venv) pip install Flask-SQLAlchemy==3.0.3
Далее перейдите в верхнюю часть файла app.py и измените его следующим образом, чтобы инициализировать базу данных:
# app.py
db = SQLAlchemy()
app = Flask(__name__)
app.config['JSON_SORT_KEYS'] = False
app.config['SECRET_KEY'] = '5b3cd5b80eb8b217c20fb37074ff4a33'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///default.db"
db.init_app(app)
Не забудьте про импорт:
from flask_sqlalchemy import SQLAlchemy
Далее, давайте определим наши модели баз данных.
Поскольку мы создаем простое приложение для просмотра списков фильмов, нам понадобится только одна модель. Определим модель Movie
следующим образом:
# app.py
class Movie(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(128), nullable=False)
release_date = db.Column(db.Date(), nullable=False)
is_watched = db.Column(db.Boolean, default=False)
watched_at = db.Column(db.DateTime, default=None, nullable=True)
def as_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
def __repr__(self):
return '<Movie %r>' % self.title
Для инициализации и заполнения нашей базы данных мы создадим простой скрипт на Python. Перейдите в корень вашего проекта и создайте новый файл init_db.py со следующим содержимым:
# init_db.py
from datetime import date
from app import db, app
from app import Movie
with app.app_context():
db.create_all()
if Movie.query.count() == 0:
movies = [
Movie(title='Fight Club', release_date=date(1999, 9, 15)),
Movie(title='The Matrix', release_date=date(1999, 3, 31)),
Movie(title='Donnie Darko', release_date=date(2001, 1, 19)),
Movie(title='Inception', release_date=date(2010, 7, 16)),
]
for movie in movies:
db.session.add(movie)
db.session.commit()
Последнее, что нам нужно сделать, это запустить скрипт:
$ (venv) python init_db.py
Это создаст базу данных, таблицы базы данных и заполнит их. Файл базы данных будет помещен в папку экземпляра.
Конечные точки API
Наше веб-приложение будет иметь следующие конечные точки:
/
возвращает основную информацию об API/api/
возвращает список фильмов/api/create/
добавляет новый фильм в список просмотра/api/<movie_id>/
возвращает подробную информацию о конкретном фильме/api/watch/<movie_id>/
отмечает фильм как просмотренный
Далее определите конечные точки в нижней части app.py:
# app.py
@app.route('/')
def index_view():
return {
'name': 'flask-watchlist',
'description': 'a simple app for tracking the movies you want to watch',
'version': 1.1,
}
@app.route('/api/')
def list_view():
json = [movie.as_dict() for movie in Movie.query.all()]
return jsonify(json)
@app.route('/api/<int:movie_id>/', methods=['GET', 'DELETE'])
def detail_view(movie_id):
movie = db.get_or_404(Movie, movie_id)
if request.method == 'DELETE':
db.session.delete(movie)
db.session.commit()
return {
'detail': 'Movie has been successfully deleted.'
}
else:
return movie.as_dict()
@app.route('/api/create/', methods=['POST'])
def create_view():
title = request.form.get('title')
release_date = request.form.get('release_date', type=float)
if title is None or release_date is None:
return {
'detail': 'Please provide the title and release_date.'
}, 400
movie = Movie(title=title, release_date=datetime.fromtimestamp(release_date))
db.session.add(movie)
db.session.commit()
return movie.as_dict()
@app.route('/api/watch/<int:movie_id>/')
def watch_view(movie_id):
movie = db.get_or_404(Movie, movie_id)
if movie.is_watched:
return {
'detail': 'Movie has already been watched.'
}, 400
movie.is_watched = True
movie.watched_at = datetime.now()
db.session.commit()
return movie.as_dict()
Не забудьте об импорте:
from datetime import datetime
from flask import request, jsonify
Отлично, теперь наше приложение более или менее готово. Запустите сервер разработки:
$ (venv) flask run
Проверьте, можете ли вы получить список фильмов:
$ (venv) curl http://localhost:5000/api/ | jq '.'
[
{
"id": 1,
"title": "Fight Club",
"release_date": "Wed, 15 Sep 1999 00:00:00 GMT",
"is_watched": false,
"watched_at": null
},
{
"id": 2,
"title": "The Matrix",
"release_date": "Wed, 31 Mar 1999 00:00:00 GMT",
"is_watched": false,
"watched_at": null
},
...
]
Gunicorn
Сервер разработки Flask не подходит для рабочей среды, поэтому давайте заменим его на Gunicorn. Gunicorn или “Green Unicorn” (“Зеленый единорог”) – это готовый к работе Python WSGI HTTP Server для Unix.
Установите его, выполнив:
$ (venv) pip install gunicorn==20.1.0
После установки пакета вы можете запустить свой WSGI-сервер следующим образом:
$ (venv) gunicorn -w 2 -b 0.0.0.0:5000 app:app
[INFO] Starting gunicorn 20.1.0
[INFO] Listening at: http://0.0.0.0:5000 (1)
[INFO] Using worker: sync
[INFO] Booting worker with pid: 7
[INFO] Booting worker with pid: 8
Имейте в виду, что эта команда работает только в операционных системах на базе UNIX.
Это запустит два рабочих Gunicorn и откроет доступ к вашему приложению в интернет. Для доступа к приложению откройте ваш любимый веб-браузер и перейдите по адресу http://localhost:5000.
requirements.txt
Последнее, что нам нужно сделать перед “докеризацией” нашего приложения, это создать файл requirements.txt. Файл requirements.txt используется для указания зависимостей проекта.
Проще всего создать его, выполнив следующие действия:
$ (venv) pip freeze > requirements.txt
Докеризация Приложения
Следующие шаги потребуют от вас установки Docker. Самый простой способ установить Docker – загрузить DockerDesktop.
Чтобы проверить, корректно ли установлен у вас Docker, выполните следующие действия:
$ docker --version
Docker version 20.10.22, build 3a2c30b
Dockerfile
Для докеризации нашего приложения мы будем использовать Dockerfile. Dockerfile – это обычный текстовый файл, который позволяет нам определить базовый образ, окружение, переменные среды, команды, сетевые настройки, тома и так далее.
Создайте Dockerfile в корне вашего проекта со следующим содержимым:
# syntax=docker/dockerfile:1.4
FROM --platform=$BUILDPLATFORM python:3.10-alpine
# set the working directory
WORKDIR /app
# set environmental variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install the requirements
COPY requirements.txt /app
RUN --mount=type=cache,target=/root/.cache/pip \
pip3 install -r requirements.txt
# copy the code to the container
COPY . .
# initialize the database (create DB, tables, populate)
RUN python init_db.py
# expose
EXPOSE 5000/tcp
# entrypoint command
CMD ["gunicorn", "-w", "2", "-b", "0.0.0.0:5000", "app:app"]
- В качестве базового образа мы использовали
python:3.10-alpine
. - Установили
PYTHONDONTWRITEBYTECODE
в1
, что заставляет Python больше не записывать файлы .pyc на диск. - Установили
PYTHONUNBUFFERED
в1
, чтобы гарантировать, что выходные потоки Python будут отправляться прямо в терминал.
Для получения дополнительной информации о написании Docker-файлов ознакомьтесь со справочником по Dockerfile.
.dockerignore
Прежде чем Docker соберет образ, он ищет файл .dockerignore. Файл .dockerignore позволяет нам определить, какие файлы мы не хотим включать в образ. Это может значительно уменьшить размер образа. Он работает аналогично файлу .gitignore.
Создайте файл .dockerignore в корне проекта со следующим содержимым:
# .dockerignore
.git/
instance/
__pycache__/
.idea/
Не забудьте добавить все дополнительные каталоги или файлы, которые вы хотите исключить.
Сборка и запуск образа
Двигаясь дальше, давайте соберем и промаркируем наш образ Docker.
$ docker build -t flask-watchlist:1.0 .
[+] Building 11.1s (15/15) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 32B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 34B 0.0s
=> resolve image config for docker.io/docker/dockerfile:1.4 0.5s
=> CACHED docker-image://docker.io/docker/dockerfile:1.4@sha256:9ba7531a0dbc 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> [internal] load .dockerignore 0.0s
=> [internal] load metadata for docker.io/library/python:3.10-alpine 0.5s
=> [stage-0 1/6] FROM docker.io/library/python:3.10-alpine@sha256:da5ab5e911253dfb 0.0s
=> [internal] load build context 0.3s
=> => transferring context: 182.45kB 0.2s
=> CACHED [stage-0 2/6] WORKDIR /app 0.0s
=> [stage-0 3/6] COPY requirements.txt /app 0.0s
=> [stage-0 4/6] RUN --mount=type=cache,target=/root/.cache/pip
pip3 install -r requirements.txt 7.2s
=> [stage-0 5/6] COPY . . 0.3s
=> [stage-0 6/6] RUN python init_db.py 1.5s
=> exporting to image 0.3s
=> => exporting layers 0.3s
=> => writing image sha256:2671ccb7546a0594807c721a0600a 0.0s
=> => naming to docker.io/library/flask-watchlist:1.0
Если вы сформируете список образов, вы увидите наш новый образ:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
flask-watchlist 1.0 7bce66230eb1 8 hours ago 110MB
Наконец, используйте образ для запуска нового контейнера Docker:
$ docker run -it -p 5000:5000 flask-watchlist:1.0
[2023-02-02 20:08:57 +0000] [1] [INFO] Starting gunicorn 20.1.0
[2023-02-02 20:08:57 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)
[2023-02-02 20:08:57 +0000] [1] [INFO] Using worker: sync
[2023-02-02 20:08:57 +0000] [7] [INFO] Booting worker with pid: 7
[2023-02-02 20:08:57 +0000] [8] [INFO] Booting worker with pid: 8
Вы можете использовать
-d
для запуска контейнера Docker в отделенном режиме. Это означает, что контейнер работает в фоновом режиме вашего терминала и не получает входные данные и не отображает выходные.
Отлично, ваше приложение теперь работает в контейнере! Перейдите по адресу http://localhost:5000 и вы должны получить следующий ответ:
{
"name": "flask-watchlist",
"description": "a simple app for tracking the movies you want to watch",
"version": 1
}
GitHub
Чтобы развернуть приложение на Back4app Containers, вам нужно загрузить исходный код в репозиторий GitHub. Создайте новый репозиторий на GitHub, добавьте remote, добавьте .gitignore и разместите ваш код. Когда ваш код будет размещен на GitHub, переходите к следующему шагу.
Развертывание Приложения на Back4appContainers
Следующие шаги потребуют от вас наличия учетной записи Back4app. Если он у вас уже есть, войдите, в противном случае перейдите к регистрации бесплатного аккаунта.
Для работы с Back4app нам сначала нужно создать приложение. Когда вы войдете в свою панель управления, вы увидите список ваших приложений. Нажмите на “Build a new app” (“Создать новое приложение”), чтобы создать новое приложение.
Далее выберите “Containers as a Service” (“Контейнеры как сервис”).
Если вы еще этого не сделали, подключите свой GitHub к Back4app и импортируйте репозитории, которые вы хотите развернуть. После подключения GitHub ваши репозитории будут отображены в таблице.
Выберите репозиторий, который вы хотите развернуть, нажав на кнопку “Select” (“Выбрать”).
Далее Back4app попросит вас настроить программную среду. Выберите имя приложения, я выбрал flask-watchlist
. Если хотите вы можете оставить все остальное по умолчанию.
Наконец, нажмите “Create App” (“Создать приложение”), чтобы автоматически создать приложение и развернуть его.
После этого вы будете перенаправлены во вкладку с более детальной информацией о приложении, где сможете увидеть журналы развертывания.
Подождите несколько минут, пока приложение развернется, и на этом все! Ваше приложение теперь работает на Back4app Containers. Чтобы увидеть ваше приложение в действии, нажмите на зеленый URL, показанный слева.
Заключение
В этой статье мы объяснили, что такое контейнеры, их преимущества и показали, как вы можете внедрить контейнеры в свой рабочий процесс. Теперь вы должны быть в состоянии создать свой собственный простой REST API, “докеризировать” его и развернуть в Back4appContainers.
Получите готовый исходный код из репозитория GitHub.
Дальнейшие Действия
- Не стоит хранить базу данных в образе. В настоящее время каждое переразвертывание будет сбрасывать базу данных. Рассмотрите возможность перехода на управляемый экземпляр PostgreSQL или MySQL.
- Узнайте о многоступенчатых сборках для оптимизации Docker-файлов.
- Прочитайте статью Развертывание Docker-контейнеров для получения пошагового руководства.
ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ
Что такое контейнер?
Контейнер – это отдельный исполняемый пакет, который включает в себя все необходимое для запуска приложения. Контейнер включает в себя код, время выполнения, библиотеки, переменные окружения и файлы конфигурации.
Каковы преимущества использования контейнеров?
– Эффективность
– Изоляция приложений
– Разделение ответственности
– Ускоренная разработка приложений
В чем разница между контейнерами и виртуальными машинами?
Виртуальные машины – это абстракция физического оборудования, в то время как контейнеры виртуализируются на уровне операционной системы. ВМ обеспечивают большую изоляцию и безопасность, в то время как контейнеры не занимают много места, эффективны и масштабируемы.
В чем разница между Docker и Kubernetes?
Docker позволяет упаковывать и распространять приложения внутри контейнеров, а Kubernetes упрощает совместную работу множества контейнеров.
Как разработать приложение с использованием контейнерной архитектуры?
1. Выберите язык программирования и напишите свое приложение.
2. Выполните “докеризацию” приложения с помощью Dockerfile или Docker Compose.
3. Создайте образ Docker и протестируйте его локально.
4. Выберите CaaS, например Back4app Containers, и разместите на нем свой код.
Подождите, пока сервис развернется, и на этом все!