Go
Jenkins
docker
DockerDay 8

Dockerを使ってオンラインコンパイル環境を作る

More than 3 years have passed since last update.

はじめに

Goの開発版などを手軽に試すことができる環境が欲しいと思い、Dockerコンテナを利用したSangoboxというサイトを作ってみました。

少し調べてみたところ、Dockerを利用したオンラインコンパイラはすでにいくつか存在するようです。ソースが公開されているものもありますが、Sangoboxを作る上では特に参考にはしていません。

ただし、インターフェースはWandboxの影響を受けています。

Sangobox

作ってみたサイトがこちらです。まだ実験段階なので対応している言語は少ないです。

ソースコードのライセンスはAGPLです。

特徴

  • JSON形式のREST API(https://github.com/h2so5/sango/wiki/REST-API)
  • WebSokcetでリアルタイムに標準出力・エラーを表示
  • ビルド時のコマンドラインを表示
  • 実行環境の詳しいバージョン情報を表示
  • 共有用のURLを自動的に生成 (例: http://35.h2so5.net/bnDLyyqWETd)
  • ビルド・実行時のgetrusageの結果を取得可能(APIのみ)
  • 複数ファイルのコンパイルが可能(APIのみ)
  • 1日1回Dockerイメージをリビルド
  • Go: 開発版が使える、Race Detectorに対応
  • C/C++: 実行時にValgrindを利用可能
  • Qtが利用可能

制限

  • ビルド・実行時間はそれぞれ5秒まで
  • 標準出力・エラーはそれぞれ10KiBまで
  • ネットワークは利用不可

環境

  • Ubuntu 14.04
  • Go 1.3
  • Docker 1.3.1
  • martini
  • Redis
  • Jenkins

Redisは実行結果の保存及びキャッシュに利用しています。

Dockerではまったところ

公式のクライアントAPIが使いにくい

公式のレポジトリにGo用のクライアントパッケージがあります(https://github.com/docker/docker/tree/master/api/client )。
最初は便利だと思ったのですが、このクライアントには後方互換性がなく最新版のDockerとしか通信できないという問題があります。

Goのパッケージの仕様上古いバージョンのパッケージを利用するのは面倒ですし、gitのタグがAPIのバージョンと同期していないのでコミットログを辿らないとお目当てのリビジョンを見つけることができません。

結局クライアントを使うのはあきらめてCmd.Runでdockerコマンドを直接実行するようにしています。

dockerコマンドを同時に実行すると不安定になる

これは最新のDockerではいくらか改善されているかもしれません。

排他制御が不十分なのか、dockerコマンドを同時に実行するとエラーが頻発します。
一番困ったのは、docker run --rm を同時に実行すると、終了時にコンテナの削除がエラーで失敗してしまいディスクスペースがどんどん圧迫されるという現象でした。

現在は対策として--rm を付けずに実行し、使い終わったコンテナは後で定期的に削除するという方法を採っています。