TypeScript で Dockerfile と CI パイプラインを作成します。
Trellis はポータブルな CI/CD ツールです。 Trellis を使用すると、TypeScript で Dockerfile と CI/CD パイプラインを定義し、それらをどこでも (ローカルまたはホストされたプラットフォーム上で) 実行できます。
まず、 brew install deno
(または同等のもの) を使用して Deno をインストールします。
次に、次のコマンドを使用して Trellis CLI をインストールします。
deno install
--allow-run=docker
--allow-net
--allow-write
--allow-env
--allow-read
https://deno.land/x/[email protected]/cli.ts
trellis --help
実行して、インストールを確認します。
>>> 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
任意のImage
をエクスポートして、Dockerfile の生成と Trellis を使用したイメージの構築を有効にします。
たとえば、いくつかの便利なユーティリティがインストールされた Ubuntu イメージを定義するには、次のmod.ts
ファイルを作成できます。
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" ,
] ) ;
trellis ls mod.ts
実行すると、ビルド可能なイメージがリストされます。
>>> trellis ls mod.ts
Images:
- buildStage (trellis build --target buildStage)
生成された Dockerfile は、 trellis preview mod.ts --target buildStage
を使用してプレビューできます。
>>> 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
trellis build --target buildStage
を使用してイメージをビルドできます。
>>> 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
TypeScript モジュールから任意の関数をエクスポートして、Trellis でタスクを実行できるようにします。
たとえば、コマンドライン ユーティリティが正常にインストールされたことを確認する CI パイプラインを定義するには、次のtasks.ts
ファイルを作成します。
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 ) ,
] ) ;
}
trellis ls tasks.ts
実行すると、実行可能なタスクがリストされます。
>>> trellis ls tasks.ts
Tasks:
- default (trellis run tasks.ts)
trellis run tasks.ts
を使用してローカルでタスクを実行できます。
>>> 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 はtrellis.config.ts
ファイルを介して設定でき、その基本的なセマンティクスは Vite をモデルにしています。
trellis.config.ts
、次のような、 defineConfig
呼び出しで構成される単一のデフォルト エクスポートが含まれている必要があります。
import { defineConfig } from "https://deno.land/x/[email protected]/mod.ts" ;
export default defineConfig ( {
engine : "docker" ,
} ) ;
Trellis は最も近いtrellis.config.ts
使用し、最初に現在の作業ディレクトリを検索し、次に後続の各親ディレクトリを検索します。
Trellis は depot.dev と互換性があり、これを使用すると、構成なしでクラウド高速化されたビルドを有効にすることができます。 Depot インストールを実行し ( brew install depot/tap/depot
などのコマンドを実行し、続いてdepot login
)、次のようにtrellis.config.ts
を定義します。
import { defineConfig } from "https://deno.land/x/[email protected]/mod.ts" ;
export default defineConfig ( {
engine : {
type : "depot" ,
project : "${YOUR_PROJECT_ID}" ,
} ,
} ) ;
そこから、すべての Trellis ビルドが Depot を介して実行されます。
Trellis は Deno 上で実行されるため、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 は、大規模なコンテナ化された CI/CD システムの保守の経験から得られた次の観察によって動機付けられています。
Dockerfile は保守が困難です。時間の経過とともに、大規模なシステムでは、同様のサブセクションを持つ Dockerfile のコレクションが蓄積される傾向がありますが、共有抽象化はありません。
効率的なDockerfileを作成するのは困難です。最小限のフットプリントで最大限にキャッシュ可能な Dockerfile を作成するには、かなりの専門知識が必要です。たとえば、 apt-get install
実行するには、Docker ドキュメントでは次のことを推奨しています。
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/ *
CI/CD 反復ループが遅すぎます。新しい GitHub Actions パイプラインや Jenkinsfile などを作成するための一般的なワークフローは、コミット、プッシュし、システムが変更を承認するまで待機し、その後、タスクが失敗するまで待機することを、数十回、場合によっては数百回続けて行うことです。既存の CI ソリューションでは、第一級の開発ワークフローを使用せずに、自分の制御の外にある見慣れないシステム上で実行するコードを作成することになります。
CI/CD システムは重大なロックインを引き起こします。 Jenkinsfiles または YAML ファイルを GitHub Actions に移植したり、その逆を行うには、プラットフォーム固有の抽象化に取り組む必要があります。
Trellis は、いくつかの重要な設計上の決定を通じてこれらの問題を解決します。
まず、 Trellis を使用すると、TypeScript で Dockerfile と CI/CD パイプラインを定義します。これにより、宣言型 API を保持しながら、「完全な」プログラミング言語の機能が得られます。 TypeScript を使用すると、次の利点が得られます。
apt-get install
ステップを手動で記述することを回避します。deno.land
から Slack クライアントをインポートするのと同じくらい簡単です。 2 番目: Trellis はローカル実行をファーストクラスのプリミティブにします。 CI/CD が完全に別個のシステムのように感じられるべきではありません。コードを実行しているように感じられるはずです。 Trellis は Deno 上に構築されており、移植性に優れています。 GitHub Actions などで行うのと同じように、 trellis build
ローカルで実行できます。このように、Trellis は Earthly や Dagger などのツールからインスピレーションを得ています。
Trellis には、まだ実現されていない野心的な目標がいくつかあります。
Trellis は、ライブラリであると同時にコマンドライン インターフェイスでもあります。 Trellis を使用すると、 Image
定義と実行可能な関数 (「タスク」と呼ばれる) を TypeScript モジュールからエクスポートし、それらをtrellis
CLI 経由で実行します。
trellis preview
TypeScript モジュールで定義された Dockerfile を生成します。
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
TypeScript モジュールで定義されたイメージを構築します。
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
TypeScript モジュールで利用可能なすべてのイメージとタスクをリストします。
Usage: trellis ls [options] [file]
List all Images and Tasks available in a TypeScript module
Options:
-h, --help display help for command
trellis run
TypeScript モジュールで定義されたタスクを実行します。
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
./examples
ディレクトリは、Trellis のさまざまな使用例を示しています。 Trellis は柔軟性があり、他のシステム用の Dockerfile を生成するため、または CI/CD パイプライン全体を定義するためだけに使用できます。
rocket
: Rocket フレームワーク上の Rust Web サーバー。 trellis preview
を活用して、Fly.io を介したマルチステージ ビルドとデプロイメントをデモンストレーションします。ruff
: Rust コマンドライン ツール。効率的なビルドと CI チェックを示します。runc
: Linux 開発コンテナ。 Trellis を使用してアーティファクトを生成し、それらをホスト マシンにコピーして戻す方法を示します。turborepo
: Turborepo 独自の Docker サンプル。Trellis で Dockerfile を生成するように変更されています。typescript
: TypeScript モノリポジトリ。定数 (TypeScript ワークスペースのリストなど) の統合とともに、効率的なビルドと CI チェックを示します。wasm
: 「Hello, world!」 Wasm にコンパイルされ、Wasmtime でテストされた Rust バイナリ。 Trellis は Deno 上に構築されており、外部依存関係のない単一のバイナリ実行可能ファイルとして配布されます。 Deno を使用するということは、どこにでもTrellis をインストールすることがdeno install ...
と同じくらい簡単であることを意味します。 — package.json
、 npm install
、および TypeScript のトランスパイル手順はありません。
Nixpack と同様に、Trellis は Dockerfile を生成します。これにより、Trellis の実装が簡素化されますが、ユーザーは完全な CI/CD ソリューションとしてではなく、Dockerfile 生成のみに Trellis を利用できるようになります。
trellis build
とtrellis run
Docker に依存しており、Docker デーモンがローカルでアクセスできることを前提としています。
マサチューセッツ工科大学