Ein Blog

Posts mit Tag "til"

Ich hab ja die Serie “HTML-Elemente und -Attribute, die kaum jemand kennt, aber doch ganz praktisch sind”. Da stoße ich meistens drauf, wenn ich mal durch die MDN-Doku scrolle. Oder einen Browser-Changelog lese.

Heute habe ich mal durch die Doku von Dockerfiles gescrollt. Hier ein paar Sachen, die man in der Praxis selten sieht, aber dennoch super sind.

Git-Repo als Build-Context

Docker-Build direkt aus einem Git-Repo:

docker build -t mein-image https://github.com/paperless-ngx/paperless-ngx.git#main

Das ist übrigens ein super Argument dafür, Multi-Stage-Dockerfiles zu machen, die ohne Verarbeitung außerhalb der Dockerfile funktionieren. Ich sehe immer noch Dockerfiles, wo einfach nur eine außerhalb des Buildprozesses kompilierte Binary reinkopiert wird. Wenn man alles in Build-Stages hat, kann man das direkt so bauen. Vielleicht jetzt nicht die super-option für die CI-Pipeline, aber um mal schnell ein Image von einem Git-Repo zu bauen, ist das super.

Dementsprechend kann man das auch in einer compose.yaml 1 als Build-Context nehmen:

services:
  paperless:
    build: https://github.com/paperless-ngx/paperless-ngx.git#main
    # ...

COPY

Wo wir gerade bei Multi-Stage-Builds waren: COPY --from kann nicht nur von anderen Stages kopieren, sondern auch aus lokalen und remote-Images. Z. B. empfiehlt composer so, wie man sich die aktuelle Binary holt:

# Specific release
COPY --from=composer/composer:2-bin /composer /usr/bin/composer

COPY kann aber auch --chmod, --chown, womit man direkt noch die Permissions anpassen kann.

Auch interessant für Multi-Stage-Build ist: COPY --link. Das ist ein etwas komplexerer Tipp, deshalb belasse ich es beim Link auf die Doku.

Mich hat aus den Socken gehauen:

# syntax=docker/dockerfile:1
FROM scratch

COPY --parents ./src/**/*.txt /parents/

# Build context:
# ./src/a.txt
# ./src/x/b.txt
# ./src/x/y/c.txt
#
# Output:
# /parents/src/a.txt
# /parents/src/x/b.txt
# /parents/src/x/y/c.txt

Globbing mit Erhaltung der Verzeichnisstruktur!

Kommen wir zu einem weiteren unterschätztem Command:

ADD

ADD kann --chmod, --chown und --link wie auch COPY.

Was aber viele nicht wissen, die Quelle kann auch ein Git-Repo oder eine HTTP-URL sein:

ADD https://example.com/archive.zip /usr/src/things/
ADD git@github.com:user/repo.git /usr/src/things/

Das Git-Repo wird dann geklont. Die URL runtergeladen.

Sicher habt ihr schonmal curl && sha256sum -c && tar -xzf gemacht oder gesehen. Ich jedenfalls schon sehr oft. ADD kann mit --unpack=true auch direkt das Zip-Archiv entpacken. Und noch besser, mit --checksum kann man auch direkt eine Checksum angeben.

ADD --unpack=true \
    --checksum=sha256:24454f830cdb571e2c4ad15481119c43b3cafd48dd869a9b2945d1036d1dc68d \
    https://example.com/archive.tar.gz /usr/src/things/

Da spart man sich direkt curl und tar zu installieren.

--unpack ist per Default übrigens true, wenn die Quelle ein lokales Archiv ist. Bei remote-Archiven ist es false.

Ist die Quelle ein Git-Repo, dann kann man mit --checksum die Commit-Id angeben.

Mal gucken, ob ich noch weitere Scahen finde. Hier gibt es noch weitere Tipps auf meinem Blog. Der mit dem Copy-From-Image war schonmal dabei.

Footnotes

  1. Das ist der neue Name für die docker-compose.yml, die auch kein version-Feld mehr hat.

Mit font-variant-numeric kann man steuern, wie Zahlen gerendert werden.

Beispiele:

  • normal: 1234567890
  • ordinal: 1st 2nd 3rd
  • slashed-zero: 0 1 2 3
  • lining-nums: 1234567890
  • oldstyle-nums: 1234567890
  • proportional-nums: 1234567890
  • tabular-nums: 1234567890
  • diagonal-fractions: 1/2 3/4 5/6
  • stacked-fractions: 1/2 3/4 5/6

Code:

<ul>
	<li>normal: <span style="font-variant-numeric: normal;">1234567890</span>
	<li>ordinal: <span style="font-variant-numeric: ordinal;">1st 2nd 3rd</span>
	<li>slashed-zero: <span style="font-variant-numeric: slashed-zero;">0 1 2 3</span>
	<li>lining-nums: <span style="font-variant-numeric: lining-nums;">1234567890</span>
	<li>oldstyle-nums: <span style="font-variant-numeric: oldstyle-nums;">1234567890</span>
	<li>proportional-nums: <span style="font-variant-numeric: proportional-nums;">1234567890</span>
	<li>tabular-nums: <span style="font-variant-numeric: tabular-nums;">1234567890</span>
	<li>diagonal-fractions: <span style="font-variant-numeric: diagonal-fractions;">1/2 3/4 5/6</span>
	<li>stacked-fractions: <span style="font-variant-numeric: stacked-fractions;">1/2 3/4 5/6</span>
</ul>

tabular-nums kann man gut dafür verwenden, wenn man eine Nicht-Monospace-Font hat, aber die Zahlen an einer Stelle gleich breit haben muss. Das muss die Font natürlich unterstützen.

Mit font-variant-position kann man auch Texte in sub/sup setzen, ohne die HTML-Tags <sub>/<sup> zu verwenden.

TIL sqlite3_set_authorizer. Damit kann man einen Callback definieren, den SQLite aufruft, wenn eine Query auf eine bestimmte Datenbank/Tabelle/Spalte zugreifen möchte.

Gefunden, weil node:sqlite das jetzt kann:

import { DatabaseSync, constants } from 'node:sqlite';
const db = new DatabaseSync(':memory:');

// Set up an authorizer that denies all table creation
db.setAuthorizer((actionCode) => {
  if (actionCode === constants.SQLITE_CREATE_TABLE) {
    return constants.SQLITE_DENY;
  }
  return constants.SQLITE_OK;
});

// This will work
db.prepare('SELECT 1').get();

// This will throw an error due to authorization denial
try {
  db.exec('CREATE TABLE blocked (id INTEGER)');
} catch (err) {
  console.log('Operation blocked:', err.message);
}

Heute im Changelog von Bun gesehen: Node.js hat eine Histogram-API: createHistogram:

import { createHistogram } from "perf_hooks";

// Create a histogram that can record values between 1 and 1,000,000,
// maintaining 3 significant figures of precision.
const histogram = createHistogram({
  lowest: 1,
  highest: 1_000_000,
  figures: 3,
});

histogram.record(100);
histogram.record(200);
histogram.record(1000);
histogram.record(100); // Record a duplicate

console.log("Min:", histogram.min);
console.log("Max:", histogram.max);
console.log("Mean:", histogram.mean);
console.log("Standard Deviation:", histogram.stddev);
console.log("Total Count:", histogram.totalCount);
console.log("Percentile 50 (Median):", histogram.percentile(50));

Any program can be a GitHub Actions shell.

Man kann damit auch Parameter von Bash setzen. Hier global als Default:

defaults:
  run:
    shell: bash -euxo pipefail {0}

ip kann JSON ausgeben: ip -j a

Docker kann mehrere Build-Contexte. Damit kann man dann shared-Directorys haben, ohne den Build-Context auf den gemeinsamen Root zu legen.

Firefox’s html parser is written in Java and converted to C++ at build time. Hier die Java-Sourcen.

Wundert mich sehr, dass das noch niemand nach Rust portiert hat. Klar, so ein HTML-Parser is bestimmt nicht so trivial, aber wenn die Java-Implementierung sich automatisiert nach C++ übersetzen kann, wird das Problem schon relativ vereinfacht sein. Vielleicht benutzen sie in der C++-Version zu viel mutability, die man in Rust einfach nicht tun würde.

TIL: HTML-<address>-Element. War gerade dabei, zu schauen, wie man ein Impressum mit möglichst viel a11y macht.

Die Curl-CLI hat einen Parameter --libcurl <filename>[hinweis], mit dem man sich ein C-Programm ausgeben lassen kann, welches die libcurl so benutzt, dass der Request dabei heraus kommt, den man mit der Curl-CLI gemacht hat.

TIL docker system df:

# docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          5         5         1.318GB   858.6MB (65%)
Containers      5         5         3.416kB   0B (0%)
Local Volumes   5         1         442B      354B (80%)
Build Cache     0         0         0B        0B

Man kennt ja aus Docker-Multistage-Builds das COPY --from=build, um eine Datei aus einer anderen Stage zu kopieren.

Gerade habe ich beim Docker-Image von composer gesehen, dass das nicht nur beschränkt auf Images im selben Multi-stage-Build ist. Man kann dort jedes Image angeben.

Also kann man statt dem hier:

RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
        && php composer-setup.php --install-dir=/usr/local/bin --filename=composer \
        && php -r "unlink('composer-setup.php');" \
        && composer --version

Auch das hier machen und die Binary aus dem offiziellen composer-Image kopieren:

COPY --from=composer /usr/bin/composer /usr/bin/composer

Nachteil dabei ist, dass der Builder dafür das komplette Image runterladen muss. Ist in manchen Situationen vielleicht ganz praktisch.

Heute lernte ich die HEALTHCHECK-Instruktion bei Dockerfiles. Damit kann ein Container einen Befehl definieren, mit dem man rausbekommen kann, ob der Container gerade “Healthy” ist. Erinnert ein bisschen an die Probes aus K8s.

HEALTHCHECK --start-period=10s --timeout=10s \
            CMD curl --fail http://localhost:80 || exit 1

Man kann das auch in einer Compose-File definieren[hinweis].

TIL es gibt ein standardisiertes Format für Test-Output: Test Anything Protocol (TAP).

HLI, dass argv[0] NULL sein kann. Hintergrund: Man kann beim Syscall execve einfach {NULL} übergeben. Das wurde jetzt für PolicyKit relevant und endete in “pwnkit”.

Dass argv[0] NULL sein kann, haben viele Programme sicherlich nicht auf dem Schirm. Gibt bestimmt auch viele andere betroffene Software.