Логотип Sharp & логотип Docker & Canvas
У цій статті я покажу, як використовувати пакети sharp та node-canvas для генерації зображень всередині контейнера Docker.
Будь ласка, перегляньте супутній репозиторій на GitHub (посилання тут) для повністю працюючого прикладу проекту. Почнемо!
TL;DR
Нижче наведено Dockerfile, використаний у цьому проекті:
УВАГА: У цьому проекті я використовую TypeScript, тому для запуску потрібно використовувати команду npm run build.
FROM node:20-alpine
RUN apk add
librsvg-dev \
pixman-dev \
freetype-dev \
fontconfig \
ttf-dejavu \
ttf-freefont
WORKDIR /app
COPY package*.json ./
RUN npm install --build-from-source
COPY . .
RUN npm run build
CMD ["node", "dist/app.js"]
Запуск проекту
Нещодавно я хотів створити сервер, який генеруватиме зображення за допомогою npm пакетів sharp та node-canvas. Однак я стикнувся з труднощами під час контейнеризації проекту з різних причин.
Нижче наведено огляд прикладу проекту (посилання тут) та інструкції, як ви можете запустити його самостійно!
Сервіс для створення зображень
Спочатку ми коротко розглянемо функцію, що використовується для генерації та, за бажанням, збереження зображення. Вона використовує комбінацію пакетів sharp та node-canvas.
УВАГА: функцію createImage() можна знайти у файлі src/services/image.service.ts.
import { createCanvas } from "canvas";
import path from "path";
import sharp from "sharp";
import fs from "fs";
const WIDTH = 1080;
const HEIGHT = 1080;
const FONT_LARGE = "bold 88px Arial";
const FONT_MEDIUM = "semi-bold 68px Arial";
const BACKGROUND_COLOR = "black";
const TEXT_COLOR = "white";
/**
* Функція для створення зображення
* @param title - заголовок зображення
* @param subtitle - підзаголовок зображення
* @param options {
* @param create_file - булеве значення, яке визначає, чи потрібно створювати файл;
* @param file_name - ім'я файлу, що буде створене;
* }
*/
export const createImage = async (
title: string,
subtitle: string,
options?: {
file_name?: string;
create_file?: boolean;
},
) => {
const canvas = createCanvas(WIDTH, HEIGHT);
const ctx = canvas.getContext("2d");
// --- ФОН ---
ctx.fillStyle = BACKGROUND_COLOR;
ctx.fillRect(0, 0, WIDTH, HEIGHT);
// --- ТЕКСТ ЗАГОЛОВКА ---
const TITLE_Y_POSITION = 200;
ctx.fillStyle = TEXT_COLOR;
ctx.textAlign = "center";
ctx.font = FONT_LARGE;
ctx.fillText(title, WIDTH / 2, TITLE_Y_POSITION);
// --- ТЕКСТ ПІДЗАГОЛОВКА ---
const SUBTITLE_Y_POSITION = 350;
ctx.font = FONT_MEDIUM;
ctx.fillText(subtitle, WIDTH / 2, SUBTITLE_Y_POSITION);
// --- КОНВЕРТАЦІЯ У PNG ---
const FINAL_IMAGE_BUFFER = canvas.toBuffer("image/png");
const CONNECTIONS_IMAGE = await sharp(FINAL_IMAGE_BUFFER).toBuffer();
// --- ЗБЕРЕЖЕННЯ У ФАЙЛ ---
if (options?.create_file) {
const OUTPUT_DIR = path.join(__dirname, "../output");
if (!fs.existsSync(OUTPUT_DIR)) {
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
}
const OUTPUT_PATH = path.join(
OUTPUT_DIR,
options?.file_name ?? "test-image.png",
);
fs.writeFileSync(OUTPUT_PATH, CONNECTIONS_IMAGE);
console.log(`Зображення збережене за адресою ${OUTPUT_PATH}`);
}
return CONNECTIONS_IMAGE;
};
Наведений код показує, як працює функція:
- Створює полотно (1080 x 1080).
- Малює заголовок та підзаголовок на зображенні.
- Конвертує в PNG за допомогою
canvas.toBuffer("image/png")
. - За бажанням зберігає зображення в папку /output.
5.
Повертає Image Buffer для подальшої обробки без збереження на диску.
Запуск та тестування проекту локально (без Docker)
Будь ласка, слідуйте інструкціям в README на GitHub, щоб клонувати репозиторій та встановити залежності для проекту локально!
Далі, запустіть команду npm run dev
Це створить зображення в папці /output
Зображення, створене за допомогою коду
Запуск та тестування проекту локально в Docker
Будь ласка, слідуйте інструкціям в README на GitHub, щоб клонувати репозиторій та встановити залежності для проекту локально!
Створіть Docker-образ:
docker build -t node-sharp-canvas-image .
Запустіть Docker-образ у контейнері:
УВАГА: Це створить ID контейнера, який буде використовуватись пізніше.
docker run -d --name node-sharp-canvas-container node-sharp-canvas-image
Перевірка Docker-контейнера:
Тепер, коли контейнер працює, ми можемо перевірити папку /output
, щоб переконатися, що зображення було створене.
docker exec ls /app/src/output
# --- Виведення: ---
# .gitkeep
# image-created-using-sharp-and-canvas.png
Висновки
Ось і все! Тепер ви можете генерувати зображення в середовищі Node.js всередині Docker-контейнера!
Підтримка
Якщо це було корисно, будь ласка, розгляньте можливість підтримати мене тут.
Перекладено з: Crafting Images in the Cloud: Using Sharp and Node-Canvas Inside a Docker Container