monoランタイムとPaketを実行できるだけのdllをインストールしたGoogle Cloud ShellのDockerイメージを作った

Google Cloud Shell で F# スクリプトを書きたかった。Google Cloud Shellには .NET Core SDK がインストールされているのでdotnet fsiコマンドで F# の REPL が使える。

nuget パッケージを使うときに Paket があると便利だが、Paket の実行には mono が必要。mono は apt でインストールができる。

Cloud Shell のインスタンスに毎回インストールしてもいいが時間がかかるので、Cloud Shell のカスタム環境として用意することにした。

カスタム環境は Google Container Registory に置いた Docker イメージを Cloud Shell として利用する。Google によって提供される Docker イメージをベースにする必要がある。提供されるベースイメージは debian 9 (strech)。

カスタム環境用の Docker イメージをビルドする Dockerfile を書いた。 mono のパッケージリポジトリと鍵を追加して、apt install で mono-runtime と必要なライブラリをインストールする。

FROM gcr.io/cloudshell-images/cloudshell:latest

RUN apt-get update \
     && apt-get install -y --no-install-recommends gnupg dirmngr \
     && export GNUPGHOME="$(mktemp -d)" \
     && gpg --batch --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF \
     && gpg --batch --export --armor 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF > /etc/apt/trusted.gpg.d/mono.gpg.asc \
     && gpgconf --kill all \
     && rm -rf "$GNUPGHOME" \
     && APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn apt-key list | grep Xamarin \
     && apt-get purge -y --auto-remove gnupg dirmngr \
     && apt-get clean \
     && rm -rf /var/lib/apt/lists/*

RUN echo "deb http://download.mono-project.com/repo/debian stable-stretch main" > /etc/apt/sources.list.d/mono-official-stable.list \
     && apt-get update \
     && apt-get install -y \
       mono-runtime \
       libmono-system-data4.0-cil \
       libmono-system-io-compression-filesystem4.0-cil \
       libmono-system-net-http4.0-cil \
       libmono-system-runtime-serialization4.0-cil \
       libmono-system-xml-linq4.0-cil \
     && apt-get clean \
     && rm -rf /var/lib/apt/lists/* /tmp/*

Paketを実行するためのライブラリ

Paket.exe を実行するには mono-runtime だけでは足りない。mono-complete パッケージであれば十分だけど使わないライブラリもインストールされる。mono-runtime で Paket を実行してみてエラー表示から足りないdllを確認した。以下はとりあえずパッケージダウンロードを試してエラーになったものだけ。これらのライブラリがあれば nuget からライブラリのダウンロードはできるようになる。

  • System.Data.dll
  • System.IO.Compression.FileSystem.dll
  • System.Net.Http.dll
  • System.Runtime.Serialization.dll
  • System.Xml.Linq.dll

必要になったmonoプロジェクトの情報

鍵IDとパッケージリポジトリURL
https://www.mono-project.com/download/stable/#download-lin-debian
パッケージリポジトリの追加のしかた
https://github.com/mono/docker/blob/1d31220a290b2b4d19654a8cdb4ba13888e29717/6.4.0.198/slim/Dockerfile
dllとパッケージ名の対応
https://github.com/mono/linux-packaging-mono/blob/master/debian/control

Dockerfileのベストプラクティ

docs.docker.jp

apt update, install, clean を同じ RUN で実行する。

RUN apt-get update \
     && apt-get install ... \
     ...
     && apt-get clean \
     && rm -rf /var/lib/apt/lists/*