競プロのサイトのように入力されたコードを実行して出力が指定のものになってるかどうかをチェックする機能をプログラミングスクールの機能として作りたい。
少なくともrubyとjsは実行できるようにしたい。メンターの@maedanaさんから競プロのジャッジサーバーのOSSであるarrow-judgeを教えてもらった。
なるほど、chroot, cgroup, ulimit等で実行ディレクトリやCPU・メモリといったリソースを制限しているようだ。
ってことはdockerでもできそうだということで調べてみた。
dockerでコンテナから外部へのネットワークアクセスを禁止する
まずは外部ネットワークにアクセスされると危険なので防ぎたい。
$ docker run --rm debian ping komagata.org -c 3
PING komagata.org (151.101.1.195) 56(84) bytes of data.
64 bytes from 151.101.1.195 (151.101.1.195): icmp_seq=1 ttl=37 time=4.34 ms
64 bytes from 151.101.1.195 (151.101.1.195): icmp_seq=2 ttl=37 time=5.27 ms
64 bytes from 151.101.1.195 (151.101.1.195): icmp_seq=3 ttl=37 time=5.32 ms
--- komagata.org ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 6ms
rtt min/avg/max/mdev = 3.698/4.748/5.385/0.748 ms
これが失敗するようにできれば良い。
$ docker run --net=none --rm debian ping komagata.org -c 3
ping: komagata.org: Temporary failure in name resolution
デフォルトでインストールされる3つのネットワークのうちの一つnone
を指定すればあらゆる外部ネットワークアクセスは防げそうだ。
dockerでメモリ使用量を制限する
docker run -m 100m --rm debian ping komagata.org -c 3
PING komagata.org (151.101.1.195) 56(84) bytes of data.
64 bytes from 151.101.1.195 (151.101.1.195): icmp_seq=1 ttl=37 time=3.70 ms
64 bytes from 151.101.1.195 (151.101.1.195): icmp_seq=2 ttl=37 time=5.16 ms
64 bytes from 151.101.1.195 (151.101.1.195): icmp_seq=3 ttl=37 time=5.39 ms
--- komagata.org ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 6ms
rtt min/avg/max/mdev = 3.698/4.748/5.385/0.748 ms
100Mに制限してみたがどのぐらいが適量かわからない。
続く
あとはコードを楽にcontainerで実行したい。そして標準入力・コマンドライン引数を流し込んで、標準出力・標準エラーが取れればOKだが・・・