Closed TiffApps closed 9 months ago
Okay nvm, I took a break, then started from scratch again and got it to work first try somehow...
Here is my Dockerfile and my code, since it seems many people struggled with that from what I found on Google:
FROM dart:stable AS dartbuild
WORKDIR /app
COPY pubspec.* ./
RUN dart pub get
COPY . .
RUN dart compile exe bin/server.dart -o bin/server
FROM debian:bullseye-slim
RUN apt-get update && apt-get install -y \
sqlite3 \
libsqlite3-dev \
chromium \
wget \
fonts-liberation \
libasound2 \
libatk-bridge2.0-0 \
libatspi2.0-0 \
libdrm2 \
libgbm1 \
libgtk-3-0 \
libnspr4 \
libnss3 \
libxcomposite1 \
libxdamage1 \
libxfixes3 \
libxrandr2 \
xdg-utils \
--no-install-recommends \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=dartbuild /runtime/ /
COPY --from=dartbuild /app/bin/server /app/bin/
COPY --from=dartbuild /app/assets /app/assets/
EXPOSE 8080
CMD ["/app/bin/server"]
Dart code:
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:intl/intl.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;
import 'package:puppeteer/puppeteer.dart';
Future<String?> imageToBase64(String imagePath) async {
final bytes = await File(imagePath).readAsBytes();
final base64String = base64Encode(bytes);
return 'data:image/png;base64,$base64String';
}
Future<String> generateRecordImageFromTemplate(
Record record, Map<String, Object?> infos) async {
Logger.root.level = Level.SEVERE;
final logger = Logger('HTML Generation');
final basePath = Platform.environment['BASE_PATH'] ?? '';
String updatedHtml = '';
try {
// Load the HTML template and fill it with the record data
final recordPath = 'assets/templates/record';
final templatePath = '$basePath/$recordPath/record_template.html';
final htmlTemplate = await File(templatePath).readAsString();
final backgroundImage =
(await imageToBase64('$basePath/${infos['image'].toString()}'))!;
// ...
updatedHtml = htmlTemplate
.replaceAll('{{top}}', infos['top'].toString())
.replaceAll('{{left}}', infos['left'].toString())
.replaceAll('{{size}}', infos['size'].toString())
.replaceAll('{{mirror}}', infos['mirror'].toString())
.replaceAll('{{index}}', infos['index'].toString())
.replaceAll('{{rotate}}', infos['rotation'].toString())
// Record infos
.replaceAll(
'{{value}}', NumberFormat('#,##0', 'en_US').format(record.value))
.replaceAll('{{type}}', record.type)
.replaceAll('{{background}}', backgroundImage)
.replaceAll('{{fontSize}}', record.player.length <= 13 ? '150' : '100');
} catch (e) {
logger.severe('Failed to load and fill the HTML file: $e');
rethrow;
}
late Browser browser;
late Uint8List bytes;
try {
// Open the HTML page and take the screenshot
browser = await puppeteer
.launch(executablePath: '/usr/bin/chromium', headless: true, args: [
'--no-sandbox',
'--disable-gpu',
]);
final page = await browser.newPage();
await page.setContent(updatedHtml, wait: Until.networkIdle);
bytes = await page.screenshot(omitBackground: true);
} catch (e) {
logger.severe('Failed to open the HTML page and take the screenshot: $e');
rethrow;
}
late String imagePath;
try {
// Ensure the directory exists then save the screenshot
final dir = '$basePath/shared/records/';
final name = '${record.id}-${record.type}-record.png';
imagePath = path.join(dir, name);
await Directory(dir).create(recursive: true);
await File(imagePath).writeAsBytes(bytes, mode: FileMode.writeOnly);
await browser.close();
Logger.root.level = Level.INFO;
} catch (e) {
logger.severe('Failed to save the screenshot and close the browser: $e');
rethrow;
}
return imagePath;
}
I hope it will help someone else!
Hi! I know that linux_arm64 isn't supported, because there is no official arm64-compatible Chromium release, but there are some on the EPEL repos. Knowing that, it should be possible to run it right?
For context, I'm trying to make a Dart image generator by loading an HTML template, filling all the infos inside, then throwing this to Puppeteer in headless mode so it can take a screenshot. It's running on an Oracle Cloud Instance (OCI) Ampere1 Flex (ARM64), with Oracle Linux 9.2 as image. Dart is version 3.2.2 (latest stable).
Here is what I tried with my Dockerfile:
As you can see, sqlite3 is a requirement for my project as well and it's not available on OL9's EPEL repo, so have to do like this for now. (I'm not very familiar with Docker, so this file might not appear optimal btw...)
However when I run my code, I get an
Exception: Not able to connect to Chrome DevTools
. I trieddocker exec -it <container> /bin/bash
to peek inside and run it manually but I got this:It took me 2 full days to get to this point, and as motivated as I am, I'm getting really worn out by the constant errors and hours of research that follow each of them, just to get new ones.
Hence my question: Is there any image to run Dart Puppeteer in a Docker with an arm64 architecture? Or any alternative, I just want to take a screenshot of my headless html page...
(Things that I can't do without for other reasons: arm64 architecture, sqlite3)
Best regards!