Dockerで建てたコンテナの上でPerlのWebサービスを開発している場合, 例えばテストを実行するとき等はコンテナ上で実行する必要があります. そういった時, 皆さんはどうしていますか?
例えばdocker-compose
でコンテナ群を立ち上げていて, PerlのWebサービスがapp
というコンテナで動いている時, 次のような選択肢があると思います:
docker-compose exec app carton ...
するdocker-compose exec app /bin/sh
でコンテナの中に入り,carton ...
する
...これでも全然良いのですけれど, とはいえ個人的には面倒という気持ちがあります.
やはり, 無意識にこれまで通りcarton
でコマンドを実行をすると, 自動的にDockerコンテナの中で実行されて欲しい!!!
...と考えた結果, このようなスクリプトが生まれました.
#!/usr/bin/env perl use strict; use warnings; use utf8; my $cmd; my $argv = join ' ', @ARGV; if ($ENV{'DISABLE_DOCKER'}) { $cmd = sprintf(q{$(plenv which carton) %s}, $argv); } else { my $plack_env = $ENV{'PLACK_ENV'} || 'local'; my $env = join ' ', map { sprintf('%s=%s', $_, $ENV{$_}) } grep { $_ =~ /^PLACK_ENV$/ } keys %ENV; my @commands = 'carton'; unshift @commands, $env if $env; push @commands, $argv if $argv; $cmd = sprintf(q{PLACK_ENV=%s docker-compose exec app /bin/sh -c '%s'}, $plack_env, join(' ', @commands)); print "exec: $cmd\n"; } exec $cmd;
あとはこのスクリプトをcarton
として呼び出せるようにしてあげればOKで, 例えばcarton exec prove t
とすると,
PLACK_ENV=local docker-compose exec app /bin/sh -c 'PLACK_ENV=local carton exec prove t'
というコマンドが実行されます.
もしDockerコンテナの中で実行したくないならば, DISABLE_DOCKER=1
を付けて実行すればOK.
...ね, 簡単でしょう?
ちなみに, Dockerを使っている時だけこのcarton
のラッパースクリプトを使いたい, という時はdirenv
を使うと便利です.
例えば, このスクリプトが /path/to/script
に設置されていて, /path/to/script/carton
で使えるようになっているなら,
export PATH=/path/to/script:$PATH
という感じで.envrc
を設置しれあげれば, そのディレクトリ下でのみ, carton
のラッパースクリプトが使われるようになります.