Schreiben Sie Dockerfiles und CI-Pipelines in TypeScript.
Trellis ist ein tragbares CI/CD-Tool. Mit Trellis können Sie Ihre Dockerfiles und CI/CD-Pipelines in TypeScript definieren und sie überall ausführen (lokal oder auf einer gehosteten Plattform).
Installieren Sie zunächst Deno mit brew install deno
(oder vergleichbar).
Zweitens installieren Sie die Trellis-CLI mit:
deno install
--allow-run=docker
--allow-net
--allow-write
--allow-env
--allow-read
https://deno.land/x/[email protected]/cli.ts
Führen Sie trellis --help
aus, um Ihre Installation zu überprüfen:
>>> trellis --help
Usage: trellis build mod.ts
Options:
-V, --version output the version number
-h, --help display help for command
Commands:
ls [file] List all Images and Tasks available in a
TypeScript module
preview [options] [file] Generate a Dockerfile defined in a TypeScript
module
build [options] [file] Build an Image defined in a TypeScript module
run [options] [file] Run a Task defined in a TypeScript module
help [command] display help for command
Exportieren Sie ein beliebiges Image
um die Generierung von Docker-Dateien und die Image-Erstellung mit Trellis zu ermöglichen.
Um beispielsweise ein Ubuntu-Image mit einigen installierten nützlichen Dienstprogrammen zu definieren, könnten Sie die folgende mod.ts
Datei schreiben:
import { Image } from "https://deno.land/x/[email protected]/mod.ts" ;
const UBUNTU_VERSION = "20.04" ;
export const buildStage = Image . from ( `ubuntu: ${ UBUNTU_VERSION } ` )
. workDir ( "/root" )
. aptInstall ( [
"curl" ,
"jq" ,
"git" ,
] ) ;
Beim Ausführen trellis ls mod.ts
werden die erstellbaren Images aufgelistet:
>>> trellis ls mod.ts
Images:
- buildStage (trellis build --target buildStage)
Wir können eine Vorschau der generierten Docker-Datei mit trellis preview mod.ts --target buildStage
anzeigen:
>>> trellis preview --target buildStage
# syntax=docker/dockerfile:1.4
FROM ubuntu:20.04 AS stage-0
WORKDIR /root
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked --mount=type=cache,target=/var/lib/apt,sharing=locked apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends curl git jq
Wir können das Image mit trellis build --target buildStage
erstellen:
>>> trellis build --target buildStage
[+] Building 0.6s (11/11) FINISHED
= > [internal] load build definition from Dockerfile 0.0s
= > = > transferring dockerfile: 335B 0.0s
= > [internal] load .dockerignore 0.0s
= > = > transferring context: 2B 0.0s
= > resolve image config for docker.io/docker/dockerfile:1.4 0.2s
= > CACHED docker-image://docker.io/docker/dockerfile:1.4@sha256:9ba7531bd80fb0a858632727cf7a112fbf 0.0s
= > [internal] load build definition from Dockerfile 0.0s
= > [internal] load .dockerignore 0.0s
= > [internal] load metadata for docker.io/library/ubuntu:20.04 0.2s
= > [stage-0 1/3] FROM docker.io/library/ubuntu:20.04@sha256:35ab2bf57814e9ff49e365efd5a5935b6915ee 0.0s
= > CACHED [stage-0 2/3] WORKDIR /root 0.0s
= > CACHED [stage-0 3/3] RUN --mount=type=cache,target=/var/cache/apt,sharing=locked --mount=type=c 0.0s
= > exporting to image 0.0s
= > = > exporting layers 0.0s
= > = > writing image sha256:17f750ba9a4becf38ce4d584d0de4793bfd6a8139674c3b332cdcdf6525ea8d9 0.0s
= > = > naming to docker.io/trellis/db112e211de238c035a9fd3bbcbd5c417aafc5ee96a8c24d99d4caf81a759903 0.0s
√ Build: trellis/db112e211de238c035a9fd3bbcbd5c417aafc5ee96a8c24d99d4caf81a759903
Exportieren Sie eine beliebige Funktion aus einem TypeScript-Modul, um die Aufgabenausführung mit Trellis zu ermöglichen.
Um beispielsweise eine CI-Pipeline zu definieren, um zu überprüfen, ob unsere Befehlszeilendienstprogramme erfolgreich installiert wurden, könnten Sie die folgende Datei tasks.ts
schreiben:
import { build , Image , run } from "https://deno.land/x/[email protected]/mod.ts" ;
import { buildStage } from "./mod.ts" ;
export default async function runChecks ( ) {
await build ( buildStage ) ;
const checkCurl = Image . from ( buildStage ) . run (
"curl --help" ,
) ;
const checkJq = Image . from ( buildStage ) . run (
"jq --help" ,
) ;
const checkGit = Image . from ( buildStage ) . run (
"git --help" ,
) ;
await Promise . all ( [
run ( checkCurl ) ,
run ( checkJq ) ,
run ( checkGit ) ,
] ) ;
}
Beim Ausführen trellis ls tasks.ts
werden die ausführbaren Aufgaben aufgelistet:
>>> trellis ls tasks.ts
Tasks:
- default (trellis run tasks.ts)
Wir können die Aufgabe lokal mit trellis run tasks.ts
ausführen:
>>> trellis run tasks.ts
[+] Building 1.1s (13/13) FINISHED
= > [internal] load build definition from Dockerfile 0.0s
= > = > transferring dockerfile: 335B 0.0s
= > [internal] load .dockerignore 0.0s
= > = > transferring context: 2B 0.0s
= > resolve image config for docker.io/docker/dockerfile:1.4 0.5s
= > [auth] docker/dockerfile:pull token for registry-1.docker.io 0.0s
= > CACHED docker-image://docker.io/docker/dockerfile:1.4@sha256:9ba7531bd80fb0a858632727cf7a112fbf 0.0s
= > [internal] load .dockerignore 0.0s
= > [internal] load build definition from Dockerfile 0.0s
= > [internal] load metadata for docker.io/library/ubuntu:20.04 0.3s
= > [auth] library/ubuntu:pull token for registry-1.docker.io 0.0s
= > [stage-0 1/3] FROM docker.io/library/ubuntu:20.04@sha256:35ab2bf57814e9ff49e365efd5a5935b6915ee 0.0s
= > CACHED [stage-0 2/3] WORKDIR /root 0.0s
= > CACHED [stage-0 3/3] RUN --mount=type=cache,target=/var/cache/apt,sharing=locked --mount=type=c 0.0s
= > exporting to image 0.0s
= > = > exporting layers 0.0s
= > = > writing image sha256:17f750ba9a4becf38ce4d584d0de4793bfd6a8139674c3b332cdcdf6525ea8d9 0.0s
= > = > naming to docker.io/trellis/adf8a603d1ab539848d89f68491e1b9213c1ca498f3f68d871e1b59c4c7de601 0.0s
√ Build: trellis/adf8a603d1ab539848d89f68491e1b9213c1ca498f3f68d871e1b59c4c7de601
√ Run: git --help
√ Run: jq --help
√ Run: curl --help
Trellis kann über eine trellis.config.ts
Datei konfiguriert werden, deren grundlegende Semantik Vite nachempfunden ist.
Die trellis.config.ts
sollte einen einzelnen Standardexport enthalten, der aus einem defineConfig
Aufruf besteht, etwa so:
import { defineConfig } from "https://deno.land/x/[email protected]/mod.ts" ;
export default defineConfig ( {
engine : "docker" ,
} ) ;
Trellis verwendet die nächstgelegene trellis.config.ts
und sucht zunächst im aktuellen Arbeitsverzeichnis und dann in jedem nachfolgenden übergeordneten Verzeichnis.
Trellis ist mit depot.dev kompatibel, das verwendet werden kann, um Cloud-beschleunigte Builds ohne Konfiguration zu ermöglichen. Führen Sie die Depot-Installation durch ( brew install depot/tap/depot
oder ähnlich, gefolgt von depot login
) und definieren Sie dann eine trellis.config.ts
wie folgt:
import { defineConfig } from "https://deno.land/x/[email protected]/mod.ts" ;
export default defineConfig ( {
engine : {
type : "depot" ,
project : "${YOUR_PROJECT_ID}" ,
} ,
} ) ;
Von dort aus laufen alle Trellis-Builds über das Depot.
Trellis läuft auf Deno und ist somit eine Installation in einem Schritt auf GitHub Actions:
name : CI
on :
push :
branches : [ main ]
pull_request :
branches : [ main ]
env :
DOCKER_BUILDKIT : 1
jobs :
build :
name : " Build "
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v3
- name : " Install Deno "
uses : denoland/setup-deno@v1
with :
deno-version : " 1.25.2 "
- name : " Install Trellis "
working-directory : ./trellis
run : deno install --allow-run=docker --allow-net --allow-write --allow-env --allow-read https://deno.land/x/[email protected]/cli.ts
- name : " Build the image "
working-directory : ./examples/typescript
run : trellis build trellis/mod.ts
Trellis basiert auf den folgenden Beobachtungen, die aus der Erfahrung mit der Wartung großer, containerisierter CI/CD-Systeme stammen.
Docker-Dateien sind schwer zu warten . Im Laufe der Zeit neigen große Systeme dazu, Sammlungen von Docker-Dateien mit ähnlichen Unterabschnitten, aber keinen gemeinsamen Abstraktionen anzusammeln.
Effiziente Docker-Dateien sind schwer zu schreiben . Das Schreiben einer Docker-Datei, die bei minimalem Platzbedarf maximal zwischenspeicherbar ist, erfordert erhebliches Fachwissen. Für apt-get install
empfiehlt die Docker-Dokumentation beispielsweise Folgendes:
RUN apt-get update && apt-get install -y
# Be sure to sort dependencies to maximize cacheability.
bzr
cvs
git
mercurial
subversion
# Clear the apt cache to minimize disk size.
&& rm -rf /var/lib/apt/lists/ *
Die CI/CD-Iterationsschleife ist zu langsam . Der übliche Arbeitsablauf zum Schreiben einer neuen GitHub Actions-Pipeline, Jenkinsfile usw. besteht darin, zu committen, zu pushen, darauf zu warten, dass das System Ihre Änderung bestätigt, und dann darauf zu warten, dass Ihre Aufgabe fehlschlägt – zehn- oder sogar hunderte Male hintereinander. Mit bestehenden CI-Lösungen schreiben Sie Code, der auf einem unbekannten System außerhalb Ihrer Kontrolle ausgeführt wird, ohne einen erstklassigen Entwicklungsworkflow.
CI/CD-Systeme erzeugen einen erheblichen Lock-in . Die Portierung Ihrer Jenkinsfiles oder YAML-Dateien auf GitHub Actions oder umgekehrt erfordert die Auseinandersetzung mit plattformspezifischen Abstraktionen.
Trellis löst diese Probleme durch einige wichtige Designentscheidungen.
Erstens: Mit Trellis definieren Sie Ihre Dockerfiles und CI/CD-Pipelines in TypeScript. Dadurch erhalten Sie die Leistungsfähigkeit einer „vollständigen“ Programmiersprache und behalten gleichzeitig eine deklarative API bei. Mit TypeScript erhalten wir folgende Vorteile:
apt-get install
zu vermeiden.deno.land
. Zweitens: Trellis macht die lokale Ausführung zu einem erstklassigen Grundelement. CI/CD sollte sich nicht wie ein völlig separates System anfühlen; Es sollte sich anfühlen, als würde man Code ausführen. Trellis basiert auf Deno und ist äußerst tragbar. Sie können trellis build
lokal ausführen, genau wie Sie es auf GitHub Actions oder anderswo tun würden. Auf diese Weise lässt sich Trellis von Werkzeugen wie Earthly und Dagger inspirieren.
Trellis hat einige ehrgeizige Ziele, die noch nicht verwirklicht wurden:
Trellis ist sowohl eine Bibliothek als auch eine Befehlszeilenschnittstelle. Mit Trellis exportieren Sie Image
und ausführbare Funktionen (genannt „Aufgaben“) aus Ihren TypeScript-Modulen und führen sie dann über die trellis
-CLI aus.
trellis preview
Generieren Sie eine Docker-Datei, die in einem TypeScript-Modul definiert ist.
Usage: trellis preview [options] [file]
Generate a Dockerfile defined in a TypeScript module
Options:
-t, --target < TARGET > Image to build within the TypeScript module
-h, --help display help for command
trellis build
Erstellen Sie ein Bild, das in einem TypeScript-Modul definiert ist.
Usage: trellis build [options] [file]
Build an Image defined in a TypeScript module
Options:
-t, --target < TARGET > Image to build within the TypeScript module
--push Whether to push the image to a remote registry
-h, --help display help for command
trellis ls
Listen Sie alle in einem TypeScript-Modul verfügbaren Bilder und Aufgaben auf.
Usage: trellis ls [options] [file]
List all Images and Tasks available in a TypeScript module
Options:
-h, --help display help for command
trellis run
Führen Sie eine in einem TypeScript-Modul definierte Aufgabe aus.
Run a Task defined in a TypeScript module
Options:
-t, --target <TARGET> Task to run within the TypeScript module
-h, --help display help for command
Das Verzeichnis ./examples
zeigt eine Vielzahl von Anwendungsfällen für Trellis. Trellis ist flexibel und kann ausschließlich zum Generieren von Docker-Dateien für andere Systeme oder zum Definieren ganzer CI/CD-Pipelines verwendet werden.
rocket
: Ein Rust-Webserver auf dem Rocket-Framework. Demonstriert mehrstufige Builds und Bereitstellung über Fly.io durch Nutzung trellis preview
.ruff
: Ein Rust-Befehlszeilentool. Demonstriert effiziente Builds und CI-Prüfungen.runc
: Ein Linux-Entwicklungscontainer. Demonstriert das Generieren von Artefakten mit Trellis und deren Zurückkopieren auf den Host-Computer.turborepo
: Turborepos eigenes Docker-Beispiel, geändert, um Docker-Dateien mit Trellis zu generieren.typescript
: Ein TypeScript-Monorepo. Demonstriert effiziente Builds und CI-Prüfungen sowie die Konsolidierung von Konstanten (wie der Liste der TypeScript-Arbeitsbereiche).wasm
: Ein „Hallo Welt!“ Rust-Binärdatei, die zu Wasm kompiliert und auf Wasmtime getestet wurde. Trellis basiert auf Deno, das als einzelne ausführbare Binärdatei ohne externe Abhängigkeiten verteilt wird. Die Verwendung von Deno bedeutet, dass die Installation von Trellis an einem beliebigen Ort genauso einfach ist wie deno install ...
– es gibt kein package.json
, kein npm install
und keinen TypeScript-Transpilierungsschritt.
Ähnlich wie Nixpacks generiert Trellis Docker-Dateien. Dies vereinfacht die Implementierung von Trellis, ermöglicht es Benutzern aber auch, Trellis allein für die Dockerfile-Generierung zu nutzen, anstatt es als vollständige CI/CD-Lösung zu nutzen.
trellis build
und trellis run
hängen von Docker ab und gehen davon aus, dass der Docker-Daemon lokal zugänglich ist.
MIT