自由のなる木

RSS
公開日
2022-05-02

GNU Guix であらゆる技術スタックのパッケージを管理する

先日、Guix が誕生してから 10 年目を迎え、様々なユーザーから祝福の声がブログで公開された。

10 years of stories behind Guix

さらに一昨日になって、FOSS and Crafts という Podcast にて下記のエピソードが公開された。

44: Celebrating a Decade of Guix

私もこのエピソードを聞いてはみたものの、英語のリスニング能力がほぼないため、話半分も理解できなかったのだが、「Guix のすばらしい 10 個のこと」を紹介する内容で、英語がわかるならば Guix の概要を把握するのにとても良いコンテンツだと思った。

今回この記事を書こうと思ったのは、8 個目の「Great way to develop other software」(24:19 くらいから) を聞いて共感したためだ。

ソフトウェア開発に必要なパッケージと環境を Guix で閉じ込める

GNU Guix といふもの」という記事で簡単に触れたことがあるが、Guix には guix shell という機能がある。

この機能を使うと開発環境を簡単に作成することができる。

具体的には以下のような手順で環境を作成する。

  1. 開発プロジェクトのルートディレクトリに manifest.scm または guix.scm というファイル名でマニフェストを記述する
  2. ~/.config/guix/shell-authorized-directories にプロジェクトルートのパスを追記する
  3. プロジェクトルートで guix shell または guix shell --pure を実行する1

上記を実行すると、マニフェストに記載したパッケージ (プログラミング言語のランタイムや、使用するライブラリなど) が利用可能な環境にアクセスできる。

Docker のコンテナに開発環境を閉じ込めて、その環境に docker exec で入るようなものだと理解してもらって良い。

この機能があるため、私はツールのカスタマイズやワンライナーで使用することの多いプログラミング言語のランタイムを除いて、プログラミング言語の環境は自分の端末にほとんどインストールしていない。

Invoking guix shell (GNU Guix Reference Manual)

ユニバーサルなパッケージ管理

guix shell で開発環境を作成する利点は、OS やプログラミング言語で提供されたパッケージ管理機能に依らず、全てを Guix のパッケージ管理機能に委ねることができる点だ。

例えば、先日、私は Haskell で Scotty を使った簡単なウェブアプリケーションのサンプルを書こうとしたのだが、Cabal や Stack などの知識が乏しいため、試しに guix shell で Scotty の使用できる Haskell の環境を作ろうと思った。

少しとまどった部分はあったが Stack の知識はほとんどなくても、Scotty の使用できる Haskell の環境を作ることができた。

具体的にはプロジェクトルートの manifest.scm に下記のようなマニフェストを書いただけだ。

(use-modules (guix packages)
             (guix download)
             (guix build-system haskell)
             ((guix licenses) #:prefix license:)
             (gnu packages haskell-xyz)
             (gnu packages haskell-web))

(define-public ghc-scotty
  (package
    (name "ghc-scotty")
    (version "0.12")
    (source
      (origin
        (method url-fetch)
        (uri (hackage-uri "scotty" version))
        (sha256
          (base32 "1lpggpdzgjk23mq7aa64yylds5dbm4ynhcvbarqihjxabvh7xmz1"))))
    (build-system haskell-build-system)
    (inputs
      (list ghc-aeson
            ghc-base-compat-batteries
            ghc-blaze-builder
            ghc-case-insensitive
            ghc-data-default-class
            ghc-fail
            ghc-http-types
            ghc-monad-control
            ghc-nats
            ghc-network
            ghc-regex-compat
            ghc-transformers-base
            ghc-transformers-compat
            ghc-wai
            ghc-wai-extra
            ghc-warp))
    (arguments
      `(#:tests?
        #f
        #:cabal-revision
        ("6" "15gwvx9gdk4vxh1x2n5xvnrix8m0wl96a4aqbdmdfrka43sywfma")))
    (home-page "https://github.com/scotty-web/scotty")
    (synopsis
      "Haskell web framework inspired by Ruby's Sinatra, using WAI and Warp")
    (description
      "This package provides a Haskell web framework inspired by Ruby's Sinatra, using
WAI and Warp. . @ {-# LANGUAGE OverloadedStrings #-} .  import
Web.Scotty .  import Data.Monoid (mconcat) .  main = scotty 3000 $   get
&#34;/:word&#34; $ do &#32;&#32;&#32;&#32;beam <- param &#34;word&#34;
&#32;&#32;&#32;&#32;html $ mconcat [&#34;&#60;h1&#62;Scotty, &#34;, beam, &#34;
me up!&#60;/h1&#62;&#34;] @ . .  Scotty is the cheap and cheerful way to write
RESTful, declarative web applications. . * A page is as simple as defining the
verb, url pattern, and Text content. . * It is template-language agnostic.
Anything that returns a Text value will do. . * Conforms to WAI Application
interface. . * Uses very fast Warp webserver by default. .  As for the name:
Sinatra + Warp = Scotty. . [WAI] <http://hackage.haskell.org/package/wai> .
[Warp] <http://hackage.haskell.org/package/warp>")
    (license license:bsd-3)))

(packages->manifest
 (list
  (specification->package "ghc@8.10.7")
  ghc-scotty))

Guix には Scotty は収録されていなかったが、Guix には guix import という、あらゆるプログラミング言語のパッケージリポジトリに収録されているパッケージを、Guix のパッケージ定義に翻訳してくれる機能がある。2

上記で定義している ghc-scotty というパッケージ定義は、下記のコマンドを実行結果を貼り付けたに過ぎない。3

guix import stackage --lts-version=18.28 -r -t scotty

ここでは Haskell を例にとったが、どのプログラミング言語でもプログラミング固有のパッケージ管理ツールの力を借りることなく、Guix でパッケージ管理ができるので、慣れてしまうと非常に快適だ。

さらに、マニフェストファイルは Scheme で記述するため、条件に応じて使用するパッケージ構成を変更したりするカスタマイズをしたければ、Scheme のプログラミング言語としての能力を借りれば良いだけだ。

Invoking guix import (GNU Guix Reference Manual)

パッケージ管理のさらに先へ

Guix がユニバーサルなパッケージ管理機能を提供するということは、単にひとつのプログラミング言語のパッケージ管理の代替手段を提供するというだけでなく、アプリケーションに必要な様々な技術スタックのパッケージを Guix で一元管理できるということでもある。

例えば、フロントエンドとバックエンドで異なる技術スタックを使用することは頻繁にあることで、データベースや Web サーバなどのミドルウェアと組み合わせることも多い。

Java で開発するプロジェクトであれば、フロントエンドは NPM でパッケージを管理し、バックエンドは Gradle で管理し、プログラミング言語のランタイムやデータベースなどのミドルウェアは APT などの OS のパッケージ管理ツールでパッケージを管理することが多いだろう。

Guix にはそれらを単一のマニフェストに記述して管理できるポテンシャルがある。

さらに FOSS and Crafts で紹介されているように、マニフェストを元に guix pack で deb パッケージにまとめたり、Docker イメージにまとめたりもできる。4

また、ミドルウェアのサービス定義やアカウント定義などのシステム定義も含めた上で、guix system vm で自己完結した仮想マシンを作成することもできるし、Ansible などのように guix deploy で、Guix がインストールされた SSH ログインできるリモートマシンへのデプロイもできるようだ。5

まだまだこの辺りは発展途上のように見受けられはするが、Guix を活用した興味深いユースケースではあるので、発展を見届けたいと思う。

Guix のユーザーが増えれば、様々なプロジェクトで Guix のマニフェストが提供される未来がやって来るかもしれない。

既存のパッケージ管理に不満がある方は試してみてほしい。

また、「GNU Guix の日本語コミュニティができた」という記事で書いたとおり、Guix-jp という Slack スペースがあるので、Guix に興味のある方はぜひ遊びにきて欲しい。

以上。


  1. guix shell の代わりに guix shell --pure を実行すると実行元の環境に依存しない独立した環境にアクセスできる。 

  2. この機能については最近まで知らなかったのだが、Guix-jp のコミュニティメンバである ROCKTAKEY さんが gh というソフトウェアをパッケージ化する過程で使用したということを教えてくれて知ることができた。コミュニティの力は偉大だ。 

  3. Haskell には hackage という importer と stackage という importer が用意されている。Haskell のバージョンを固定した上で、stackage importer を使用すると環境の再現性が高まって安全かもしれない。 

  4. 試しにシンプルな環境を guix pack で Docker イメージにまとめたところ、イメージサイズが相当に大きかったので、用途は限られそうだ。 

  5. 公式で DigitalOcean の Droplet をデプロイする機能も用意されているため、AWS などの仮想マシンをプロビジョニングすることも技術的には可能だと思われる。