Контейнеризация приложений — удобный и гибкий способ быстрого развертывания приложений, будь то веб-серверы, СУБД, системы мониторинга и так далее. Также контейнеры активно используются при работе с микросервисными приложениями. Для этих целей идеально подходит Docker, который максимально упрощает работу с контейнерными приложениями. Впервые Docker был представлен в 2013 году и с тех пор активно поддерживается и используется. Сегодня мы рассмотрим шаги по созданию своих собственных образов Docker для трех приложений на разных языках программирования, а также запустим их.
Для работы с платформой Docker нам понадобится следующее:
Сервер или виртуальная машина с любым предустановленным дистрибутивом Linux. Рекомендуем выбрать один из следующих дистрибутивов: Ubuntu, Debian, CentOS, Fedora, RHEL, SLES. Именно они заявлены в качестве поддерживаемых — для них всегда выпускаются стабильные и актуальные версии Docker. Мы будем использовать Ubuntu 22.04.
Установленный Docker. Процесс установки Docker на Ubuntu 22.04 можно найти в нашей инструкции. Также можно воспользоваться готовым образом с предустановленным Docker, выбрав его при создании облачного сервера на вкладке «Маркетплейс».
В первую очередь нужно арендовать облачный сервер.
1) Переходим на страницу авторизации и входим в аккаунт при помощи логина или адреса электронной почты и пароля или при помощи Passkey, ВКонтакте, GitHub, Google.
2) После успешной авторизации отобразится панель управления текущего проекта. Переходим в раздел «Облачные серверы» и нажимаем «Создать» или «Добавить».
3) Выбираем операционную систему, которая будет установлена на сервер. В нашем случае нам необходима Ubuntu версии 22.04.
Также в этом же разделе можно выбрать уже готовый образ с Docker перейдя во вкладку «Маркетплейс»:
4) Выбираем регион, в котором будет находиться наш сервер. Выбирать рекомендуется тот регион, который ближе всего находится к вам физически. У каждого доступного региона справа вверху отображается ping, т.е. время, необходимое для передачи данных с вашего компьютера на сервер. Чем меньше указанное время, тем быстрее будет осуществляться передача данных.
5) Далее выбираем необходимую конфигурацию для сервера. Так как в данной статье будут рассмотрены только тестовые примеры по работе с образами Docker, то для конфигурации сервера можно выбрать минимальную доступную конфигурацию, включающую в себя одноядерный процессор, 1 ГБ оперативной памяти и 15 ГБ места на NVMe диске. В реальности вам необходимо выбирать именно ту конфигурацию, которая будет удовлетворять вашим потребностям при работе с контейнерными приложениями и их образами.
Стоит отметить, что сам Docker потребляет минимум ресурсов. Расчет необходимой конфигурации производится исходя из той нагрузки и конфигурации, которую будет использовать контейнер. Выбираем соответствующий тариф:
6) Далее необходимо решить, будет ли сервер доступен из внешний сети или же только из приватной (частной) сети. Если не уверены в настройках, оставьте эти параметры без изменений.
7) По желанию можно оформить дополнительные услуги, включая резервные копии и защиту от DDoS-атак (последняя доступна только в Санкт-Петербурге и Москве).
8) Также заранее можно загрузить SSH-ключ, чтобы не входить на сервер при помощи пароля.
9) Можно задать необходимое имя для сервера которое будет отображаться в панели управления, а также выбрать проект.
10) Для создания сервера необходимо нажать на кнопку «Заказать»:
Если на вашем аккаунте недостаточно средств, то будет выведено предупреждение о необходимости пополнить баланс. После оплаты и создания сервера откроется Дашборд сервера, где можно будет найти IP-адрес, логин и пароль для подключения.
vds
В основе концепции Docker лежит понятие образа. Под образом понимают шаблон, по сути представляющий собой исполняемый файл, из которого из которого можно запустить Docker-контейнер. Внутри образа находится все, что необходимо для запуска готового приложения: исходный код, конфигурационные файлы, сторонние программы, утилиты и библиотеки.
Архитектура образов основана на слоях. Каждый слой — это какое-либо действие, совершенное внутри образа, например, создание файлов и каталогов или установка программ. В качестве файловой системы для Docker-образов используется OverlayFS, которая основана на объединении нескольких точек монтирования в одну, благодаря чему создается единая структура каталогов.
Созданный образ Docker можно переносить между системами и использовать сразу в нескольких местах по аналогии с исполняемыми файлами .exe
для Windows-систем.
Рассмотрим, как создать образы для приложений Flask, Node.js и Go.
Для создания образов используется Dockerfile — текстовый файл без расширения? в котором указаны команды (инструкции) для создания образа контейнера. С инструкциями Dockerfile можно ознакомиться более подробно в официальной документации.
В качестве первого примера мы создадим и запустим Docker-образ, содержащий код на языке программирования Python с использованием фреймворка Flask, который используется для создания веб-приложений. В качестве приложения будет использоваться обычная HTML-страница, отображающая текущую дату.
Перед созданием приложения нам нужно установить пакетный менеджер pip, с помощью которого производится установка дополнительных Python зависимостей — пакетов, а также пакет python3-venv
для создания виртуальных окружений. При помощи виртуальных окружений можно работать с разными версиями пакетов, тем самым избегая конфликтов при работе с двумя или более версиями разных пакетов. Команда установки будет следующей:
apt -y install python3-pip python3-venv
1) Создадим и перейдем в директорию, в которой будут храниться файлы проекта:
mkdir dockerfile-flask && cd dockerfile-flask
2) Далее создаем новое виртуальное окружение с именем env
:
python -m venv env
После этого в корневой директории будет создана папка с именем env
, где хранятся конфигурационные файлы виртуального окружения:
3) Для начала работы с виртуальным окружением его необходимо активировать при помощи команды:
source env/bin/activate
После активации слева от строки приглашения будет отображаться слово (env)
, которое говорит нам о том, что мы находимся в виртуальном окружении. Теперь при установке пакетов с помощью пакетного менеджера pip
они будут устанавливаться на уровне виртуального окружения, не влияя на функционал системы.
4) Установим пакет flask
при помощи pip
:
pip install flask
Также необходимо отдельно установить пакет MarkupSafe
версии 2.1.5:
pip install MarkupSafe==2.1.5
5) Переходим к процессу создания нашего тестового приложения. Внутри директории создаем файл с именем app.py
, в котором будет храниться исходный код сервиса.
from flask import Flask
import datetime
app = Flask(__name__)
@app.route('/')
def display_current_date():
current_date = datetime.datetime.now().date()
return f"Current date is: {current_date}"
if __name__ == '__main__':
app.run(debug=True)
6) Протестируем наш сервис. Для этого запустим приложение на любом адресе и на 80 порту при помощи команды:
flask run --host=0.0.0.0 --port=80
Открываем приложение в браузере используя, IP-адрес сервера. Порт указывать не надо, так как используется 80 порт по умолчанию:
Приложение успешно работает — при открытии страницы отображается текущая дата.
8) Последним шагом необходимо сохранить все зависимости (в нашем случае это только один пакет flask
) в специальный текстовый файл под названием requirements.txt
, где перечислены все сторонние пакеты, используемые в проекте и установленные при помощи pip
. Для этого необходимо выполнить команду:
pip freeze > requirements.txt
Итоговая структура проекта изображена на скриншоте ниже:
Теперь можно переходить к созданию образа Docker.
7) Создаем Dockerfile со следующим содержимым:
FROM python:3.8-slim-buster
WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0", "--port=80"]
Разберем данный Dockerfile:
FROM python:3.8-slim-buster
На данном этапе задается базовый образ. В данном примере мы выбрали образ с Python версии 3.8, который в свою очередь основан на slim-версии дистрибутива Debian Buster. Slim-образы меньше по размеру, чем обычные образы (например, по сравнению с обычным Debian Buster).
WORKDIR /app
Команда для создания директории внутри образа. Является аналогом команды mkdir
в Linux-дистрибутивах. В данном примере файлы проекта будут сохранены внутри директории app
.
COPY requirements.txt requirements.txt
Команда COPY
копирует файлы внутрь образа. В нашем примере мы копируем файл requirements.txt
в образ, сохранив его с тем же именем.
RUN pip3 install -r requirements.txt
Команда RUN
запускает команду внутри образа. При помощи RUN можно создавать файлы и папки, устанавливать пакеты, запускать сторонние утилиты и т.д. Для работы нашего Flask-приложения нам необходимо установить сторонние пакеты, перечисленные в файле requirements.txt
, поэтому мы используем инструкцию RUN
, задав ей необходимую команду.
COPY . .
Как уже было упомянуто ранее, команда COPY
копирует файлы внутрь образа. Первая точка означает, что в образ будут скопированы рекурсивно все файлы из текущей директории, откуда запускается Dockerfile, в тот каталог, который был указан в команде WORKDIR
(вторая точка).
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0", "--port=80"]
Команда CMD
предназначена для указания команд и параметров приложения, которые будут использованы при запуске контейнера.
8) Также стоит упомянуть про использование файла .dockerignore
, где можно указать те файлы и папки, которые не будут скопированы в образ. Это может быть полезно, чтобы уменьшить итоговый размер образа.
В нашем случае у нас есть директория env
, которая не имеет отношения к запуску приложения, а также директория __pycache__
.
Исключим данные директории из итого образа. Для этого создадим файл .dockerignore
в корневой директории проекта и добавим необходимые файлы:
env
__pycache__
Обратите внимание, что файл .dockerignore
является скрытым — перед именем файла необходимо указать символ точки.
Итоговая структура проекта выглядит следующим образом:
10) После того как Dockerfile был создан, можно приступать к сборке образа. Для этого используется команда docker build
. При сборке образа необходимо использовать тег — уникальный идентификатор образа. В качестве имени можно задать имя приложения, а также указать версию. Например, запустим сборку образа, присвоив тег flask-app:01
. Точка в конце команды означает, что Dockerfile находится в текущей директории, из которой выполняется команда:
docker build -t flask-app:01 .
После завершения сборки будет создан Docker-образ:
docker images
11) Готовый образ можно запустить при помощи команды docker run
:
docker run -d -p 80:80 flask-app:01
Где:
-d
— запускает контейнер в режиме «демона», то есть в фоновом режиме. -p 80:80
— ключ -p
отвечает за проброс портов. По умолчанию доступ до контейнера из внешней сети отсутствует (доступ до контейнера можно получить только локально). Чтобы получить доступ до контейнера из сети интернет, необходимо пробросить порты. Сначала указывается порт, по которому будет доступен контейнер, далее указывается порт самого сервиса, который запущен в контейнере. flask-app:01
— имя образа и тег, который был задан на этапе сборки образа.Проверим что образ был успешно запущен:
docker ps
В столбце STATUS
должен отображаться статус Up
.
Чтобы получить доступ до нашего приложения, необходимо использовать IP-адрес сервера и ранее заданный порт (так как у нас был задан 80 порт, его можно не указывать):
Как можно увидеть на скриншоте выше приложение успешно открылось.
В качестве следующего примера создадим образ для приложения, которое написано на языке программирования JavaScript с использованием платформы Node.js. Приложение будет выводить на веб-странице фразу «This app was created using Node.js!».
Перед тем как приступить к работе с платформой Node.js, ее необходимо установить. Инструкция по установке Node.js в Ubuntu 22.04 приведена в нашей статье.
1) Создадим и перейдем в директорию, в которой будут храниться файлы проекта:
mkdir dockerfile-nodejs && cd dockerfile-nodejs
2) Инициализируем новый проект:
npm init --yes
3) Далее установим дополнительный пакет под названием Express для создания веб-приложений:
npm install express --save
4) Создаем файл с именем app.js
и используем следующий код для веб-приложения:
const express = require("express");
const app = express();
app.get("/", function(req, res) {
return res.send("This app was created using Node.js!");
});
app.listen(3000, '0.0.0.0', function(){
console.log('Listening on port 3000');
});
5) Убедимся, что приложение отрабатывает корректно. Для этого запускаем приложение при помощи команды:
node app.js
Далее открываем браузер и переходим по IP-адресу сервера, указав также порт приложения 3000:
Приложение успешно открывается.
6) Создаем Dockerfile со следующим содержимым:
FROM node:20
WORKDIR /app
COPY package.json /app
RUN npm install
COPY . /app
CMD ["node", "app.js"]
7) Как и при работе с Flask-приложением, у Node.js присутствуют файлы, которые не нужны для запуска самого приложения. В данном случае это директория node_modules
, где хранятся сторонние библиотеки, которые можно использовать в вашем проекте при необходимости. Создадим скрытый файл .dockerignore
в директории проекта со следующим содержимым:
**/node_modules/
8) Далее можно запускать сборку образа:
docker build -t nodejs-app:01 .
9) После того как процесс сборки образа будет завершен, можно запустить контейнер при помощи команды:
docker run -d -p80:3000 nodejs-app:01
В качестве порта приложения (источника) мы задали порт 3000, так как он был указан в коде приложения.
Для проверки работоспособности приложения перейдем в браузере по IP-адресу сервера и порту:
Приложение успешно работает.
В качестве еще одного языка программирования мы рассмотрим Go, который часто используется для создания как многочисленных сетевых утилит, так и для написания микросервисов. В качестве теста будем использовать простое приложение которые выводит фразу «Hello from GO!».
Для начала необходимо установить сам язык Go. Процесс установки Go на Ubuntu приведен в нашей инструкции.
1) Создадим и перейдем в директорию, в которой будут храниться файлы проекта:
mkdir dockerfile-go && cd dockerfile-go
2) Инициализируем новый модуль Go:
go mod init go-test-app
3) Создаем файл с именем main.go
и вставляем следующий код:
package main
import "fmt"
func main() {
fmt.Println("Hello from GO!")
}
Проверим, что приложение запускается корректно:
go run .
4) Переходим к созданию Dockerfile:
FROM golang:1.23-alpine
WORKDIR /app
COPY go.mod ./
RUN go mod download
COPY *.go ./
RUN go build -o /go-test
CMD [ "/go-test" ]
В Dockerfile были использованы директивы:
COPY go.mod ./
Копирует файл go.mod
внутрь образа, в котором перечислены зависимости проекта.
RUN go mod download
Скачивает зависимости, указанные в файле go.mod
.
COPY *.go ./
Копирует все остальные файлы, расширение которых заканчивается на .go
.
RUN go build -o /go-test
Запускает процесс компиляции.
5) Запускаем процесс сборки Docker-образа для нашего Go-приложения:
docker build -t go:01 .
6) Запустим созданный образ. Так как у нас простое приложение, которое выводит только одну фразу, ключ -d
для запуска не нужен:
docker run go:01
В выводе программы отобразилась фраза «Hello from GO!».
Разворачивайте приложения на VDS/VPS в Timeweb Cloud
В данной статье мы рассмотрели процесс создания своих собственных образов Docker для трех разных приложений на трех разных языках программирования. При помощи Docker можно легко «упаковать» любое приложение и также легко его развернуть.