集中力が10分しか持たないハチワレ先生

集中力が10分しか持たないハチワレ先生

技術メインの雑記ブログ

AWS でサーバレスな寮飯確認 Bot を作った話

こんにちわ、krkettleです
今回は AWS で寮飯確認 Bot を作った、そしてサポートを終了した話を書きたいと思います

背景

私は社員寮在住なのですが、ありがたいことに
夕食は寮で提供されます(代金は取られますが良心的だと思います)
ある日の夜、同期と寮食を食べようとした時に同期がポツリ

「うわー、今日の夕食カレーか!昼に食べちゃったよ」

寮では食堂の掲示板にその週の献立が掲示されるのですが
毎週献立を撮っておくのは面倒なものです...

そこで、当時私が AWS ソリューションアーキテクトの資格を取ろうと
思っていたこともあり、練習も兼ねて寮生の悩みを解決することにしました
(AWS SAA に合格できました!)

krkettle.hatenablog.com

AWS 構成

家賃が安いが売りの社員寮に住む寮生から、なけなしのお金を取るわけにはいきません
そこで以下のコンセプトで構成を考えることにしました

  • 出来る限り安く(出来れば無料で)
  • 運用コストをできる限り抑える
  • 最小構成でまず動くものを

全体構成図は以下の通りです

AWS全体構成図
AWS全体構成図

寮飯確認 Bot のフロー

  1. 利用者は事前に LINE の寮飯確認 Bot チャンネルに登録
  2. 運営者が寮飯の献立画像を撮影し S3 にアップロード
  3. 寮食が提供される曜日の 11:30 に献立画像を寮飯確認 Bot に送信

画像アップロード

当初の予定では下図のように S3 への画像アップロードもシステム化する予定でした
(覚えたての React と S3 の静的ホスティングを使って Web アプリっぽく)

当初のAWS全体構成図
当初のAWS全体構成図

しかし、コア要素でないところに時間を掛けたくないのと
「最小構成でまず動くものを」というコンセプトから外れるため後回しにして
まずは手動で AWS コンソールから運営者(私のみ)がアップロードすることにしました

メッセージ送信

今回は無料のLINE Messaging APIを利用しました
この API では Push/Reply が可能ですが、今回は Push(Bot 側から送信する)だけを採用しました
その理由は以下の 2 点です

  • 無料枠では送信可能なメッセージ数が固定なので、無駄な返信で消費しないようにするため
  • 返信のたびに Lambda が起動するとお金がかかってしまうため

CloudWatch Eventsを使って指定の時間にLambdaが起動します
Lambda は S3 にアップロードした画像を Messaging API 経由で寮飯確認 Bot チャンネルに送信します

認証情報の管理

LINE Messaging API ではアクセストークンを発行する必要があるため
認証情報の管理が必須になりますが、AWS では認証情報の管理として以下の2つが有名です

全体構成図でも書いているように、選んだのはパラメータストアです
理由は機能・非機能的に問題がなく無料だからです

両者の比較は以下の記事が参考になりました
参考: AWS の Parameter Store と Secrets Manager、結局どちらを使えばいいのか?比較

監視・通知

寮生に閉じられた完全無料なシステムとはいえ、
「ダウンしたら利用者から連絡がくるまで放置」というのは忍びないので
CloudWatch, Chatbotで監視・通知機能をつけました
仕組みは単純で Lambda で例外が発生したら管理者の Slack に通知します

S3 の署名付き URL でハマる

AWS は非常に使いやすくドキュメントも豊富なので
設計を含め全部で 3 時間ほどで最低限の機能が動くところまで出来ました
ただ S3 の署名付き URLで少しハマりました

なぜ署名付き URL を使ったのか

理由としては以下の通りです

  • アップロード画像に有効期限をつけたかった
    • 献立は毎週変わるので古い画像はアクセスされないようにしたかった
  • S3 バケットを非公開にしたかった
    • 誤って S3 から直接画像をダウンロードされないようにするため
    • 今から考えるとそれほど必要なかったかも
  • (AWS SAA の試験対策時に知って使ってみたかったから)

発行者の認証情報に応じて署名付き URL の長さが変わる

今回署名付き URL は IAM ロールを付与した Lambda で発行しました
しかし以下の参考記事にある通り、IAM ロールを用いて署名付き URL を発行する場合
一時的な認証情報を用いるため、その情報を URL に含める必要があります
そのため、IAM ユーザを用いる場合よりも IAM ロールを用いる場合は URL が長くなります

署名付き URL が長いと何が問題なのか

通常であれば URL が長いのはそれほど問題にはならないはず(?)
しかし今回はLINE Messaging API の仕様に落とし穴がありました...

Image URL (Max character limit: 1000)

URL の最大長が1000に設定されていたんですね
(私の使い方がイレギュラーだと思うので、この仕様が悪いわけではないと思います)
これが原因となり Lambda でメッセージ通知時に例外が発生していました

どう解決したか

スマートなやり方ではないと思うのですが
Bitly APIを利用して署名付き URL の短縮 URL を発行して回避しました

今考えると

  • そこまでして署名付き URL を使う必要はなかった
  • 公開用の S3 バケットを用意して削除イベントを作るでもよかった
  • 使ったことない技術使ってみたい気持ちが先行した感がある

本番環境と同じ環境で行うテストが大事

このハマり点のタチの悪いところはLambda で実行してみて初めて気づくという点です
自動テスト、CI/CD の設定は全く出来ていなかったので、ソースコードのチェックには
実行環境をローカルに Docker 環境で作って検証していました

krkettle.hatenablog.com

しかしローカル環境では IAM ユーザの認証情報を使用していため正常終了していました
よく言われることですが、本番環境とテスト環境は同じにしておくことが大事だなと実感しました

サービス開始、そしてサービス終了まで

晴れてサービス開始となりましたが、その数ヶ月後に終わりを迎えることとなりました

サービス開始

ハマりポイントはあったものの、AWS 様様で最低限動くサービスがサクッと完成しました

寮生の同期何人かに寮飯確認 Bot のアカウントを伝え利用してもらいました
「こんなの個人で作れるんだ」「すごいね!」という感想が嬉しかったです

拡張を考える

運用しているうちに利用者の同期からこんなコメントが

  • 画像だけだとつまらないから、何か追加で配信してよ
  • 献立の画像は 1 週間分の物が送られてくるけど、その日の分だけ切り出してよ

完全無料のアプリとはいえ、ありがたいご意見には応えたくなります

文章も送ってみる

1 つ目の要望は簡単に対応できました
今まで画像しか配信していませんでしたが当然文章も配信可能です
毎日労いの言葉を添えるようにアップデートしました

献立の画像を切り出す

2 つ目の要求には画像処理が必要になります
学部時代の記憶を掘り起こしOpenCVなどでゴニョゴニョしましたが
実用に耐えうるものは出来ず、これに関しては一旦断念しました

自動化したい気持ちが強くなる

ソースコードを変更するたびに zip で固めて Lambda にアップロードするのは
流石に面倒だし署名付き URL の件もあったので自動化したい気持ちが強くなりました

丁度その頃 Udemy でAWS Code シリーズの講座を受講していたこともあり
Serverless Framework, AWS CDKあたりで CI/CD 環境作ろうと思っていました

サービス終了

思い描いていた拡張は叶うことなく、サービスは突如終わりを迎えます
理由としては「業務が忙しくなってきた」という月並みな言い訳もありますが
最大の理由は献立撮影&S3 へのアップロードが面倒だったからです

技術に関することであればたとえ無料でも頑張れたのですが、
「毎週写真を撮って、S3 に上げる」という単純な作業が面倒になってしまったのです...

怠惰

これが最大の理由となり、サービスは数ヶ月の歴史に幕を閉じました

サービスを振り返って

終焉はあっけなかったですが結果ローコスト・ハイリターンだったと思います

よかった点

  1. AWS の使った開発ができた
  2. AWS 利用料が無料枠の範囲内でサービスを運営できた
  3. 同期の何人かに実際にサービスを利用してもらえた

反省点

  1. モチベーションの維持方法を考えるべきだった
    • 募金という形式でも利用料を取れば義務感が生じたかも
    • 一人で運営せずに運営側に仲間を巻き込めばサボらなかったかも
  2. せめて自動テストまではやり切りたかった

プロダクト開発してみると色々学べるのは分かってるんだけど、最初の一歩がなかなか出んのよね...

10 分で入門する SSH(概念編)

AWS などを使う上で利用する機会の多い SSH の概要を暗号技術の基礎を踏まえて紹介します

この記事を読んで分かること

前提条件

対象者

  • SSH を使った事がなく、これから使おうと思っている方
  • SSH を使っているけど、最低限の仕組みは抑えておきたい方

この記事で紹介しないこと

  • 具体的な SSH のコマンドや設定
  • SSH を使う上で最低限必要なものではないと筆者が判断したもの

SSH についての基礎知識

以下の 2 点についてこの章で紹介します

  • SSH とは何か?
  • SSH を使うと何が嬉しいの?

SSH とは何か?

ざっくり言うとリモートマシンに安全にアクセスする仕組みです
暗号技術を活用して通信を暗号化し、安全に通信を行うために利用できます

SSH を使うと何が嬉しいの?

そのままですがリモートマシンに安全に接続できることが利点です
ただ、分かりにくいので具体例を挙げて説明してみます

SSH している場合としていない場合の比較

A さんは自宅のノート PC から大学の研究室にあるサーバにアクセスしたいと考えています
しかし、大事な研究情報を悪意のある人に盗聴されてしまう可能性があります
そこで SSH を利用する事で盗聴の心配なく、安全に通信ができました

(最近の研究室はサーバじゃなくてクラウドインスタンスとかなのかな...?)

どうやって安全に通信するの?

安全に通信を行うには暗号化通信を行います

  • 暗号化: 通信内容を他人にわからないように加工します
  • 復号: 暗号化された通信内容を元の状態に戻します
    • ※復号であり、復号ではないので注意

具体例としてシーザー暗号を挙げてみます
シーザ暗号とは「文字を辞書順で N 文字分ずらす」暗号です

N = 2 の時 A → C, B → D になります
事前に N の値を通信相手と合意しておけば暗号化通信が可能です
「N」を暗号における、暗号化される前のデータを平文(ひらぶん)と呼ぶ

N = 2のシーザー暗号
N = 2のシーザー暗号

※シーザ暗号は簡単な暗号の一例として挙げましたが
SSH に使われている訳ではないのでご注意ください

認証ってどうするの?

暗号化通信によって盗聴を防ぐことは分かりましたが
どうやって正規の通信相手かを見分けるのでしょうか → この答えが認証です

通信相手が誰であるかを確認することを認証と言います
(ちなみによく混同されますが、認証認可は異なります)

参考: よくわかる認証と認可

SSH にはどんな認証の種類があるの?

SSH では主に以下の 2 つの認証があります

  • パスワード認証方式
  • 公開鍵認証方式

パスワード認証方式は、リモートマシンのユーザ名とパスワードによる認証です
ただし後述の公開鍵認証方式と比べるとセキュリティが低いので注意が必要です

公開鍵暗号電子署名

この章では公開鍵暗号電子署名について紹介します
どちらも後述の公開鍵・秘密鍵を用いますが、暗号と署名は別物なので注意してください

参考: 「電子署名=『秘密鍵で暗号化』」という良くある誤解の話

公開鍵暗号

公開鍵暗号とは公開鍵・秘密鍵を用いた暗号方式のことです
公開鍵と秘密鍵は対になっており、二つ合わせてキーペアと呼ばれます

  • 公開鍵
    • 他人に公開して良い
    • GitHub 等を利用する際にも登録することがあります
    • 暗号化に用いる
  • 秘密鍵
    • 絶対に公開してはいけない鍵です
    • 盗まれると「なりすまし」されてしまう危険があります
    • 復号に用いる
  • 暗号化&復号
    • 送り主は受け取り主の公開鍵で暗号化し、受け取り主は自分の秘密鍵で復号する
    • 公開鍵を使って誰でも暗号化できる
    • 復号できるのは秘密鍵を持つ本人だけ

公開鍵暗号
公開鍵暗号

電子署名

データに署名する事で、本人確認やデータの改竄検出を行う事が出来ます
署名には秘密鍵を、署名の検証には公開鍵を使います

ポイントは以下の通りです

  • 秘密鍵を持つ本人しか署名が出来ない
  • 署名の検証は公開鍵を使うため誰でも出来る
  • 署名対象のデータをハッシュ化した値(ハッシュ値)から電子署名を作成する
  • ※署名と共に元のデータが送られるため、ハッシュ化の方法が合意されていればハッシュ値は計算できる(検証できる)

電子署名を用いた認証を公開鍵認証と呼びます

参考: 暗号学的ハッシュ関数(Cryptographic Hash Function)

電子署名
電子署名

共通鍵暗号との違い

前述のシーザ暗号のように暗号化・復号に同じ鍵を使う暗号方式のことを共通鍵暗号と呼びます
(これに対して公開鍵暗号のことを非対称鍵暗号とも呼んだりします)

共通鍵暗号公開鍵暗号の違いは以下の通りです

共通鍵暗号 公開鍵暗号
認証範囲 真正性 真正性・否認防止
鍵管理 大変 容易
暗号化速度 早い 遅い

認証範囲

公開鍵認証は前述の通り電子署名を利用します 共通鍵暗号でもメッセージ認証コード(MAC)などの認証方式がありますが
公開鍵認証と異なり署名と検証の鍵が一緒なので否認の防止や第三者証明が出来ません

鍵管理

鍵の管理ですが共通鍵暗号では 2 つの不便さがあります

  1. 鍵の交換方法がない
    • 公開鍵暗号であれば公開鍵を渡す際に盗まれたとしても問題ありません
    • 共通鍵は盗まれないように渡す必要があります
  2. 管理する鍵の数が増える
    • 鍵は通信したい相手の数だけ持つ必要があります
    • n 人の間で各々通信したい場合は n(n-1)/2 個の鍵が必要になります

暗号化速度

一般に共通鍵暗号の方が公開鍵暗号よりも高速です
そのため SSH では 2 つを組み合わせたハイブリッド暗号を用います

  • 公開鍵暗号: 鍵交換・認証に使う
  • 共有鍵: 暗号化&復号・メッセージ認証に使う

公開鍵認証を活用した暗号化通信

公開鍵認証では通常以下のステップで暗号化が行われます

  1. 鍵交換
  2. 認証
  3. 暗号化通信

鍵交換

キーペアを使い、2者間で秘密裏に情報を共有できる方式です
これを利用して暗号化通信に使う共有鍵を交換します

※以下の参考記事が非常に分かりやすいので参照することをオススメします

認証

アクセス元は「接続先が本当に意図している相手か」を公開鍵認証で確認します
(具体的には接続先の署名を、接続先の公開鍵を用いて検証します)

暗号化通信

鍵交換した共有鍵を用いて暗号化通信を行います
鍵交換〜認証に用いたキーペアは原則使い回しますが
暗号化通信に用いた共有鍵は使い捨てで問題ありません

まとめ

この記事では以下の 4 つについて確認しました

SSH を使うだけであれば以下の点だけ意識しておけば良いでしょう

  • 秘密鍵絶対に誰にも渡さない
  • 公開鍵は他の場所に置いても問題はない

参考書籍

AWS ソリューションアーキテクトアソシエイト(SAA)合格体験記

AWS SAA デジタルバッチ

2020 年 12 月 AWS ソリューションアーキテクトアソシエイト(SAA)に合格しました
行った対策、申込〜試験当日、これから勉強する方へのオススメの勉強法について書きたいと思います

学習期間と行った対策

  • 学習期間: 約 3 ヶ月
  • 行った対策
    • AWS 公式資料や動画学習サイトを活用する
    • 実際に AWS サービスを触ってみる

学習期間: 約 3 ヶ月

私の場合は以下の理由(言い訳)から 3 ヶ月ほどかかりました

  • ネットワーク、DB、DNS などの IT 基礎知識が不足していた
  • 業務が忙しい時期だったため、平日に勉強時間を思うように確保できなかった
  • 周辺知識を調べすぎた

IT 基礎知識が既にあったり、短期集中で時間を確保できる方であれば
2 週間 ~ 1 ヶ月ほどで合格することも可能だと思います

行った対策

行った対策は主に以下の通りです

  • AWS 公式資料を読む
  • AWS サービスを実際に使ってみる
  • Udemyで対策講座を受講する
  • 疑問に思った内容を適宜調べて理解を深める

AWS 公式資料を読む

基本的に困ったときはAWS 公式ドキュメントをみるのが一番です
ただ、日本語の翻訳が一部おかしい時もあるので可能であれば原文(英語)で読むのがより良いと思います

出典: Amazon Simple Storage Service ユーザガイド
出典: Amazon Simple Storage Service ユーザガイド

参考: Amazon Simple Storage Service ユーザガイド

ただ、AWS 公式ドキュメントをいきなり読み始めるのは大変なので
まずはAWS 公式のスライド(BlackBelt シリーズ)から見始めるのがとっつきやすいと思います

出典: 20190220 AWS Black Belt Online Seminar Amazon S3 / Glacier
出典: 20190220 AWS Black Belt Online Seminar Amazon S3 / Glacier

参考: 20190220 AWS Black Belt Online Seminar Amazon S3 / Glacier

AWS サービスを実際に使ってみる

AWS サービスをより良く使えるようにするための資格なので
実際にサービスを触ってみることは必須だと思います ドキュメントを理解したつもりでも、実際に使ってみると「あれっ」となることはよくあります

何から始めるべきかが分からない方は公式チュートリアルを利用してみても良いですが
試験対策という意味であれば後述の Udemy(動画学習講座)を利用するのがオススメです

Udemy で対策講座を受講する

Udemy以下のような特徴のある動画学習サービスです

  • プログラミングなど IT 関連の動画が豊富
  • 月額〇〇円といったサブスク形式ではなく、1 つ 1 つの動画の買い切り
  • 頻繁にセールをやっているのでセール時に買うべき(24,000 円 -> 1,200 円など)

AWS SAA 関連で私が受講したのは以下の 2 つです
(内容は定期的に更新されるため、タイトルが一部異なる場合があります)

試験突破講座の良かったと思う点は以下の 2 点です

  • ハンズオン形式の講座のため、どの AWS サービスを触りながら理解できる
  • 幅広いサービスをカバーし、試験を受ける際に抑えるべきポイントが紹介されている

模擬試験問題集に関しては以下の理由から別のものを選んでも良いと思います

  • 問題文・解説に誤字脱字がある
  • 実際の試験問題よりも難易度が高かったり、細かすぎる知識を問う問題がある

とはいえ、問題数が多く全問題に対して解説がついているので
上記の点があることを事前に分かっておけば問題ないと思います

疑問に思った内容を適宜調べて理解を深める

講座・問題集の勉強中に疑問に思ったこと、知らなかったことは適宜検索しました
おすすめのサイトは以下の通りです

  • AWS 公式ドキュメント
    • やはり基本的には公式ドキュメントです
    • 最初から読み始めるのは骨が折れるので、分からない部分をスポット的に調べると便利です
    • また他のサービスとの比較(例えば SQS と SNS の違いなど)は良くある質問が分かりやすい時が多かったです
    • もちろんAWS 公式のスライド(BlackBelt シリーズ)を見直すのもオススメです
  • クラスメソッド
    • クラスメソッドさんは AWS の様々な記事を公開されています
    • 入門者向けの概要記事や試験で問われるような細かい知識の記事も複数存在します
    • 公式ドキュメントよりも図が多く直感的に分かりやすいことが多いです

申込 〜 試験当日

申込〜試験当日で記憶に残っているものを紹介します

試験実施会社の選択に迷った

受験当時、AWS 試験実施会社は「ピアソン VUE」、「PSI」の 2 種類がありました
以下の理由からピアソン VUEを選択しました

  • コロナ禍ということもあり、自宅受験が良かった
  • パスポートなどの英語圏監督者が分かる身分証明書を持っていなかった

英語の試験官にビビる

日本対応の監督者が良かったのですが、スケジュールが合わず英語対応の監督者の日程で受験しました

特にこちらから英語を話す機会はなかったのですが、
試験中考え込む際、無意識に碇司令のように口元を隠してしまっていたようで
試験画面のチャットで「Don't hide mouth」的な事を言われ「OK」と返信しました
特に問題はなかったのですが、英語が苦手なこともあり、少し焦りました

結果発表はすぐ

試験が終了するとすぐに合否が表示され、証明書や得点比率は後日メールで送られてきました

これから受験を考える方へ

AWS の利用経験や IT 基礎知識がどれくらいあるかにも寄りますが以下の 2 つに分類しました

  • 普段から AWS サービスを幅広く使っている方向け
  • ほとんど AWS サービスを使ったことがない方向け

(私自身は AWS 歴が約半年でだったので、ちょうど間くらいだったかなと思っています)

普段から AWS サービスを幅広く使っている方

AWS 公式模擬試験を受講するだけでも良いかもしれません
ただ、Web アプリ開発に関連するサービス(EC2, Lambda, DynamoDB など)は触った事あるけど
データ分析系のサービス(RedShift, Kinesis)は触った事がないという場合は苦手なサービスだけ
AWS 公式のスライド(BlackBelt シリーズ)を見つつ触ってみるのが良いかもしれないです

ほとんど AWS サービスを使ったことがない方

以下の流れがオススメです

  1. これだけで OK! AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座 を受講する
  2. AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集 などの問題を一通り解いてみる
  3. 理解が足りないと感じた問題について良くある質問クラスメソッドで調べて知識を補う

ポイントとしては以下の 2 点です

  • 試験突破講座を受講後に問題を解いてみて、正答率が低くてもめげない
    • 「ちゃんと受講したはずなのに意外と取れないな」と思っても諦めず知識を補充して下さい
  • 模擬試験問題集を各回の正当率が 90%以上になるまで繰り返す
    • 1 回目は「とりあえず受けてみる」で正答率 20%とかでも問題ないです
    • 2 回目 or 3 回目あたりで点数が取れてくるようになります

まとめ

今回は AWS ソリューションアーキテクトアソシエイト(SAA)試験の
行った対策、申込〜試験当日、これから勉強する方へのオススメの勉強法について紹介しました
次は AWS ディベロッパーアソシエイト(DVA)を取得したいと思っています

10 分で入門する Docker(実践編)

Docker を使う上で最低限必要な知識のみを厳選して説明していきます

この記事を読んで分かること

  • Docker の状態とコマンドの関係性を示した下図の意味が分かる
    • 本記事では docker コマンドにフォーカスして説明していきます
    • Docker 自体の基本知識や、概念を知りたい方は10 分で入門する Docker(概念編)を参照して下さい
  • 以下の Docker コマンドについて紹介します
    • pull, rmi
    • create, rm
    • start, stop
    • run
    • attach, exec
    • images, ps

Docker遷移図
Docker遷移図

前提条件

  • 対象者
    • Docker の全体像をサクッとつかみたい人
    • Docker やコンテナ技術を聞いたことはあるけど、よく分かってない人
  • この記事で紹介しないこと
    • Docker の基礎知識や概念
    • Dockerfile、マウント、ネットワークなど

Docker についての基礎知識

10 分で入門する Docker(概念編)から抜粋して紹介します

Docker 使うと何が嬉しいの?

Docker を使う利点は主に以下の 2 点だと思っています

  1. Docker がインストールされていれば環境の横展開(共有・複製等)が容易
    • OS の種類に関わらず同じ環境を起動することができる
  2. 他の仮想化技術に比べて軽量で高速のため、スクラップ&ビルドが容易
    • 手順書やホスト OS の違いを意識したスクリプトを作成せず、コマンドで環境構築ができる

Docker ってざっくり言うと?

  • コンテナ型仮想化技術と呼ばれ、 1 台のホストマシンから複数の OS を同時に動作させることが可能
  • Docker イメージから Docker コンテナを起動することで、比較的簡単に仮想環境を利用できる
  • Docker レジストリから Docker イメージを簡単にダウンロードできる

Docker コマンドを実行して Python 環境を整える

この章では 以下の手順で Docker コマンドを叩くことで Python の実行環境を整えます

  1. レジストリ(Docker Hub)から Python のイメージを取得する
  2. イメージからコンテナを作成する
  3. コンテナを起動する
  4. コンテナ上でコマンドを実行する

レジストリからイメージをダウンロードする(pull, images)

レジストリからイメージをダウンロードするにはdocker pullを実行します

  • デフォルトのレジストリは Docker Hub が設定されています
docker pull python
  • docker pullはイメージデータをダウンロードするため時間がかかることが多いです
    • とはいえ Docker では CoW 方式を採用しているので効率は良いです
  • docker pullが完了したらdocker imagesでダウンロード済みのイメージを確認できます
docker images

REPOSITORY     TAG             IMAGE ID            CREATED            SIZE
python         latest          254d4a8a8f31        1 hours ago        885MB

python という Docker イメージが存在することが分かります

イメージからコンテナを作成する(create, ps)

イメージからコンテナを作成するにはdocker createを実行します

docker create -it --name sample_container python

オプションの説明

  • -it(実際は-i, -tの 2 つに分かれている)
  • --name sample_container
    • 作成するコンテナに名前(今回は sample_container)をつけます
    • 明示的に名前をつけなくても問題はないですが、つけておいた方が管理しやすいです
  • python
    • 作成対象のイメージ名を指定します

コンテナが作成されているかはdocker psで確認できます

docker ps -a
CONTAINER ID    IMAGE            COMMAND      CREATED        STATUS    PORTS    NAMES
d4f4cabbc93c    python:latest    "python3"    1 hours ago    Created            sample_container

docker psはデフォルトでは起動中のコンテナしか表示しませんが
-aをつけることで全てのコンテナを表示します

イメージを起動する(start)

イメージを起動するにはdocker startを実行します

docker start sample_container

コンテナが起動されているかもdocker psで確認できます
(今回は起動中かの確認なので-aをつける必要はありません)

docker ps
CONTAINER ID    IMAGE            COMMAND      CREATED        STATUS       PORTS    NAMES
d4f4cabbc93c    python:latest    "python3"    1 hours ago    Up 1 hours            sample_container

ホストマシンから起動中のコンテナに接続する(attach, exec)

attach

ホストマシンから起動中のコンテナに接続するにはdocker attachを実行します

docker attach sample_container
>>>

今回は Python のイメージなので、Python が実行された状態で接続されます

exec

ホストマシンから起動中のコンテナで任意のコマンドを実行するにはdocker execを実行します

  • 基本的にはdocker exec -it [コンテナ名] [実行したいコマンド]
  • -itをつける理由はcreateの時と同じ
docker exec -it sample_container bash

attach と exec 違い

主に以下の 2 点です
コンテナを Exit する度にコンテナが停止してしまうため、execの方が良いと思っています

attach exec
実行コマンド 事前に決められている 任意
Exit した時 コンテナが停止する コンテナは停止しない
  • これまでの内容で docker コマンドを叩くだけで、Python を実行できる環境は整いました
  • しかし、ホスト上の Python ファイルをコンテナ上で動作させることは出来ていません
  • この解決策は補足にて紹介します
  • 以降の章ではコンテナの停止・削除などお片付けについて紹介します

コンテナを停止・削除する(stop, rm)

コンテナの停止にはdocker stopを実行します

docker stop sample_container

コンテナの Status を確認すると Exited になっています

docker ps -a

CONTAINER ID    IMAGE            COMMAND      CREATED        STATUS                   PORTS    NAMES
d4f4cabbc93c    python:latest    "python3"    1 hours ago    Exited (137) 1 hours              sample_container

コンテナの削除にはdocker rmを実行します

docker rm sample_container

docker psで確認すると sample_container が消えています

docker ps -a
CONTAINER ID    IMAGE            COMMAND      CREATED        STATUS       PORTS    NAMES

イメージからコンテナを作成&起動する(run)

イメージからコンテナを作成&起動するにはdocker runを実行します

# 実行コマンドを指定する場合
docker run -it --name sample_container python

# 実行コマンドを設定しない場合
docker run -it --name sample_container python /bin/bash

docker runはコマンドを指定する・しないに関わらず Exit 時にコンテナが停止します
これは以下のようにすることで回避することが可能です

docker run -itd --name sample_container python
docker exec -it sample_container bash

docker runのオプションとして-dをつけることでバックグランド実行が可能です
その上でdocker execすることで Exit してもコンテナの停止を防ぐことが出来ます

イメージをホストマシンから削除する(rmi)

イメージをホストマシンから削除するにはdocker rmiを実行します
(※削除するには対象のイメージを元に作成しているコンテナを全て削除している必要があります)

docker rm sample_container
docker rmi python

補足

この記事を読んで以下の疑問を持たれた方がいるかもしれません

  • イメージをレジストリから取得出来たけど、そもそもイメージはどう作るの?
  • Python のコンテナを作成出来たけど、ホスト上の Python ファイルを実行するにはどうするの?
  • Web アプリのコンテナを作成したら、ホストからどうやってアクセスすればいいの?

この疑問にはそれぞれ

  • Dockerfile
  • Docker ボリューム
  • Docker ネットワーク

が関連しています
今後これらの記事も作成予定ですが、気になった方は調べてみて下さい

まとめ

本記事では Docker の状態とコマンドの関係性を示した下図と以下のコマンドについて紹介しました

Docker遷移図
Docker遷移図

  • pull, rmi
  • create, rm
  • start, stop
  • run
  • attach, exec
  • images, ps

10 分で入門する Docker(概念編)

Docker を使う上で最低限必要な知識のみを厳選して説明していきます

この記事を読んで分かること

  • Docker を使うメリットが分かる
  • 公式ドキュメントにある下図の意味が分かる
    • ※具体的な Docker コマンドについてはこの記事では紹介しません

Docker全体像
Docker全体像

※まず Docker を動かしてみたい方は以下の記事で紹介しているので、参照して下さい

前提条件

  • 対象者
    • Docker の全体像をサクッとつかみたい人
    • Docker やコンテナ技術を聞いたことはあるけど、よく分かってない人
  • この記事で紹介しないこと
    • 具体的な Docker コマンド
    • Dockerfile、マウント、ネットワークなど

Docker 使うと何が嬉しいの?

Docker を使う利点は主に以下の 2 点だと思っています

  1. Docker がインストールされていれば環境の横展開(共有・複製等)が容易
  2. 他の仮想化技術に比べて軽量で高速のため、スクラップ&ビルドが容易

以降の説明ではこの 2 点に絡めて説明をしていこうと思います

Docker とは何か?

  • 仮想化技術の 1 つ
  • CLI から Docker コマンドを叩くことで利用できる

仮想化技術の 1 つ

1 台のホストマシンから複数の OS を同時に動作させることが出来ます
(Windows PC 上で Ubuntu の環境を立ち上げるなど)

Docker はコンテナ型仮想化技術と呼ばれ他にもいくつか仮想化技術の種類がありますが コンテナ型仮想化技術である Docker は比較的高速です 参考: 仮想化技術の違いを比較(IT zoo)

CLI から Docker コマンドを叩くことで利用できる

Mac であればの CLI(Terminal など)から Docker コマンド(docker buildなど)を叩いて利用します
コマンドに応じて Docker クライアントが Docker デーモンとやりとりして動作します (※ユーザは Docker デーモンと直接やり取りせず、原則 docker コマンドを叩くだけで OK です)

Docker コンテナとは何か?

Docker ロゴ

Docker を端的に示しているのが上記のロゴです

  • クジラ: Docker が動作しているホストマシン(PC とかサーバとか)
  • クジラが背負っている1つ1つの箱: コンテナ

それぞれのコンテナは独立した実行環境になっています
(「Ubuntu + Nginx + Python」、「CentOS + MySQL」とか)
また、クジラ(ホストマシン)からコンテナ(実行環境)の追加・削除は容易に行えます

Docker コンテナで出来ること

コンテナ(実行環境)同士は独立していて、追加・削除は容易なので以下のことが可能です

  • 利用したいコンテナを起動するだけで環境構築が終わる
    • Docker さえインストールされていればホスト OS の違いを気にせず同じ実行環境を利用できる
    • 独立というより、自立しているというイメージ(もちろん Docker は必要だけど...)
  • コンテナが壊れたり、必要なくなったりしても削除&再作成(スクラップ&ビルド)すれば OK
    • テスト用のコンテナを作成してテストを実行し終わったらコンテナを破棄するとか
    • 新しい技術を試しに使ってみる検証環境を作って、終わったら破棄するとか
  • Web サーバなどのスケールアウトが容易
    • 負荷のかかる Web サーバなどは負荷を分散するためにサーバを追加することがあります
    • Docker であれば同じコンテナを追加するだけで済みます

Docker コンテナを利用しない場合

  • 手順書を書く
  • ホスト OS の違いを加味してスクリプトを書く必要がある

といった手間がかかりますが、Docker であれば後述の設定ファイル・コマンドを打つだけで済みます

Docker イメージとは何か?

Docker イメージはコンテナを作成する情報が詰まっているものです
Docker イメージがあれば、それに応じた Docker コンテナを作成できます
(逆にコンテナからイメージも作成できますが、最初は無視して OK です)

ここでもう一度、公式ドキュメントにある全体像を見てみます

Docker全体像
Docker全体像

上図には Ubuntu(OS)と Redis(インメモリ DB)のイメージが用意されており、 Ubuntu のイメージから Ubuntu のコンテナができていることが分かると思います

Docker イメージで出来ること

Docker イメージに対応するコンテナを起動できるので以下のことが可能です

  • Docker イメージを他のホストマシンに渡すことで同じ実行環境(コンテナ)を利用できる
  • 1 つの Docker イメージから同じコンテナを複数起動できる

Docker レジストリとは何か?

前の章で

Docker イメージを他のホストマシンに渡すことで同じ実行環境(コンテナ)を利用できる

と紹介しましたが、「どうやって他のホストマシンに渡すの?」という疑問が生じます
メール等で送ったりするのは面倒なので、レジストリが用意されています

公式にはDocker Hubというレジストリが用意されており、これを使うことが多いです
レジストリには Docker イメージが共有されており、docker コマンドを叩くだけでホストマシンに Docker イメージをダウンロードできます

まとめ

本記事では公式ドキュメントにある下図について紹介しました

Docker全体像
Docker全体像

Docker を使うことで

  • 手順書を書く
  • ホスト OS の違いを加味してスクリプトを書く

といった作業から解放され

  • Docker がインストールされていれば環境の横展開(共有・複製等)が容易
  • 他の仮想化技術に比べて軽量で高速のため、スクラップ&ビルドが容易

というメリットがあることを紹介しました

Docker で Python 環境構築を 10 分で整える

初心者エンジニアにとって環境構築が最初にして最大の難関です(私はそうでした...)
そこでDockerを利用することで、環境構築をつまづきポイントを少なくできます
今回は Docker(Docker Compose)を利用することで Python の環境構築を紹介します

この記事を読んで分かること

  • Docker Compose を使うことで Python の実行環境を用意できる
  • ブラウザから Jupyter Notebook を実行できる

前提条件

今回は Python を Docker コンテナ上で動作可能にすることにフォーカスします
Python, Docker の細かい説明には焦点を当てないのでご注意を m(__)m

動作環境は以下の通りです

Docker, DockerCompose をインストールする

※今回は Mac を前提としているため Docker for Mac をインストールします

Docker ドキュメントを日本語翻訳して頂いているサイトに記載があります
(英語を読むのに抵抗がない方は本家ドキュメントを参照してください)

  1. Docker Hubから Docker Desktop for Mac をダウンロードします
  2. インストール方法に従ってインストールすると Docker だけでなく、Docker Compose も一緒にインストールされます

設定ファイルを記述する

Docker を使う時に、毎回長々とオプションをつけるよりも
設定を YAML 形式で記述するDocker Composeを利用する方がとっつきやすいと思っています (ssh する時に config 書いておいた方が早くアクセスできるみたいな...?)

最終的なディレクトリ構成は以下の通りです

docker_python
        ├── .docker
        │   ├── Dockerfile
        │   └── requirements.txt
        ├── docker-compose.yml
        └── sample.py
  • docker-compose.yml
    • Docker Compose の設定ファイル(YAML 形式)
    • Docker のコンテナの設定を記述します
version: "3.7"
services:
  app:
    build: .docker
    volumes:
      - ./:/app
    working_dir: /app
    tty: true
    ports:
      - "8890:8890"
  • .docker/Dockerfile
    • Docker イメージの設計図のようなもの
    • requirements.txtに設定したパッケージ群をインストールした Python の実行環境を用意します
FROM python:3.8

WORKDIR /init

COPY requirements.txt /init

RUN pip3 install -r /init/requirements.txt
  • .docker/requirements.txt
    • Python にインストールするパッケージ群を記述します
    • ※今回はデータ分析でよく使われるパッケージを設定しましたが適宜変更可能です
numpy
pandas
jupyter
  • sample.py

    • ここでは Python の実行確認をするためだけなので、シンプルにしておきます
    • 実行完了後はsample.csvを出力します
import numpy as np
import pandas as pd

data = pd.Series(np.arange(10))
data.to_csv('./sample.csv')

Python を Docker コンテナ上で実行する

  1. Docker Compose の起動

    • docker-compose.yml で設定した Docker コンテナを起動します
docker-compose up -d
  1. Python の実行

    • Docker コンテナ上で sample.py を実行します
    • 実行後、sample.py と同じディレクトリ下に sample.csv が作成されます
docker-compose exec app python sample.py

ここまでで Python の実行環境の構築は完了ですが、Python でデータ分析をする際は
Jupyter Notebook 等を利用することが多いため、その方法についても紹介します

Docker コンテナ上の Jupyter Notebook にブラウザにアクセスする

  1. Docker コンテナ上で bash を起動する
docker-compose exec app bash
  1. Jupyter Notebook を起動する

    • --allow-root, --ip=0.0.0.0
      Docker コンテナ上で Jupyter Notebook を起動するために必要な設定です
    • --port
      docker-compose.yml で設定している(コンテナ側の)ポート番号と合わせる必要があります
    • --NotebookApp.token=''
      つけなくても問題ありませんが、その場合は実行時に発行される URL をブラウザに入力する必要があります
jupyter notebook --allow-root --ip=0.0.0.0 --port=8890 --NotebookApp.token=''
  1. ブラウザから Jupyter Notebook を開く

    • Google Chrome などのブラウザからlocalhost:8890にアクセスすれば OK

まとめ

Docker Compose を利用することで Python の実行環境を用意する方法を紹介しました
つまづきがちな環境構築も Docker をインストールしていれば比較的スムーズになると思います