(追記)

この記事で書いていた Dockerfile が動かなくなっていたので動くように修正した記事を書きました。

(追記ここまで)

この記事は、 Perl Advent Calendar 2017 の 13 日目の記事です。

昨日は sago35 さんの 「Strawberry Perl に Minilla をインストールする」でした。

この記事のパッチがあたって、 CPAN からインストールできるようになったようです。

これで、 Windows + Strawberry Perl な方も安心して使えますね。

ちょっとしたものを作り始める時でも Minilla で雛形を作ってから始めると色々と便利ですよね。

最近はあまり使っていなかったので、この機会にまた使い始めようと思います。

Docker で動いている Perl で作ったアプリを Heroku で公開する

実は少し前に「DockerでHerokuでMojoliciousが動いたぞ!!!」というのを書いてしまっていて、これを少し改善してアドベントカレンダーのネタにしようと思います。

Heroku で Perl のプログラムを動かすには buildpack を使えばよいのですが、少しコツがいるのです。

しかし、2年ほど前から Heroku でもコンテナを動かすことができるようになっており、最近ではインターフェイスも改善されていて、比較的簡単に公開できるようになっています。

なので、コンテナを使って Perl のアプリを作って、それを Heroku で公開する、というのが今後しばらくは良さそうかなと思います。

Heroku をコマンドラインインターフェイスで操作する

さて、 heroku を使う時はコマンドラインツールを使うと便利です。

Mac な方は Homebrew を使って brew install heroku が手軽だと思います。

Windows な方にも用意されているようなので使ってみてください。私は使ったことがないので使用感についてはわかりません。

基本的な使い方はググれば色々と出てくると思いますので省略します。幾つか丁寧そうな記事を貼っておきます。

事前の準備

一つのプロジェクトを作るところをイメージしながら進めていきます。

ソースコードは git で管理することにします。

まずは、プロジェクトのディレクトリを作成しましょう。

また、 Heroku では現在は Volume をマウントする方式には対応していないので、 COPY コマンドを使います。細かい説明は省きますが、 COPY する必要があるファイルだけをまとめておくと便利だと思います。

ここでは、 COPY するファイル群を webapp というディレクトリに入れておくことにします。

では、ターミナルを操作していきます。

1
2
3
$ mkdir myproject && cd myproject
$ git init
$ mkdir webapp && cd webapp

ひとまずコレで準備は完了です。

Mojolicious

さて、次は Perl のアプリを書いていきます。

特にこだわりがなければ、 Mojolicious を使っていくと良いと思います。

必要に応じて Perl や Mojolicious をインストールしておいてください。

資料としてはPerl入学式の資料が秀逸です。 Mojolicious については第5回に掲載されています。

Mojolicious のバージョンについては以下のもので動作を確認しています。

1
2
3
4
5
6
7
8
9
10
11
$ mojo version
CORE
Perl (v5.26.1, darwin)
Mojolicious (7.58, Doughnut)

OPTIONAL
EV 4.0+ (4.22)
IO::Socket::Socks 0.64+ (0.74)
IO::Socket::SSL 1.94+ (2.052)
Net::DNS::Native 0.15+ (0.15)
Role::Tiny 2.000001+ (2.000006)

説明を簡単にするためにここでは Mojolicious::Lite の方を使っていきます。

コマンドを使って雛形を作っておきます。

1
$ mojo generate lite_app myapp.pl

とりあえず、これでアプリを書いたことにします。

動作するか確認してみましょう。

1
2
$ morbo myapp.pl
Server available at http://127.0.0.1:3000

この状態でブラウザで http://127.0.0.1:3000 にアクセスして Welcome to the Mojolicious real-time web framework! という画面が表示されれば成功です。

ターミナルに戻って、 ctrl + c でアプリを止めておきます。

手元では Mojolicious が入っているので動作しますが、コンテナには入っていません。

動作に必要な Module は cpanfile に記述しておくことで、コンテナを作成する時に自動的にインストールされるような仕組みをあとで作成します。

なので、 cpanfile という名前のファイルを作成し、必要なモジュールを書いておきます。

今回は簡素化のためコマンドで作ります。

1
$ echo "requires 'Mojolicious';" > cpanfile

一旦、プロジェクトのディレクトリに戻って現在の状態を確認します。

1
2
3
4
5
6
$ cd ..
$ tree .
.
└── webapp
├── cpanfile
└── myapp.pl

Docker

次は Docker で動かせるように Dockerfile を作っていきます。

Docker のインストールなどは完了しているものとします。

資料としては、公式の日本語サイトがあるのでそちらをご覧ください。

Docker のバージョンについては以下のもので動作を確認しています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ docker version
Client:
Version: 17.09.1-ce
API version: 1.32
Go version: go1.8.3
Git commit: 19e2cf6
Built: Thu Dec 7 22:22:25 2017
OS/Arch: darwin/amd64

Server:
Version: 17.09.1-ce
API version: 1.32 (minimum version 1.12)
Go version: go1.8.3
Git commit: 19e2cf6
Built: Thu Dec 7 22:28:28 2017
OS/Arch: linux/amd64
Experimental: true

元になるイメージですが、特にこだわりがなければ公式の Perl のイメージを使うと良いと思います。

タグを指定すると、特定のバージョンの Perl が使用できるのでバージョンを固定するのも簡単です。

ここでは、現在の最新の安定版である 5.26.1 のイメージを使用します。

プロジェクトのルートディレクトリに、以下のような Dockerfile を作成します。

基本的な方針としては、 Carmel を使用してモジュールのインストールを行い、 Mojolicious の機能でアプリサーバーを起動します。

Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FROM perl:5.26.1

RUN useradd -m -s /bin/bash appuser \
&& cpanm Carmel --notest

USER appuser
RUN mkdir -p /home/appuser/webapp
WORKDIR /home/appuser/webapp

COPY --chown=appuser:appuser webapp/cpanfile .
RUN carmel install

COPY --chown=appuser:appuser webapp .

CMD carmel exec -- ./myapp.pl daemon -l http://0.0.0.0:$PORT

WORKDIR の前に RUN mkdir しているのは、 WORKDIR の場合、 root ユーザーで webapp ディレクトリが作成されてしまい、その後の RUN carmel install が失敗してしまうためです。なので、事前に appuser でディレクトリを作成し、そのディレクトリを作業ディレクトリに指定しています。

なお、 root ユーザーで実行しないのはセキュリティの観点からです。やっておいて損はないと思います。

最後の CMD は、 Heroku で動かすための設定です。この挙動は省略時に使用されるので、 docker run の時に実行するコマンドを指定すれば、この行は使用されません。

とはいえ、毎回書くのはだるいので、 docker-compose を使用して手軽に起動できるようにしておくと便利だと思います。

使用するコンテナが一つでも起動が簡単になるので、使えるものは使っていくのが良いと思います。

では、 docker-compose を使用するため、プロジェクトのルートディレクトリに docker-compose.yml を作成します。

docker-compose.yml
1
2
3
4
5
6
7
version: "3"
services:
webapp:
build: .
command: carmel exec -- morbo myapp.pl
ports:
- 3000:3000

動作するか確認してみましょう。

プロジェクトのルートディレクトリにいることを確認して、以下のように実行してください。

なお、実行すると 300MB 以上あるイメージファイルをダウンロードしてくるので、ちゃんとしたネットワーク環境で実行することをオススメします。

1
$ docker-compose up --build

しばらく待っていると以下のような表示が出て画面の動きが止まります。

1
2
Attaching to myproject_webapp_1
webapp_1 | Server available at http://127.0.0.1:3000

Server available at http://127.0.0.1:3000 というのが目印です。

この表示が出たら、またブラウザで http://127.0.0.1:3000 にアクセスしてみてください。

先ほどと同じような画面が出たら成功です。

これで、 Perl の( Mojolicious::Lite で書いた)プログラムが Docker で動作しました。

動作が確認できたら、ターミナルに戻って ctrl + c で Docker を終了しておきましょう。

Heroku

さて、お待たせしました。

いよいよ、 Docker で動いている Perl のプログラムを Heroku で公開しましょう。

まずは、コマンドラインツール( Heroku Toolbelt と呼ばれています)でログインします。

すでにログインしている方は不要です。

Email, Password, (設定している方は)Two-factor code を訊かれるので入力します。

1
$ heroku login

ログインできたら、次はアプリを登録します。

新しく登録するのは簡単です。以下のようにコマンドを入力するだけです。

1
$ heroku create

指定すればアプリの名称も決められますが、後でも変更できるので、まずは確実に作っておくほうが良いと思います。

さて、コンテナを使用する場合、 Container Registry にログインする必要があるようですのでログインします。

1
$ heroku container:login

ログインが出来たら、いよいよデプロイです。

デプロイということは、つまり、コンテナをアップロードするということなので、大きなファイルを送信することになります。くれぐれもネットワーク環境に注意してください。

1
$ heroku container:push web

デプロイが終わったら動作確認をしてみましょう。

コマンドを使用して、アプリの URL をブラウザで開くことが出来ます。

1
$ heroku open

先ほどと同じような画面が出たら成功です。

Perl で作成したアプリを Heroku で公開することが出来ました。

まとめ

Perl でアプリを作って、 Docker で動かしたら Heroku で公開しましょう!

Docker や Heroku はまだまだ進化しています。

仕様がいつ変わるかわかりません。

今のうちに是非お試しください。

明日は

明日は @Morichan さんで「Bio::Perlを使いこなせずに挫折した話」のようです。

明日もお楽しみに!