Perl入学式 2018 in東京 秋開講 第2回 お疲れ様でした
受講された方、サポーターの方、お疲れ様でした。
講師をやったジャージの人です。
スライド中の練習問題と復習問題ですが、今年春に書いた解答例をblogに掲載しています。
参考にしてください。
あと、一緒に掲載してるアナグラくんのスライドも超いいので見て!
sironekotoro.hateblo.jp
fizzbuzz
今回は18時ギリギリまで引っ張ったものの、20分くらい足りず、以下の練習問題にたどり着けず、すみませんでした。
fizzbuzzはぜひ自宅で自習してチャレンジしてみてください。
fizzbuzzができれば、「2007年のコンピュータサイエンス学科卒業生の過半数」より出来る・・・と言えるので!
1から100までの数をプリントするプログラムを書け。ただし3の倍数のときは数の代わりに「Fizz」と、5の倍数のときは「Buzz」とプリントし、3と5両方の倍数の場合には「FizzBuzz」とプリントすること。
ちゃんとしたプログラマであれば、これを実行するプログラムを2分とかからずに紙に書き出せるはずだ。怖い事実を聞きたい? コンピュータサイエンス学科卒業生の過半数にはそれができないのだ。自称上級プログラマが答えを書くのに10-15分もかかっているのを見たこともある。
重要開示
なお、うちは2007年当時、dankogaiさん(Perlハッカー)のblogでこのfizzbuzz問題に言及があり、そこで知ったクチです。
当時はプログラムを書けませんでしたが、日常使っているExcelのセル内に書けるIF関数で書けるだろう・・・って思ったものです。
そんで書けませんでした。
これはショックな出来事で、IT業界の片隅にいながらこれが出来なかったこと・・・簡単と思った課題に歯が立たなかったことに超絶危機感を覚え、真面目に勉強するきっかけの一つになりました。
そんな人でも、諦めなければ講師ができるくらいにはなります。みなさんやっていきましょう。
用意していたスライド
解説用のスライドを用意していたのですが、時間に余裕がなく活用できませんでした。
ここに掲載して供養しておきます。
配列の存在意義
スカラー変数だけではたくさんのデータを扱う時に大変ですが、配列にデータを押し込めることで扱いが楽になります。
もし、スカラー変数しか存在しなかったら・・・?
Q.あるクラスには5人の生徒がいます。この生徒たちの体重の平均を出しなさい。
といった問題が出た場合、スカラー変数しかないと以下のようなスクリプトを書くことになります。
use strict; use warnings; my $abe = 68; my $inoue = 58; my $ueshima = 65; my $edajima = 87; my $ono = 72; my $sum = $abe + $inoue + $ueshima + $edajima + $ono; print $sum / 5; # 70
5人くらいであれば、手書きでいいかもしれません。
でも、もしクラスの生徒が30人だったら・・・?
あなたが市の教育委員会の人間で、市の小学5年生1000人の体重を求める必要が出て来たら?
あなたが厚生労働省の役人で全国の小学5年生の体重を・・・(大体100万人くらいみたい)
スカラー変数を100万個用意するのは避けたい事態です。
また、合計を間違いなく求めたとして、何人の平均であるか?を求める必要もあります。
「何人で割るか」、正確に出せるでしょうか。
5人くらいであれば・・・(以下ループ
そこで配列の出番です
この課題の場合、「誰が何キロ」である、という情報は実は重要ではありません。 単に平均のみを知りたいので、体重の値そのものだけで良いのです。
Perl入学式第2回の内容にあるものだけで書いてみるとこんな感じです。
先頭部で宣言されている@weight
に数値をスペース区切りで追加していくだけで、平均を求めることができます。
楽ですね!
しかも、平均を出すために必要な「何人で割るか」についてもmy $count = scalar @weight;
で自動的に算出してくれます。
超楽ですね!
use strict; use warnings; # 配列@weightに体重を入れる。 # qwショートカットを利用 my @weight = qw( 68 58 65 87 72 ); # 配列の中にいくつの要素が入っているかを求める my $count = scalar @weight; # 合計値を保存するスカラー変数を用意する # 数字を加算していくので、初期値として0を代入しておく my $sum = 0; # for文を利用して、配列@weightの要素を先頭から # 順に取り出し、$sumに加えていく for my $w (@weight) { # $sum = $sum + $w と同じ意味になる書き方 $sum += $w; } # 平均を求める my $average = $sum / $count; print $average; # 70
世の中はデータと制御構造だらけ
プログラムの勉強を始めると、世の中にたくさんのデータと制御構造が溢れていることに気づくようになります。
例えば銀行で考えてみます。
銀行の口座残高は増えたり減ったりします。変数の増減です。
残高が0未満になる引き下ろしをしようとすると、エラーを出します。これはIF文で実現できます。
いつ、いくらの金額を預けたり引き落としした、というデータは時系列で順番に格納されていると思うので(通帳をイメージ)配列のような構造でしょうか。
銀行の口座残高に応じて、ダイレクトメールを発送する、なんとこともあるかもしれません。
それぞれのレベルの顧客リストを得る時には IF〜elsif〜else 文で数値を比較してるでしょう- 預金残高が1億円以上であれば・・・(貧乏なので想像がつかない、外貨預金とか?)
- 預金残高が1000万円以上であれば、マンション購入の住宅ローンのお知らせを発送するリストに載せる
- 預金残高が100万円以上であれば、自動車ローンのお知らせを発送するリストに載せる
- 預金残高が100万円未満であれば、宝くじ発売のお知らせを発送するリストに載せる
身の回りで他の例もいろいろと出てくると思います。
Perl入学式 2018 in東京 秋開講 第2回 ピザ会の課題
恒例となりつつある、ピザ会でのお題です。
時限パスワード貼り付けツールを作ろう!
このピザ回でのお題なのですが、普段自分が書かないプログラムを書くことになり、とても楽しいです。
今回はOSの機能を使うため、PerlからOSの機能を呼び出すsystem
関数を使うのですが、これを実用で使ったのは2回目くらいです。
system関数は「初めてのPerl」にも掲載されているので、知ってはいたのですが、知っていることと使えることはまた違うわけです。
なお、「初めてのPerl 第7版」では15章・プロセス管理のところで出てきます。うむ、見た覚えある。
macOSでしか動かない版ですが、自分の作例です。
一定時間だけパスワードをクリップボードに貼り付け、時間が経過すると元の内容に書き戻す君(OSコマンドインジェクション対応) — Bitbucket
注:OSコマンドインジェクションの脆弱性の指摘があったので、12月24日にその部分を修正してます。勉強になる!
Perl入学式 2018 in東京 秋開講 第3回
ピザ会中にも発表がありましたが、2019年1月19日(土)を予定しています。twitter/web/connpassでの開講のお知らせをお待ちください。
次回は以下の3本立てです
- 配列に要素を加えたり抜いたりする配列操作
- 配列と似ているけども違うデータ構造「ハッシュ」
- 初心者殺しのリファレンス
うちもリファレンスに3回くらい殺されてますが、諦めなければ講師ができるくらいにはなりますので、やっていきましょう!
YAPC::Tokyo 1月26日開催!チケットは今日まで!
そして、2019年1月26日は、あの!YAPC::Tokyo 2019が!開催されます!チケット買えるのは本日12月16日いっぱいです!!
なんと年明け2019年1月6日まで伸びてる!やった!
現役のプログラマー/エンジニア達の取り組みを「生の声」で聞ける貴重な機会です。
うちも毎年楽しみで、2013年から参加しています。
当時はまだリファレンスも理解できない状態でしたが、それでも参加して様々な取り組みや技術のことを聞くことができ、とても楽しかったです。
Perlでこんなことができるかも!って可能性の幅が広がる瞬間がたくさんあります。ぜひ参加ください!
吉祥寺pm #16 で登壇して来た
初登壇でした。
5分の時間をいただいたんですが、オーバーしてしまいました・・・すみません
Googleスライドのツールでちゃんと発表者側に経過時間が表示されていたのですが、緊張して全く時間を見ることができなかったですね・・・
補足
Linuxの勉強はどうやったの?
- 基本的なところはLPIC
- なにから始めればいいか分からなかったので、とりあえず体系的な知識を得るため
- 当時は会社の補助なかった
- 各自で初心者本買ったりVPS借りて色々やる
- 検証機を提供してもらい、素人が存分に実験
CSがシステム(Linux)触って問題はなかったか?
- たくさんあった
- 箇条書きで書きだしたものの、表に出して良いネタかどうかわからないので消す
問題はどうやって回避したの?
- ターミナルソフトのマクロ機能を使い、定型処理を簡易化した
- エンジニアさんに頼み、フールプルーフな仕組みを作ってもらった
- ファイル編集時のフローを整備した
主にどんなコマンド使うの?
発表
マミーさんのお話、登壇へのハードルを下げてくれる内容で良かった。
「カラオケボックス借りて一人登壇発表練習」ってのはいいなぁ、と。
あと、エンジニアさんが古代の会社に行ったという話が良かった・・・。
SIerが旅館に勤めてその旅館がすごくなった、ってな話を思い出しました。
まさかのRPGツクールを使っての起業プロセスの発表、ああいう方法もあるのか!と
#kichijojipm 起業クエストww pic.twitter.com/mUhow0FKpO
— teckl (@teckl) November 22, 2018
つっちーさんのプロキシサーバをPerlで作るというお話。
うちだったら、Squid立てて設定して、それでおしまいにするところを、Perlでやってみるという方法があるのか!と当たり前のことに衝撃
ほんと、吉祥寺pm面白かったです。
Perl入学式 2018 in東京 秋開講 第1回 落穂ひろい
msys2・ターミナル(黒い画面)編
スライドの入力例の先頭にある $
マーク
この $
は一般ユーザー権限でコマンド入力待ちになっていることを示すものです。
UNIXやLinuxには権限といった考え方があり、一般ユーザーとスーパーユーザー(管理者,root)とで実行できるコマンドに差があります。
書籍やスライドにある先頭の $
は入力する必要はないです(というか、手元のターミナルに既に表示されているはず
スーパーユーザーの場合には、先頭に #
と表示されます。
whoami
はユーザー名を表示するコマンド、su -
は一般ユーザーから管理者ユーザーになる時のコマンドです。
先頭の $
が #
に変わっています。
以前に入力したコマンドをもう一度使いたい
キーボードの ↑
↓
キーを押すことで、過去に入力したコマンドが出てきます。
長いファイル名を入力するのが大変
キーボードの TAB キーを押すことで、ファイル名が補完されます。
長いファイル名のファイルを作成し、それを削除する時に先頭のファイル名先頭の a
のみを入力してTABキーでそれ以降を保管しています。
ターミナルの画面が入力した文字や、実行結果で埋まってきた・・・
clear
コマンドで画面がきれいになります。
CUIは寡黙
コマンドが成功した場合には特に応答を返さないことが多いです。
エラー時にはエラーメッセージを表示します。
OSの歴史編
プログラミング言語の系統図
Plotter ってのをクリックすると一枚のPDFで表示されます。重いので注意。
Perlは1987年に誕生しています。
書籍だと、この本が簡潔にまとまってて良いです。もちろんPerlも載ってます!
詳説! Hello world
!/usr/bin/env perl use strict; use warnings; print "Hello world!";
1行目:#!/usr/bin/env perl
いきなりわかんないですよね・・・ということで定番書籍にご登場願います。
#!/usr/bin/perl
(中略)Unixシステムでは、テキストファイルの最初の2文字が
#!
(shebang:シバンまたはシェバンと発音します)だったら、その後ろに続くものが、ファイルの残りの部分を実際に実行するプログラムの名前になります。このケースでは、そのプログラムはusr/bin/perl
に格納されています。はじめてのPerl 第7版 電子版 14p
この上記の例だと、「このファイルは /usr/bin/perl
で実行してくださいねー」とシステム(Unix)に伝える行、と思ってください。
ですので、この行を適当に書き換えると、Unixはどのプログラムで実行して良いか分からず、エラーになったり異なる応答をします。
macOSで実行してみました。
- 1行目を存在しないプログラム名(SuperDuperMiracleLanguage)にした場合
#!/usr/bin/SuperDuperMiracleLanguage
$ perl hello.pl Can't exec SuperDuperMiracleLanguage at hello.pl line 1.
そんなプログラム無いから実行できないよ、とエラーが出ます。
- 1行目を別のプログラム言語にした場合
#!/usr/bin/ruby
$ perl hello.pl hello.pl:2:in `<main>': undefined local variable or method `strict' for main:Object (NameError)
rubyとしてファイルを実行したけど、rubyが2行目の use strict
の解釈でエラー、と出ます。
では/usr/bin/env perl って?
再度定番書籍にご登場願います。
Unixシステムの中には、
#!
行に次のように書くと、perlを探してくれるものもあります。#! /usr/bin/env perl
はじめてのPerl 第7版 電子版 14p
ということで、Unix環境の中からPerlを探してくれることを期待して書く行なのでした。
2行目:use strict;
厳密な書式を定めたり, 未定義の変数を警告するといった効果があります
変数については第2回でやるので、そこで説明します。
3行目:use warnings;
望ましくない記述を警告してくれる効果があります。
例えば、use warnings
の無い、このようなプログラムで実験してみます。
#!/usr/bin/env perl use strict; print;
実行します。
$ perl hello.pl $
エラーは出ません。
print
文ですが、なにをprint、表示するのかの指定が無いプログラムです。
しかし、これは正しいprint文でしょうか?何も表示しないなら、不要な行なのでは?
こういったあやしい記述を警告してくれるのが use warnings
です。
#!/usr/bin/env perl use strict; use warnings; print;
実行します。
$ perl hello.pl Use of uninitialized value $_ in print at hello.pl line 5.
エラーが出ます。
エラーの内容は「未定義の暗黙の変数使ったな!」ってやつなのですが、「エラーが出たんでどっか直さないとダメなんだな」くらいでokです。
4行目:(空白行)
Perlでは空白文字であるスペースやタブは無視されます。
そのため、これらの空白文字を使ってプログラムを読みやすくすることができます。
5行目:print "Hello world"
・・・古来、というか1989年の「プログラミング言語C 第2版(訳書訂正版)によるとこうです。
ちなみに、すごい驚いたんですが、Perlちょっとやってると、Cのプログラムが読めます。書けないけど。びっくり。
練習問題(1), 練習問題(2)
TMTOWTDIのモットー通り、いろいろな書き方があります。
- 普通の書き方
print "Perl-Entrance\n"; print "2018/10/27\n"; print "Gotanda\n"; print "Tokyo\n";
- 1行で書いてみる
print "Perl-Entrance\n2018/10/27\nGotanda\nTokyo\n";
- 偏屈な書き方
print "Per"; print "l-Entrance\n20"; print "18/10/27\nGot"; print "anda\nTokyo\n";
上記3つとも同じ出力になります。
- 練習問題(2)の引き算
print 2018 - 1987;
- 練習問題(1)と練習問題(2)の引き算も含めて1行で・・・ってのは第1回の範囲では無理かなー?
第2回でやる文字列連結演算子.
(ドット) と計算部分をカッコで囲む方法を使います。
print "Perl-Entrance\n2018/10/27\nGotanda\nTokyo\n" . (2018 - 1987) . "\n";
Perl入学式 2018 in東京 秋開講 第1回 お疲れ様でした
Perl入学式 2018 in東京 秋開講 第1回
受講された方、サポーターの方、お疲れ様でした。
講師をやったジャージの人です。
今期からの新要素は以下となります。
不慣れなところが多く、お手数をおかけしました。
今回ですが、Perlの学習内容としては print "Hello! World";
のみなので特に復習問題はないです。
また来月お会いしましょう!
Perl入学式 2018 in東京 秋開講 第1回 ピザ会の課題
Perl入学式 in東京 では講義終了後、希望者で集まりピザ会と称した懇親会を行っています。
(ジュース・ピザ代は実費)
昨年からそこで余興として xtetsuji さんが課題を出し、そこにチャレンジャーが回答して公開する、というようなことをやってます。
今回の出題は、シミュレーションでした。
過去の出題傾向からてっきりWebからスクレイピングってネタが来ると思ってたので完全に不意打ち。
ルール
- プレイヤーA、プレイヤーBに手札が3枚配られる
- 今回は配られる手札は固定
- プレイヤーA:1, 5, 10
- プレイヤーB:2, 2, 2
- 1 〜 40 の目がランダムに出るルーレットを3回まわし、手札と同じ数字が出たら手札を捨てる
- プレイヤーBのように同じ手札が複数枚ある場合には、同じ目が出ても捨てられるカードは1枚だけ
- 先にカードがなくなった方が勝ち
ヒント
- 1 〜 40 のランダムな数字を出すには
int( rand(40) + 1 )
を使う
うちの予想
- 3枚のカードが来て、ルーレットも3回まわすんだから、プレイヤーAもプレイヤーBも勝率は同じなのではないか?
コード
ピザ会で書いたものを少し改変して、コメントを入れてアップしています。
Perl入学式でやる範囲の内容のみ、かつリファレンスを使わない、という縛りで書いてみました。
結果、めっちゃ煩雑になりましたわ・・・
Perl入学式 2018 in東京 秋開講 第1回 ピザ会でのお題 — Bitbucket
なお、コードを実行すると勝利回数は6〜7倍プレイヤー1の方が高いですが、これは確率的に正しいとのこと。
うちはサイコロに置き換えて考えて納得した気になってるけど、正しいかどうか不安・・・
昨日の #Perl入学式 in東京 ピザ会のお題を解き直してたけど、サイコロに置き換えてやっとわかった。
— sironekotoro (@sironekotoro) 2018年10月28日
同じ目が3回連続で出る(2,2,2)のと、3つの異なる数字(1,3,5)が順不同で出るのでは確率が違う
サイコロに置き換えると
- プレイヤーAの手札(1, 3, 5)
- 出た目が 1, 3, 5 どれかに合致すれば札を捨てられる
- 最初に 1 が来ても 3 が来ても 5 が来ても手札を捨てることができる
- 3/6 * 2/6 * 1/6 = 6/216
- 出た目が 1, 3, 5 どれかに合致すれば札を捨てられる
- プレイヤーBの手札(2, 2, 2)
- 3回とも同じ目が出なくてはいけない
- 1/6 * 1/6 * 1/6 = 1/216
これで約6倍の差、って言ってたのもわかる気がする・・・合ってるかな?
そういえば
Perl入学式 第5回の作例をDockerにした & オススメ本 #マンガでわかるDocker
Perl入学式 第5回の作例をDockerにした
これの一番最後に自分で書いた宿題の回収です。
Mojoliciousアプリをお手軽セキュアに展開する方法も探していかんとなぁ
一つの回答として、Dockerイメージを用意しました。
https://hub.docker.com/r/sironekotoro/bbs_custom/
本当はどこかwebにあげて、そこで好きに触ってもらおうかなぁ、とも思ったんですが、なんせ掲示板アプリなので脅迫とか殺人予告が書き込まれないとも限らない・・・ので、Dockerイメージにしてみました。
dockerコマンドが動くなら以下の2行でokのはず。
$ docker pull sironekotoro/bbs_custom
$ docker run --rm -p 3000:3000 --name bbs_custom -e PORT=3000 sironekotoro/bbs_custom
このあと、ブラウザで http://localhost:3000
を開くと掲示板が開きます。
ソースはこちらです。
sironekotoro / bbs_custom / source / — Bitbucket
Perl の Web Application Framework である Mojolicious のバージョンが上がったので、前回から少し手直しをしています。
ナマナマしい JavaScript のところを Vue で書き換えるって目標もあるんですが、全然進んでない。
オススメ本 #マンガでわかるDocker
Dockerイメージを自分で作ってあげてみよう!ってモチベーションになったのは通称「わかばちゃん本」2巻でした。
本当にオススメです。
うちは bitbucket と Docker Hub を連携させましたが、手元で git push
したのがスルスルと Docker Hub に上がった時は感動しました。
( git も「わかばちゃん本」にお世話になったんだった)
とにかく、この本でハードル低くしといて「あれはどうやるんだろ、こういう風にやってみたい!」ってな欲望が出てきたら、一般書店で最近出た Docker 本を購入して勉強するのがいいんじゃないかなぁと思います。
第1巻出てから自習してたから復習気分で読めたんだけど、どうも自習に使った本が古かったらしくコマンドが新しくてシュトロハイムのようにうろたえる / #マンガでわかるDocker ② 〜開発環境を作ろう編〜 ダウンロード版 #技術書典 5 | 湊川あいの、わかば家。 https://t.co/dsczG7uVF3 #booth_pm
— sironekotoro (@sironekotoro) October 11, 2018
Docker実践活用ガイド Chapter 10 DockerとJavaScriptでウェブサービスを作る(簡易オンラインジャッジシステム)
ずっと気になっていたDockerなのですが、本屋で見かけてこれなら(うちみたいな初級者でも)理解できそう、ということで購入。
厚みはある本なのですが256pとIT技術書にしては少なめ。
細かい仕様よりも、とりあえず動かしてみよう!ってところが気に入りました。
AmazonのKindle Unlimited対象なのも良い。
- 作者: 吉岡恒夫
- 出版社/メーカー: マイナビ出版
- 発売日: 2016/05/30
- メディア: Kindle版
- この商品を含むブログを見る
すでに業務とかで触っている人向けではないですね。
この本を参考書にハンズオン形式とかやるといいかもしれないなぁ、と思いましたわ。
蒙が啓かれる
うちはDockerを「本番環境をそのまま手元に再現できる、開発環境のツール」としか思ってなかったんですね。
でも、この本に掲載されている「任意のコードをDocker環境上で動かし、その結果をホストに持ってくる」ってのに衝撃を受けましたわ。
それってつまり、普通のソフトと同じように使えるということ。すごい。
2つの不満点・・・
Chapter 8 「複数のDocker を使う(Docker MAchine, Docker Swarm, Docker Compose)」
最後のDocker Composeで docker-compose scale web=3
でスケールアップできなかったこと。
前節のDocker Swarm のところから続けて試してたんだけど、暗黙の何かの前提条件があったのか、うちの見落としか、スケールアップすることができず。
動かせなかったDocker Composeは次のDocker本で改めて学習するつもり。
コードがWeb上にない!
目gerpで目を酷使してつらい。
そんで、いまからこの2016年の本を読む人がいるかどうかはともかく、うちはきっと戻ってくるだろう、ってことで10章のコードを載っけときます。
Docker実践活用ガイド Chapter 10 DockerとJavaScriptでウェブサービスを作る(簡易オンラインジャッジシステム) — Bitbucket
本に書いてあるものを少し拡張して、Perlのコードも試せるようにしています。Perl好きなんだもん仕方ないね。
Perl追加したことと、エディタの自動整形の影響で、本に掲載されている行数と異なってますのでご注意を(主に将来の自分へ)
お手軽に動かしてみたい!という将来の自分へ
環境
macOS 10.12.6
Docker for Mac で実行
$ docker version Client: Version: 18.06.1-ce API version: 1.38 Go version: go1.10.3 Git commit: e68fc7a Built: Tue Aug 21 17:21:31 2018 OS/Arch: darwin/amd64 Experimental: false Server: Engine: Version: 18.06.1-ce API version: 1.38 (minimum version 1.12) Go version: go1.10.3 Git commit: e68fc7a Built: Tue Aug 21 17:29:02 2018 OS/Arch: linux/amd64 Experimental: true
準備
コード実行環境用コンテナを用意する
# イメージ作成時に ubuntu-devの名前をつける # docker build -t ubuntu-dev . FROM ubuntu RUN apt-get update RUN apt-get install -y perl RUN apt-get install -y ruby RUN apt-get install -y python RUN apt-get install -y clang RUN apt-get install -y time RUN apt-get install -y binutils
コード実行環境のフロントエンド用コンテナをDocker Hubから持ってくる
https://hub.docker.com/u/sironekotoro/
docker pull sironekotoro/code-runner
イメージサイズはこんな感じ。大きい
docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu-dev latest 5cbc5fafea4f 17 minutes ago 674MB sironekotoro/code-runner latest 73722453f41f About an hour ago 678MB
起動
docker run -v /usr/local/bin/docker:/usr/local/bin/docker -v /var/run/docker.sock:/var/run/docker.sock -p 3000:3000 --rm sironekotoro/code-runner
http://localhost:3000
にブラウザでアクセスする
遊ぶ
写経大変だった。あとでbitbucketにあげとこ・・・でもこれDockerだから上げるんならDockerHubの方がいいんかな pic.twitter.com/1cQwHyEuym
— sironekotoro (@sironekotoro) October 7, 2018
後片付け
docker stop $(docker ps -a -q)
docker rmi ubuntu-dev sironekotoro/code-runner
Mojolicious::Liteで作ったWebアプリをDockerに入れてHerokuで動かす
昔語り
書いてたら止まらなくなってしまったので全部カット
参考・影響を受けた記事&スライド
環境
- macOS 10.12.6
heroku CLI(https://devcenter.heroku.com/articles/heroku-cli)
$ heroku -v heroku/7.14.2 darwin-x64 node-v10.9.0
Docker for Mac(https://store.docker.com/editions/community/docker-ce-desktop-mac)
$ docker version Client: Version: 18.06.1-ce API version: 1.38 Go version: go1.10.3 Git commit: e68fc7a Built: Tue Aug 21 17:21:31 2018 OS/Arch: darwin/amd64 Experimental: false Server: Engine: Version: 18.06.1-ce API version: 1.38 (minimum version 1.12) Go version: go1.10.3 Git commit: e68fc7a Built: Tue Aug 21 17:29:02 2018 OS/Arch: linux/amd64 Experimental: true
-
$ perl -v | grep This This is perl 5, version 28, subversion 0 (v5.28.0) built for darwin-2level
cpanm
,Mojolicious
についてはLocal::Lib
を利用せず、普通にインストールしてますcpanm
$ cpanm --version | head -1 cpanm (App::cpanminus) version 1.7044 (/Users/sironekotoro/.plenv/versions/5.28.0/bin/cpanm)
mojolicious
$ mojo version CORE Perl (v5.28.0, darwin) Mojolicious (7.94, Doughnut) OPTIONAL Cpanel::JSON::XS 4.04+ (4.04) EV 4.0+ (n/a) IO::Socket::Socks 0.64+ (n/a) IO::Socket::SSL 2.009+ (2.056) Net::DNS::Native 0.15+ (n/a) Role::Tiny 2.000001+ (2.000006) This version is up to date, have fun!
macOSにtreeコマンドなかったんで急遽入れたtree
brew install tree
作成手順
Mojolicious::Liteを利用したWebアプリを作る(Perl入学式の範囲)
今回の作業場所になるフォルダを作成します
$ mkdir heroku
フォルダの中に移動します
$ cd heroku/
Dockerfileを作成します(作成だけ)
$ touch Dockerfile
Webアプリ用のフォルダを作成します
$ mkdir webapp/
ここまでのフォルダ構成です。
Dockerfile
はファイル、webapp
はフォルダです$ tree . ├── Dockerfile └── webapp 1 directory, 1 file
Webアプリ用のフォルダに移動します
$ cd webapp/
Mojolicious::Liteの雛形を作成します。
myapp.pl
ファイルが作成され、実行権限がつきます$ mojo generate lite_app
この時点で一度Webアプリを起動して確認しておきます
$ morbo -l http://*:3000 myapp.pl
ブラウザで
http://localhost:3000
にアクセスし、いつものMojoliciousの画面が出るかどうか確認しますターミナルを
Ctrl + c
で抜けます1つ上の階層に戻ります
$ cd ../
この時点でのフォルダ構成です
$ tree . ├── Dockerfile └── webapp └── myapp.pl 1 directory, 2 files
Dockerイメージの中に、先ほど作ったWebアプリを入れる
Dockerfileを下記の内容で編集します
# ベースイメージ FROM perl:5.28 # Mojolicious::Liteのインストール RUN cpanm Mojolicious::Lite # Dockerイメージ内にウェブアプリケーション用のフォルダを用意して移動 WORKDIR webapp/ # ホストのwebapp/myapp.plをDockerイメージ内の現在位置(webapp/)にコピー # 行末にあるドット . に注意 COPY webapp/myapp.pl . # Mojoliciousを起動 CMD morbo -l http://*:3000 myapp.pl
Dockerfileを元にDockerイメージをbuildします
最後の.
を忘れないように$ docker build -t mojolicious -f Dockerfile .
Dockerイメージが作成されたか確認します
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE mojolicious latest 9241214e107f About a minute ago 902MB perl 5.28 c58a7ea6dfc4 28 hours ago 885MB
DockerイメージからDockerコンテナを起動します
オプションにより、コンテナは実行後破棄されます。また、ホストのポート3000番とDockerコンテナのポート3000番を結びつけ、コンテナにはmojoという名前をつけています$ docker run --rm -i -t -p 3000:3000 --name mojo mojolicious
ブラウザで
http://localhost:3000
へアクセスし、いつもの画面が出ることを確認しますこの時点で実行中のコンテナに入る場合には、別途ターミナルを立ち上げて以下のコマンドを入力します
$ docker exec -it mojo bash
コンテナから抜けるには
exit
コマンドで抜けます
ブラウザでの確認が終わったら
Ctrl + c
で終了します
Herokuに先ほど作ったDockerイメージをアップする
Dockerfileの最後の行であるCMD行を修正します
# Mojoliciousを起動 # Herokuではポート番号の指定ができない。3000 を $PORT に書き換える CMD morbo -l http://*:$PORT myapp.pl
Herokuにログインします
heroku login heroku: Enter your login credentials Email:heroku-test@sironekotoro.com Password: ************************** Logged in as heroku-test@sironekotoro.com
Heroku上でwebアプリ用のスペースを用意します
⬢ 以降の文字列がアプリ名、その下の行がアプリ用のURLとgitのリモートリポジトリです$ heroku create Creating app... done, ⬢ floating-hamlet-68207 https://floating-hamlet-68207.herokuapp.com/ | https://git.heroku.com/floating-hamlet-68207.git
先ほど用意されたURLにブラウザでアクセスして画面を確認します
ターミナルに戻り、HerokuのContainer Registryにログインします
$ heroku container:login Login Succeeded
HerokuのContainer RegistryにDockerイメージをpushします。
-a
の後のアプリ名はheroku create
で発行されたものを利用します$ heroku container:push web -a floating-hamlet-68207 === Building web (/Users/sironekotoro/Desktop/heroku/Dockerfile) (以下略)[f:id:sironekotoro:20180909150557p:plain] latest: digest: sha256:08cc85e39e5ab8a6faf0653737d5e9fa658935faab9c30df13f5d3653a327423 size: 2632 Your image has been successfully pushed. You can now release it with the 'container:release' command.
Heroku上でwebアプリをリリースします
$ heroku container:release web -a floating-hamlet-68207 Releasing images web to floating-hamlet-68207... done
ブラウザでアプリのURL(この例では https://floating-hamlet-68207.herokuapp.com/ )を入力し、アクセスします。なお、初回の表示は少し時間がかかるようです
表示を確かめてニヤリとします
後片付け
アプリに割り当てられているwebのプロセスを0にします
$ heroku ps:scale web=0 -a floating-hamlet-68207 Scaling dynos... done, now running web at 0:Free
この時点でWeb上ではエラーが表示されます
Herokuで作成したアプリを削除します
本当に消して良いのか再確認を求められるので、アプリ名を入力します$ heroku apps:destoroy floating-hamlet-68207 ▸ WARNING: This will delete ⬢ floating-hamlet-68207 including all add-ons. ▸ To proceed, type floating-hamlet-68207 or re-run this command with ▸ --confirm floating-hamlet-68207 > floating-hamlet-68207
Herokuからログアウトします
$ heroku logout Logging out... done
Dockerイメージを削除する場合には、
docker images
を利用してIMAGE ID
を確認します
表示が見切れていると思うので、右側にスクロールしてください$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE registry.heroku.com/floating-hamlet-68207/web latest 282624a4c7c5 11 minutes ago 891MB mojolicious latest 60486db357d4 23 minutes ago 891MB perl 5.28 c58a7ea6dfc4 4 days ago 885MB
確認した
IMAGE ID
を引数にしてdocker rmi
コマンドを実行します
なお、Perlのイメージファイルは大きいので、今後もPerlを利用したコンテナを作る場合には残しておいた方がよいでしょう$ docker rmi 282624a4c7c5 60486db357d4 Untagged: registry.heroku.com/floating-hamlet-68207/web:latest Untagged: registry.heroku.com/floating-hamlet-68207/web@sha256:406a6002c3657824f5e79689c7d4b9083ec50cf64c16c9c5764d451a5567c6dc Deleted: sha256:282624a4c7c58dd90c385eb3e1607275bda542db1d278bc3c3c0687846a26ad0 Untagged: mojolicious:latest (中略) Deleted: sha256:c42cc493a9c425ca897aaac856b3ae547840b28d34678d19aefcca98b759599e