toshiki-notebook/assets/development_aws_main.md.9b60fdd4.js

1912 lines
975 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import{_ as n}from"./chunks/earth_from_earth.8c108f53.js";import{_ as l,a as p,b as o,c as e}from"./chunks/terminal.94539704.js";import{_ as t,a as r,b as c,c as i,d as y,e as d,f as u,g as b,h as A,i as m,j as h}from"./chunks/iac.2263bc12.js";import{_ as s,a}from"./chunks/VPC.e1acca4d.js";import{_ as B,a as g,b as _,c as f,d as k,e as v,f as q}from"./chunks/ec2_keypair_console.fc89ef69.js";import{_ as D,a as C}from"./chunks/cnn.a8836fd9.js";import{_ as S,a as w,b as P,c as E,d as I,e as z,f as x,g as T,h as W,i as $,j as L,k as G,l as N,m as U,n as R,o as X,p as M}from"./chunks/mnist_prediction.4ba5b405.js";import{_ as H,a as F,b as O,c as j,d as V,e as K,f as Y,g as J}from"./chunks/ecs.73d77e6a.js";import{_ as Q,a as Z,b as ss,c as as,d as ns,e as ls,f as ps,g as os,h as es,i as ts,j as rs}from"./chunks/ask_many_output.0bb19110.js";import{_ as cs,a as is,b as ys,c as ds,d as us,e as bs,f as As,g as ms,h as hs,i as Bs,j as gs,k as _s,l as fs,m as ks,n as vs,o as qs,p as Ds,q as Cs,r as Ss,s as ws}from"./chunks/cloud_development.e43e5d4a.js";import{_ as Ps,a as Es}from"./chunks/rest_api.602a6e96.js";import{_ as Is,a as zs,b as xs,c as Ts,d as Ws}from"./chunks/s3_vs_filesystem.fd65005d.js";import{_ as $s,a as Ls,b as Gs,c as Ns,d as Us,e as Rs,f as Xs,g as Ms,h as Hs,i as Fs,j as Os,k as js,l as Vs}from"./chunks/s3_bucket_filelist.89f3f384.js";import{_ as Ks,a as Ys,b as Js,c as Qs,d as Zs,e as sa,f as aa,g as na,h as la}from"./chunks/bashoutter_2.cd8a2a95.js";import{_ as pa,a as oa,b as ea,c as ta,d as ra,e as ca,f as ia,g as ya,h as da,i as ua,j as ba,k as Aa,l as ma,m as ha,n as Ba,o as ga}from"./chunks/venv_shell.dc2530bc.js";import{_ as _a,c as fa,o as ka,R as va}from"./chunks/framework.ade46834.js";const Ya=JSON.parse('{"title":"はじめに!","description":"","frontmatter":{},"headers":[],"relativePath":"development/aws/main.md","filePath":"development/aws/main.md","lastUpdated":1694919393000}'),qa={name:"development/aws/main.md"},Da=va('<h1 id="はじめに" tabindex="-1">はじめに! <a class="header-anchor" href="#はじめに" aria-label="Permalink to &quot;はじめに!&quot;"></a></h1><h2 id="本書の目的・内容" tabindex="-1">本書の目的・内容 <a class="header-anchor" href="#本書の目的・内容" aria-label="Permalink to &quot;本書の目的・内容&quot;"></a></h2><p>本書は,東京大学計数工学科で 2021 年度 S1/S2 タームに開講されている&quot;システム情報工学特論&quot;の講義資料として作成された.</p><p>本書の目的は,クラウドの初心者を対象とし,クラウドの基礎的な知識・概念を解説する. また, Amazon Web Services (以下, AWS) の提供するクラウド環境を実例として,具体的なクラウドの利用方法をハンズオンを通して学ぶ.</p><p>とくに,科学・エンジニアリングの学生を対象として,研究などの目的でクラウドを利用するための実践的な手順を紹介する. 知識・理論の説明は最小限に留め,実践を行う中で必要な概念の解説を行う予定である. 読者が今後,研究などでクラウドを利用する際の,足がかりとなれば本書の目的は十分達成されたことになる.</p><p>本書は以下のような三部構成になっている.</p><table><caption>本書の構成</caption><colgroup><col style="width:20%;"><col style="width:40%;"><col style="width:40%;"></colgroup><thead><tr class="header"><th></th><th>テーマ</th><th>ハンズオン</th></tr></thead><tbody><tr class="odd"><td><p>第一部 (1章-4章)</p></td><td><p>クラウドの基礎</p></td><td><ul><li><p>AWSに自分のサーバーを立ち上げる</p></li></ul></td></tr><tr class="even"><td><p>第二部 (5章-9章)</p></td><td><p>クラウドを活用した機械学習</p></td><td><ul><li><p>AWS と Jupyter を使って始めるディープラーニング</p></li><li><p>スケーラブルな自動質問回答ボットを作る</p></li><li><p>並列化されたハイパーパラメータサーチの実装</p></li></ul></td></tr><tr class="odd"><td><p>第三部 (10章-13章)</p></td><td><p>サーバーレスアーキテクチャ入門</p></td><td><ul><li><p>Lambda, DynamoDB, S3 の演習</p></li><li><p>俳句を投稿する SNS &quot;Bashoutter&quot; を作る</p></li></ul></td></tr></tbody></table><p>第一部は,クラウドの基礎となる概念・知識を解説する. セキュリティやネットワークなど,クラウドを利用する上で最低限おさえなければいけないポイントを説明する. ハンズオンでは,はじめての仮想サーバーを AWS に立ち上げる演習を行う.</p><p>第二部では,クラウド上で科学計算 (とくに機械学習) を走らせるための入門となる知識・技術を解説する. あわせて, <a href="https://www.docker.com/" target="_blank" rel="noreferrer">Docker</a> とよばれる仮想計算環境の使用方法を紹介する. 一つ目のハンズオンでは, AWS のクラウドで Jupyter Notebook を起動し簡単な機械学習の計算を走らせる課題を実践する. 二つ目のハンズオンでは,深層学習を用いた自然言語処理により,質問に自動で回答を生成するボットを作成する. 最後に,複数台の GPU インスタンスからなるクラスターを起動し,並列に深層学習のハイパーパラメータサーチを行う方法を紹介する.</p><p>第三部では,サーバーレスアーキテクチャとよばれる最新のクラウドのアーキテクチャを紹介する. これは,サーバーの処理能力を負荷に応じてより柔軟に拡大・縮小するための概念であり,それ以前 (Serverful としばしばよばれる) と質的に異なる設計思想をクラウドに導入するものである. ハンズオンでは,サーバーレスクラウドの主要なコンポーネントである Lambda, DynamoDB, S3 の演習を提供する. さらに,サーバーレスの技術を使用して簡単な SNS をクラウド上に作成する.</p><p>これらの豊富なハンズオンにより, AWS 上にクラウドシステムを開発するための知識と技術が身につくはずである. いずれのハンズオンも,実用性を重視したものになっており,これらをベースにカスタマイズを施すことで様々な応用が可能である.</p><h2 id="本書のフィロソフィー" tabindex="-1">本書のフィロソフィー <a class="header-anchor" href="#本書のフィロソフィー" aria-label="Permalink to &quot;本書のフィロソフィー&quot;"></a></h2><p>本書のフィロソフィーを一言で表すなら, <strong>&quot;ロケットで宇宙まで飛んでいって一度地球を眺めてみよう!&quot;</strong> である.</p><p>どういうことか?</p><p>ここでいう&quot;地球&quot;とは,クラウドコンピューティングの全体像のことである. 言うまでもなく,クラウドという技術は非常に広範かつ複雑な概念で,幾多の情報技術・ハードウェア・アルゴリズムが精緻に組み合わさってできた総体である. そして,今日では科学研究から日常のインフラ設備に至るまで,我々の社会の多くの部分がクラウド技術によって支えられている.</p><p>ここでいう&quot;ロケット&quot;とはこの講義のことである. この講義では,ロケットに乗って宇宙まで飛び立ち,地球(クラウド)の全体を自身の目で眺めてもらう. その際,ロケットの成り立ちや仕組み (背後にある要素技術やプログラムのソースコード) を深くは問わない. 将来,自分が研究などの目的でクラウドを利用することになった際に,改めて学んでもらえば良い. 本書の目的はむしろ,クラウドの最先端に実際に触れ,そこからどんな景色が見えるか(どんな応用が可能か)を実感してもらうことである.</p><p>そのような理由で,本書はクラウドの基礎から応用まで幅広いテーマを取り扱う. 第一部はクラウドの基礎から始め,第二部では一気にレベルアップし機械学習(深層学習)をクラウドで実行する手法を解説する. さらに第三部では,サーバーレス・アーキテクチャというここ数年のうちに確立した全く新しいクラウドの設計について解説する. それぞれで本一冊分以上の内容に相当するものであるが,本書はあえてこれらを一冊にまとめ連続的に俯瞰するという野心的な意図をもって執筆された.</p><p>決して楽な搭乗体験ではないかもしれないが,このロケットにしがみついてきてもらえれば,とてもエキサイティングな景色が見られることを約束したい.</p><p><img src="'+n+'" alt="宇宙からみた地球 (Image from NASA https://www.nasa.gov/image-feature/planet-of-clouds)"></p><h2 id="aws-アカウント" tabindex="-1">AWS アカウント <a class="header-anchor" href="#aws-アカウント" aria-label="Permalink to &quot;AWS アカウント&quot;"></a></h2><p>本書では,ハンズオン形式で AWS のクラウドを実際に動かす演習を提供する. 自分でハンズオンを実行してみたい読者は,各自で AWS のアカウントの作成をしていただく. AWS のアカウントの作成の仕方は巻末付録 (<a href="#sec:create_aws_account">AWS アカウントの取得</a>) に簡単に記載したので,必要に応じて参照していただきたい.</p><p>AWS にはいくつかの機能に対して無料利用枠が設定されており,いくつかのハンズオンは無料の範囲内で実行できる. 一方,ほかのハンズオン (とくに機械学習を扱うもの) では数ドル程度のコストが発生する. ハンズオンごとに発生するおおよそのコストについて記述があるので,注意をしながらハンズオンに取り組んでいただきたい.</p><p>また,大学などの教育機関における講義で AWS を使用する際は, <a href="https://aws.amazon.com/education/awseducate/" target="_blank" rel="noreferrer">AWS Educate</a> というプログラムを利用することも可能である. これは,講義の担当者が申請を行うことで,受講する学生に対し AWS クレジットが提供されるというプログラムである. AWS Educate を利用することで金銭的な負担なしに AWS を体験することができる. また,講義を経由せず個人でも AWS Educate に参加することも可能である. AWS Educate からは様々な学習教材が提供されているので,ぜひ活用してもらいたい.</p><h2 id="環境構築" tabindex="-1">環境構築 <a class="header-anchor" href="#環境構築" aria-label="Permalink to &quot;環境構築&quot;"></a></h2><p>本書では, AWS 上にクラウドアプリケーションを展開するハンズオンを実施する. そこで紹介するプログラムを実行するためには,以下の計算機環境が必要である. インストールの方法については,巻末付録 (<a href="#sec:appendix_settingup">Appendix: 環境構築</a>) に記してある. 必要に応じて参照し,環境構築を各自実施していただきたい.</p><ul><li><p><strong>UNIX 系コンソール</strong>: ハンズオンで紹介するコマンドを実行したり, SSH でサーバーにアクセスするため, UNIX 系のコンソール環境が必要である. Mac または Linux のユーザーは, OS に標準搭載のコンソール(ターミナルとも呼ばれる)を使用すればよい. Windows のユーザーは, <a href="https://docs.microsoft.com/en-us/windows/wsl/about" target="_blank" rel="noreferrer">Windows Subsystem for Linux (WSL)</a> を使い, Linux の仮想環境のインストールを推奨する (<a href="#sec:install_wsl">WSL のインストール</a> 参照)</p></li><li><p><strong>Docker</strong>: 本書では Docker とよばれる仮想計算環境の利用方法を解説する. インストール手順については <a href="#sec:install_docker">Docker のインストール</a> を参照のこと.</p></li><li><p><strong>Python</strong>: Version 3.6 以上をインストールする. とくに,ハンズオンでは <code>venv</code> モジュールを使用する. <code>venv</code> の使い方は <a href="#venv_quick_guide">Python クイックガイド</a> 参照のこと.</p></li><li><p><strong>Node.js</strong>: version 12.0 以上 をインストールする.</p></li><li><p><strong>AWS CLI</strong>: <a href="https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html" target="_blank" rel="noreferrer">Version 2</a> をインストールする. インストール手順については <a href="#aws_cli_install">AWS CLI のインストール</a> 参照のこと.</p></li><li><p><strong>AWS CDK</strong>: Version 1.100 以上をインストールする. Version 2 以降には未対応である. インストール手順については <a href="#aws_cdk_install">AWS CDK のインストール</a> 参照のこと.</p></li><li><p><strong>AWS 認証鍵の設定</strong>: AWS API をコマンドラインから呼ぶには,認証鍵 (secret key) が設定されている必要がある. 認証鍵の設定については <a href="#aws_cli_install">AWS CLI のインストール</a> 参照のこと.</p></li></ul><h3 id="ハンズオン実行用の-docker-image" tabindex="-1">ハンズオン実行用の Docker Image <a class="header-anchor" href="#ハンズオン実行用の-docker-image" aria-label="Permalink to &quot;ハンズオン実行用の Docker Image&quot;"></a></h3><p>Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもクローン済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.</p><p>次のコマンドで起動する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-it</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tomomano/labc</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-it</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tomomano/labc</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>この Docker image の使い方や詳細は <a href="#sec_handson_docker">ハンズオン実行用の Docker image の使い方</a> に記載している.</p><h2 id="前提知識" tabindex="-1">前提知識 <a class="header-anchor" href="#前提知識" aria-label="Permalink to &quot;前提知識&quot;"></a></h2><p>本書を読むにあたり,要求する前提知識は大学初等程度の計算機科学の知識 (OSプログラミングなど)のみである. それ以上の前提知識はとくに仮定しない. クラウドの利用経験もゼロで問題ない. が,以下の事前知識があるとよりスムーズに理解をすることができるだろう.</p><ul><li><p><strong>Python の基本的な理解</strong>: 本書では Python を使ってプログラムの作成を行う. 使用するライブラリは十分抽象化されており,関数の名前を見ただけで意味が明瞭なものがほとんどであるので, Python に詳しくなくても心配する必要はない.</p></li><li><p><strong>Linux コマンドラインの基礎的な理解</strong>: クラウドを利用する際,クラウド上に立ち上がるサーバーは基本的に Linux である. Linux のコマンドラインについて知識があると,トラブルシュートなどが容易になる. 筆者のおすすめの参考書は <a href="http://linuxcommand.org/tlcl.php" target="_blank" rel="noreferrer">The Linux Command Line by William Shotts</a> である. ウェブで無料で読むことができるので,読んだことのない人はぜひ一読を.</p></li></ul><h2 id="講義に関連する資料" tabindex="-1">講義に関連する資料 <a class="header-anchor" href="#講義に関連する資料" aria-label="Permalink to &quot;講義に関連する資料&quot;"></a></h2><p>ハンズオンで使うプログラムや教科書のソースコードは以下のウェブページで公開している.</p><p><a href="https://github.com/tomomano/learn-aws-by-coding" target="_blank" rel="noreferrer">https://github.com/tomomano/learn-aws-by-coding</a></p><h2 id="本書で使用するノーテーションなど" tabindex="-1">本書で使用するノーテーションなど <a class="header-anchor" href="#本書で使用するノーテーションなど" aria-label="Permalink to &quot;本書で使用するノーテーションなど&quot;"></a></h2><ul><li><p>コードやシェルのコマンドは <code>monospace letter</code> で記述する.</p></li><li><p>シェルに入力するコマンドは,それがシェルコマンドであると明示する目的で,先頭に <code>$</code> がつけてある. <code>$</code> はコマンドをコピー&amp;ペーストするときは除かなければならない. 逆に,コマンドの出力には <code>$</code> はついていない点に留意する.</p></li></ul><p>また,以下のような形式で注意やチップスを提供する.</p><p>追加のコメントなどを記す.</p><p>発展的な議論やアイディアなどを紹介する.</p><p>陥りやすいミスなどの注意事項を述べる.</p><p>絶対に犯してはならないミスを指摘する.</p><h1 id="クラウド概論" tabindex="-1">クラウド概論 <a class="header-anchor" href="#クラウド概論" aria-label="Permalink to &quot;クラウド概論&quot;"></a></h1><h2 id="クラウドとは" tabindex="-1">クラウドとは? <a class="header-anchor" href="#クラウドとは" aria-label="Permalink to &quot;クラウドとは?&quot;"></a></h2><p><img src="'+l+'" alt="Cloud"></p><p>クラウドとはなにか? クラウドという言葉は,それ自身がとても広い意味をもつので,厳密な定義付けを行うことは難しい.</p><p>学術的な意味でのクラウドの定義づけをするとしたらNIST(米国・国立標準技術研究所) による <a href="https://csrc.nist.gov/publications/detail/sp/800-145/final" target="_blank" rel="noreferrer">The NIST Definition of Cloud Computing</a> が引用されることが多い. ここに記載されたクラウドの定義・モデルを図示したのが <a href="#fig:nist_cloud_definition">figure_title</a> である.</p><p><img src="'+p+'" alt="The NIST Definition of Cloud Computing"></p><p>これによると,クラウドとは以下の要件が満たされたハードウェア/ソフトウェアの総体のことをいう.</p><ul><li><p><strong>On-demand self-service</strong> 利用者のリクエストに応じて計算資源が自動的に割り当てられる.</p></li><li><p><strong>Broad network access</strong> 利用者はネットワークを通じてクラウドにアクセスできる.</p></li><li><p><strong>Resource pooling</strong> クラウドプロバイダーは,所有する計算資源を分割することで複数の利用者に計算資源を割り当てる.</p></li><li><p><strong>Rapid elasticity</strong> 利用者のリクエストに応じて,迅速に計算資源の拡大あるいは縮小を行うことができる.</p></li><li><p><strong>Measured service</strong> 計算資源の利用量を計測・監視することができる.</p></li></ul><p>…と,いわれても抽象的でよくわからないかもしれない.もう少し具体的な話をする.</p><p>個人が所有する計算機で, CPU をアップグレードしようと思ったら物理的に筐体を開けCPU ソケットを露出させ,新しい CPU に交換する必要があるだろう. あるいは,ストレージがいっぱいになってしまったら,古いディスクを抜き取り,新しいディスクを挿入する必要がある. 計算機の場所を移動させたときには,新しい部屋の LAN ケーブルを差し込まないとネットワークには接続できない.</p><p>クラウドでは,これらの操作が<strong>プログラムからのコマンドによって実行できる</strong> CPU が 1000 個欲しいと思ったならば,そのようにクラウドプロバイダーにリクエストを送れば良い. すると,数分もしないうちに 1000 CPU の計算資源が割り当てられる. ストレージを 1TB から 10TB に拡張しようと思ったならば,そのようにコマンドを送ればよい (これはGoogle Drive や Dropbox などのサービスなどで馴染みのある人も多いだろう) 計算資源を使い終わったら,そのことをプロバイダーに伝えれば,割り当て分はすぐさま削除される. クラウドプロバイダーは,使った計算資源の量を正確にモニタリングしており,その量をもとに利用料金の計算が行われる.</p><p>このように,クラウドの本質は物理的なハードウェアの仮想化・抽象化であり,利用者はコマンドを通じて,<strong>まるでソフトウェアの一部かのように,物理的なハードウェアの管理・運用を行うことができる</strong> もちろん,背後では,データセンターに置かれた膨大な数の計算機が大量の電力を消費しながら稼働している. クラウドプロバイダーはデータセンターの計算資源を上手にやりくりし,ソフトウェアとしてのインターフェースをユーザーに提供することで,このような仮想化・抽象化を達成しているわけである. クラウドプロバイダーの視点からすると,大勢のユーザーに計算機を貸し出し,データセンターの稼働率を常時 100%に近づけることで,利益率の最大化を図っているのである.</p><p>著者の言葉で,クラウドの重要な特性を定義するならば,以下のようになる.</p><blockquote><p>クラウドとは計算機ハードウェアの抽象化である.つまり,物理的なハードウェアをソフトウェアの一部かのように自在に操作・拡大・接続することを可能にする技術である.</p></blockquote><p>先述の The NIST Definition of Cloud Computing に戻ると,クラウドプロバイダーによるクラウドサービスの形態としては,次の三つが定義されている (<a href="#fig:nist_cloud_definition">figure_title</a>)</p><ul><li><p>Software as a Service (SaaS): クラウド上で実行されるアプリケーションをサービスとして利用者に提供する形態. 例として, Google Drive や Slack などが挙げられる. 利用者は,背後にあるクラウドのインフラ (ネットワークやサーバーなど) には直接触れず,アプリケーションとして提供されているクラウドサービスを享受する.</p></li><li><p>Platform as a Service (PaaS): 顧客の作成したアプリケーション (多くの場合データベースと API リクエスト処理を行うサーバーのコードから構成される) をデプロイする環境をサービスとして利用者に提供する形態. PaaS では利用者はクラウドのインフラに直接触れることはなく,計算負荷が増減した際のサーバーのスケーリングはクラウドプロバイダーによってなされる. 例としては, Google App Engine や Heroku などがある.</p></li><li><p>Infrastructure as a Service (IaaS): クラウド上の計算インフラストラクチャーを従量課金制で利用者に提供する形態. 利用者は必要なネットワーク・サーバー・ストレージをプロバイダーから借り受け,そこに自身のアプリケーションを展開し運用する. IaaS の例としては AWS EC2 などが挙げられる.</p></li></ul><p>本書が扱うのは,主に IaaS におけるクラウド開発である. すなわち,開発者がクラウドのインフラを直接操作し,所望のネットワーク・サーバー・ストレージなどを一から構成し,そこにアプリケーションを展開するというクラウド開発である. この意味において,クラウドの開発とは<strong>クラウドインフラストラクチャーを定義・展開するプログラムを構築するステップ</strong>と<strong>インフラ上で実際に走るアプリケーションを作成するステップ</strong>の二つに分けることができる. この二つは,プログラマーの技術としてはある程度分業を行うことが可能であるが,最も効率化・最適化されたクラウドシステムを構築するためには両方の理解が必須である. 本書では,前者 (クラウドインフラの記述) に重きを置きつつ,アプリケーションレイヤーの話題も取り扱う. PaaS とは,開発者はアプリケーションレイヤーの開発に注力し,クラウドインフラの部分はクラウドプロバイダーに依存するという概念である. PaaS は,クラウドインフラの開発が不要になることで開発の時間が短縮されるが,細かなインフラの挙動はコントロールできないという限界がある. 本書では PaaS についてはとくに取り扱わない.</p><p>SaaS は本書の文脈では開発による&quot;成果物&quot;と捉えられるだろう. すなわち, IaaS を構成するプログラムを作成し展開することによって,一般の人が利用できるようなウェブ上の計算サービスやデータベースを提供することが開発の最終ゴールである. 本書のハンズオンではその実例として,シンプルな SNS の作成 (<a href="#sec_bashoutter">Hands-on #6: Bashoutter</a>) などの演習を提供する.</p><p>なお,最近では Function as a Service (FaaS) やサーバーレスコンピューティングなども新たなクラウドのカテゴリとして認知されている. これらの概念については <a href="#sec_intro_serverless">Hands-on #5: サーバーレス入門</a> などの章で詳しく触れていく. 本書を読み進める中で明らかになるように,クラウドの技術は日進月歩である. 本書では実用的・教育的な観点から,従来的なクラウドの設計概念に触れたあと,サーバーレスなどの最新の技術も網羅するので,楽しみにしながら読み進めていただきたい.</p><p>最後にThe NIST Definition of Cloud Computing によると,クラウドの運用形態について次のような定義がなされている (<a href="#fig:nist_cloud_definition">figure_title</a>) 特定の組織・団体・企業の内部のみで使用されるクラウドを,<strong>プライベートクラウド (private cloud)</strong> とよぶ. 例えば,大学や研究機関では,その機関の構成員向けの大規模計算機サーバーが運用されていることが多い. プライベートクラウドは,組織の構成員ならば無料もしくは極めて割安のコストで計算を実行できる. しかし,使用できる計算資源の上限は限られる場合が多く,拡張時の柔軟性に欠ける場合もある.</p><p>一方,商用のサービスとして一般の顧客に向けたクラウドのことを,<strong>パブリッククラウド (public cloud)</strong> とよぶ. 有名なパブリッククラウドプラットフォームの例を挙げると, Google 社が提供する <a href="https://cloud.google.com/" target="_blank" rel="noreferrer">Google Cloud Platform (GCP)</a> Microsoft 社が提供する <a href="https://azure.microsoft.com" target="_blank" rel="noreferrer">Azure</a> Amazon 社が提供する <a href="https://aws.amazon.com" target="_blank" rel="noreferrer">Amazon Web Services (AWS)</a> などがある. パブリッククラウドを利用する場合は,プロバイダーの設定した利用料金を支払うことになる. その分,巨大なデータセンターを運用する企業の計算資源にアクセスすることができるので,計算のキャパシティは無尽蔵にあるといって過言でない.</p><p>第三のクラウドの運用形態として,コミュニティクラウド (community cloud) が挙げられる. これは,例えば政府の省庁・機関など目的・役割を共有する団体・組織が共有して運用するクラウドを指す. 最後に,ハイブリッドクラウド (hybrid cloud) という形態もあり,これはプライベート・パブリック・コミュニティクラウドの二つ以上の組み合わせによって構成されるクラウドのことである. データ保護の観点から,いくつかの機密データやプライバシーに関わる情報はプライベートクラウドに保持し,残りのシステムをパブリッククラウドに依存する,などの形態が想定される.</p><p>本書で説明するのは,基本的にパブリッククラウドを使ったクラウド開発である. 特にAmazon Web Services (AWS) を使用して,具体的な技術と概念を学んでいく. 一方で,サーバーのスケーリングや仮想計算環境などのテクニックはすべてのクラウドに共通な概念であるので,クラウドのプラットフォームが変わろうと一般に通用する知識も同時に身につくはずだ.</p><h2 id="なぜクラウドを使うのか" tabindex="-1">なぜクラウドを使うのか? <a class="header-anchor" href="#なぜクラウドを使うのか" aria-label="Permalink to &quot;なぜクラウドを使うのか?&quot;"></a></h2><p>上述のように,クラウドとはプログラムを通じて自由に計算資源を操作することのできる計算環境である. ここでは,リアルなローカル計算環境と比べて,なぜクラウドを使うと良いことがあるのかについて述べたい.</p><ol><li><p><strong>自由にサーバーのサイズをスケールできる</strong></p><p>なにか新しいプロジェクトを始めるとき,あらかじめ必要なサーバーのスペックを知るのは難しい. いきなり大きなサーバーを買うのはリスクが高い. 一方で,小さすぎるサーバーでは,後のアップグレードが面倒である. クラウドを利用すれば,プロジェクトを進めながら,必要な分だけの計算資源を確保することができる. 2. <strong>自分でサーバーをメンテナンスする必要がない</strong></p><p>悲しいことにコンピュータとは古くなるものである最近の技術の進歩の速度からすると5 年も経てば,もはや当時の最新コンピュータも化石と同じである. 5 年ごとにサーバーを入れ替えるのは相当な手間である. またサーバーの停電や故障など不意の障害への対応も必要である. クラウドでは,そのようなインフラの整備やメンテナンスはプロバイダーが自動でやってくれるので,ユーザーが心配する必要がない. 3. <strong>初期コスト 0</strong></p><p>自前の計算環境とクラウドの,経済的なコストのイメージを示したのが <a href="#cloud_economic_curve">figure_title</a> である. クラウドを利用する場合の初期コストは基本的に 0 である. その後,使った利用量に応じてコストが増大していく. 一方,自前の計算環境では,大きな初期コストが生じる. その分,初期投資後のコストの増加は,電気利用料やサーバー維持費などに留まるため,クラウドを利用した場合よりも傾きは小さくなる. 自前の計算機では,ある一定期間後,サーバーのアップグレードなどによる支出が生じることがある. 一方,クラウドを利用する場合は,そのような非連続なコストの増大は基本的に生じない. クラウドのコストのカーブが,自前計算環境のコストのカーブの下にある範囲においては,クラウドを使うことは経済的なコスト削減につながる.</p><p><img src="'+o+'" alt="クラウドと自前計算機環境の経済的コストの比較"></p></li></ol><p>とくに,**1.**の点は研究の場面では重要であると筆者は感じる. 研究をやっていて,四六時中計算を走らせ続けるという場合は少ない. むしろ,新しいアルゴリズムが完成したとき・新しいデータが届いたとき,集中的・突発的に計算タスクが増大することが多いだろう. そういったときに,フレキシブルに計算力を増強させることができるのは,クラウドを使う大きなメリットである.</p><p>ここまでクラウドを使うメリットを述べたが,逆に,デメリットというのも当然存在する.</p><ol><li><p><strong>クラウドは賢く使わないといけない</strong></p><p><a href="#cloud_economic_curve">figure_title</a> で示したコストのカーブにあるとおり,使い方によっては自前の計算環境のほうがコスト的に有利な場面は存在しうる. クラウドを利用する際は,使い終わった計算資源はすぐに削除するなど,利用者が賢く管理を行う必要があり,これを怠ると思いもしない額の請求が届く可能性がある. 2. <strong>セキュリティ</strong></p><p>クラウドは,インターネットを通じて世界のどこからでもアクセスできる状態にあり,セキュリティ管理を怠ると簡単にハッキングの対象となりうる. ハッキングを受けると,情報流出だけでなく,経済的な損失を被る可能性がある. 3. <strong>ラーニングカーブ</strong></p><p>上記のように,コスト・セキュリティなど,クラウドを利用する際に留意しなければならない点は多い. 賢くクラウドを使うには,十分なクラウドの理解が必要であり,そのラーニングカーブを乗り越える必要がある.</p></li></ol><p>Mac/Linux などでコマンドを入力するときに使用する,あの黒い画面のことを Terminal とよんだりする. この言葉の語源をご存知だろうか?</p><p><img src="'+e+'" alt="Terminal"></p><p>この言葉の語源は,コンピュータが誕生して間もない頃の時代に遡る. その頃のコンピュータというと,何千何万のという数の真空管が接続された,会議室一個分くらいのサイズのマシンであった. そのような高価でメンテが大変な機材であるから,当然みんなでシェアして使うことが前提となる. ユーザーがコンピュータにアクセスするため,マシンからは何本かのケーブルが伸び,それぞれにキーボードとスクリーンが接続されていた… これを <strong>Terminal</strong> とよんでいたのである. 人々は,代わる代わる Terminal の前に座って,計算機との対話を行っていた.</p><p>時代は流れWindows や Mac などのいわゆるパーソナルコンピュータの出現により,コンピュータはみんなで共有するものではなく,個人が所有するものになった.</p><p>最近のクラウドの台頭は,みんなで大きなコンピュータをシェアするという,最初のコンピュータの使われ方に原点回帰していると捉えることもできる. 一方で,スマートフォンやウェアラブルなどのエッジデバイスの普及も盛んであり,個人が複数の&quot;小さな&quot;コンピュータを所有する,という流れも同時に進行しているのである.</p><h1 id="aws-入門" tabindex="-1">AWS 入門 <a class="header-anchor" href="#aws-入門" aria-label="Permalink to &quot;AWS 入門&quot;"></a></h1><h2 id="aws-とは" tabindex="-1">AWS とは? <a class="header-anchor" href="#aws-とは" aria-label="Permalink to &quot;AWS とは?&quot;"></a></h2><p>本書では,クラウドの実践を行うプラットフォームとして, AWS を用いる. 実践にあたって,最低限必要な AWS の知識を本章では解説しよう.</p><p><a href="https://aws.amazon.com" target="_blank" rel="noreferrer">AWS (Amazon Web Services)</a> は Amazon 社が提供する総合的なクラウドプラットフォームである. AWS は Amazon 社が持つ膨大な計算リソースを貸し出すクラウドサービスとして2006 年に誕生した. 2021 年では,クラウドプロバイダーとして最大のマーケットシェア (約 32%) を保持している (<a href="https://www.canalys.com/newsroom/global-cloud-market-Q121" target="_blank" rel="noreferrer">参照</a>) Netflix や Slack をはじめとした多くのウェブ関連のサービスで,一部または全てのサーバーリソースが AWS から提供されているとのことである. よって,知らないうちに AWS の恩恵にあずかっている人も少なくないはずだ.</p><p>最大のシェアをもつだけに,機能・サービスの幅広さはほかのクラウドプラットフォームと比べ抜きんでている. また,利用者数が多いことを反映して,公式あるいはサードパーティによる技術紹介記事が数多くウェブ上に存在しているだけでなく,ライブラリのユーザーコミュニティも大きく問題解決が捗るのも魅力の一つだ. 初期のころウェブビジネスを行う企業がユーザーの大半を占めていたが,最近は大学などでの科学研究用途としても頻繁に用いられるようになってきている.</p><h2 id="aws-の機能・サービス" tabindex="-1">AWS の機能・サービス <a class="header-anchor" href="#aws-の機能・サービス" aria-label="Permalink to &quot;AWS の機能・サービス&quot;"></a></h2><p><a href="#fig_aws_services">figure_title</a> は,執筆時点において AWS で提供されている主要な機能・サービスの一覧である.</p><p><img src="'+t+'" alt="AWSで提供されている主要なサービス一覧"></p><p>計算,ストレージ,データベース,ネットワーク,セキュリティなど,クラウドの構築に必要な様々な要素が<strong>独立したコンポーネント</strong>として提供されている. 基本的に,これらを組み合わせることで一つのクラウドシステムができあがる.</p><p>また機械学習・音声認識・AR/VR など,特定のアプリケーションにパッケージ済みのサービスも提供されている. これらを合計すると全部で 170 個以上のサービスが提供されているとのことである (<a href="https://dev.classmethod.jp/articles/aws-summary-2020/" target="_blank" rel="noreferrer">参照</a>)</p><p>AWS の初心者が陥りがちなのは,<strong>大量のサービスの数に圧倒され,どこから手をつけたらよいのかわからなくなる</strong>,という状況である. たくさんのサービスの中から,どのサービスをどの順番で学んでいったらいいのか,その道筋すら明らかでなく,大きな参入障壁となっていることは間違いない. だが実のところ, AWS の<strong>基本的な構成要素はそのうちの数個</strong>のみに限られる. 基本要素となる機能の使い方を知れば, AWS のおおよそのリソースを使いこなすことが可能になる. ほかの機能の多くは,基本の要素を組み合わせて特定のアプリケーションに特化したパッケージとして AWS が用意したものである. そのポイントを認知することが, AWS の学習の最初のステップである.</p><p>ここでは, AWS 上でクラウドシステムを構築するときの基本となる構成要素を列挙する. これらは後のハンズオンで実際にプログラムを書きながら体験する. 現時点では,名前だけでも頭の片隅に記憶してもらえればよい.</p><h3 id="計算" tabindex="-1">計算 <a class="header-anchor" href="#計算" aria-label="Permalink to &quot;計算&quot;"></a></h3><p><img src="'+s+'" alt="S3"> <strong>EC2 (Elastic Compute Cloud)</strong> 様々なスペックの仮想マシンを作成し,計算を実行することができる. クラウドの最も基本となる構成要素である. <a href="#sec_first_ec2">Hands-on #1: 初めての EC2 インスタンスを起動する</a>, <a href="#sec_jupyter_and_deep_learning">Hands-on #2: AWS でディープラーニングを実践</a>, <a href="#sec_aws_batch">Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する</a> で詳しく触れる.</p><p><img src="'+r+'" alt="S3"> <strong>Lambda</strong> Function as a Service (FaaS) とよばれる,小さな計算を<strong>サーバーなし</strong>で実行するためのサービス. サーバーレスアーキテクチャの章 (<a href="#sec_serverless">Serverless architecture</a>) で詳しく解説する.</p><h3 id="ストレージ" tabindex="-1">ストレージ <a class="header-anchor" href="#ストレージ" aria-label="Permalink to &quot;ストレージ&quot;"></a></h3><p><img src="'+c+'" alt="S3"> <strong>EBS (Elastic Block Store)</strong> EC2 に付与することのできる仮想データドライブ. いわゆる&quot;普通の&quot;(一般的な OS で使われている)ファイルシステムを思い浮かべてくれたらよい.</p><p><img src="'+i+'" alt="S3"> <strong>S3 (Simple Storage Service)</strong> Object Storage とよばれるAPI を使ってデータの読み書きを行う,いうなれば”クラウド・ネイティブ”なデータの格納システムである. サーバーレスアーキテクチャの章 (<a href="#sec_serverless">Serverless architecture</a>) で詳しく解説する.</p><h3 id="データベース" tabindex="-1">データベース <a class="header-anchor" href="#データベース" aria-label="Permalink to &quot;データベース&quot;"></a></h3><p><img src="'+y+'" alt="S3"> <strong>DynamoDB</strong> NoSQL 型のデータベースサービス (知っている人は <code>mongoDB</code> などを思い浮かべたらよい) サーバーレスアーキテクチャの章 (<a href="#sec_serverless">Serverless architecture</a>) で詳しく解説する.</p><h3 id="ネットワーク" tabindex="-1">ネットワーク <a class="header-anchor" href="#ネットワーク" aria-label="Permalink to &quot;ネットワーク&quot;"></a></h3><p><img src="'+a+'" alt="S3"> <strong>VPC(Virtual Private Cloud)</strong> AWS 上に仮想ネットワーク環境を作成し,仮想サーバー間の接続を定義したり,外部からのアクセスなどを管理する. EC2 は VPC の内部に配置されなければならない.</p><p><strong>API Gateway</strong> <img src="'+d+'" alt="S3"> API のエンドポイントとバックエンドのサービス (Lambda など) を接続する際に用いる,リバースプロキシとしての役割を担う. <a href="#sec_bashoutter">Hands-on #6: Bashoutter</a> で詳しく解説する.</p><h2 id="region-と-availability-zone" tabindex="-1">Region と Availability Zone <a class="header-anchor" href="#region-と-availability-zone" aria-label="Permalink to &quot;Region と Availability Zone&quot;"></a></h2><p>AWS を使用する際に知っておかなければならない重要な概念として, <strong>リージョン (Region)</strong> と <strong>Availability Zone (AZ)</strong> がある (<a href="#fig_aws_regions_and_azs">figure_title</a>) 以下ではこの概念について簡単に記述する.</p><p><img src="'+u+'" alt="AWSにおける Region と Availability Zones"></p><p><strong>リージョン (Region)</strong> とは,おおまかに言うとデータセンターの所在地のことである. 執筆時点において, AWS は世界の 25 の国と地域でデータセンターを所有している. <a href="#fig_aws_regions">figure_title</a> は執筆時点で利用できるリージョンの世界地図を示している. 日本では東京と大阪にデータセンターがある. 各リージョンには固有の ID がついており,例えば東京は <code>ap-northeast-1</code>, 米国オハイオ州は <code>us-east-2</code>,などと定義されている.</p><p><img src="'+b+'" alt="Regions in AWS(出典: https://aws.amazon.com/about-aws/global-infrastructure/)"></p><p>AWS コンソールにログインすると,画面右上のメニューバーでリージョンを選択することができる(<a href="#fig_aws_console_regions">figure_title</a>, 赤丸で囲った箇所) EC2, S3 などの AWS のリソースは,リージョンごとに完全に独立である. したがって,<strong>リソースを新たにデプロイする際,あるいはデプロイ済みのリソースを閲覧する際は,コンソールのリージョンが正しく設定されているか,確認する必要がある</strong> ウェブビジネスを展開する場合などは,世界の各地にクラウドを展開する必要があるが,個人的な研究用途として用いる場合は,最寄りのリージョン (i.e. 東京) を使えば基本的に問題ない.</p><p><img src="'+A+'" alt="AWSコンソールでリージョンを選択"></p><p><code>Avaialibity Zone (AZ)</code> とは,リージョン内で地理的に隔離されたデータセンターのことである. それぞれのリージョンは 2 個以上の AZ を有しており,もし一つの AZ で火災や停電などが起きた場合でも,ほかの AZ がその障害をカバーすることができる. また, AZ 間は高速な AWS 専用ネットワーク回線で結ばれているため, AZ 間のデータ転送は極めて早い. AZ は,ビジネスなどでサーバーダウンが許容されない場合などに注意すべき概念であり,個人的な用途で使う限りにおいてはあまり深く考慮する必要はない.言葉の意味だけ知っておけば十分である.</p><p>AWS を使用する際,どこのリージョンを指定するのがよいのだろうか? インターネットの接続速度の観点からは,地理的に一番近いリージョンを使用するのが一般的によいだろう. 一方, EC2 の利用料などはリージョンごとに価格設定が若干 (10-20%程度) 異なる. したがって,自分が最も頻繁に利用するサービスの価格が最も安く設定されているリージョンを選択する,というのも重要な視点である. また,いくつかのサービスは,特定のリージョンで利用できない場合もある. これらのポイントから総合的に判断して使用するリージョンを決めると良い.</p><p>AWS Educate を利用している読者へ</p><p>執筆時点においてAWS Educate による Starter Account を使用している場合は <code>us-east-1</code> region のみ利用できる (<a href="https://awseducate-starter-account-services.s3.amazonaws.com/AWS_Educate_Starter_Account_Services_Supported.pdf" target="_blank" rel="noreferrer">参照</a>)</p><ul><li><a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html" target="_blank" rel="noreferrer">AWS documentation &quot;Regions, Availability Zones, and Local Zones&quot;</a></li></ul><h2 id="aws-でのクラウド開発" tabindex="-1">AWS でのクラウド開発 <a class="header-anchor" href="#aws-でのクラウド開発" aria-label="Permalink to &quot;AWS でのクラウド開発&quot;"></a></h2><p>AWS のクラウドの全体像がわかってきたところで,次のトピックとして,どのようにして AWS 上にクラウドの開発を行い,展開していくかについての概略を解説しよう.</p><p>AWS のリソースを追加・編集・削除するなどの操作を実行するには,<strong>コンソールを用いる</strong>方法と,<strong>API を用いる方法</strong>の,二つの経路がある.</p><h3 id="コンソール画面からリソースを操作する" tabindex="-1">コンソール画面からリソースを操作する <a class="header-anchor" href="#コンソール画面からリソースを操作する" aria-label="Permalink to &quot;コンソール画面からリソースを操作する&quot;"></a></h3><p>AWS のアカウントにログインすると,まず最初に表示されるのが<strong>AWS コンソール</strong>である (<a href="#aws_console_window">figure_title</a>)</p><p><img src="'+m+`" alt="AWSマネージメントコンソール画面"></p><p>コンソールを使うことで, EC2 のインスタンスを立ち上げたりS3 のデータを追加・削除したりログを閲覧したりなどAWS 上のあらゆるリソースの操作を GUI (Graphical User Interface) を通して実行することができる. <strong>初めて触る機能をポチポチと試したり,デバッグを行うときなどにとても便利である</strong></p><p>コンソールはさらっと機能を試したり,開発中のクラウドのデバッグをするときには便利なのであるが,実際にクラウドの開発をする場面でこれを直接いじることはあまりない. むしろ,次に紹介する API を使用して,プログラムとしてクラウドのリソースを記述することで開発を行うのが一般的である. そのような理由で,本書では AWS コンソールを使った AWS の使い方はあまり触れない. AWS のドキュメンテーションには,たくさんの <a href="https://aws.amazon.com/getting-started/hands-on/" target="_blank" rel="noreferrer">チュートリアル</a> が用意されており,コンソール画面から様々な操作を行う方法が記述されているので,興味がある読者はそちらを参照されたい.</p><h3 id="api-からリソースを操作する" tabindex="-1">API からリソースを操作する <a class="header-anchor" href="#api-からリソースを操作する" aria-label="Permalink to &quot;API からリソースを操作する&quot;"></a></h3><p><strong>API (Application Programming Interface)</strong> を使うことで,コマンドを AWS に送信し,クラウドのリソースの操作をすることができる. API とは,端的に言えば AWS が公開しているコマンドの一覧であり,<code>GET</code>, <code>POST</code>, <code>DELETE</code> などの <strong>REST API</strong> から構成されている (REST API については <a href="#sec_rest_api">REST API</a> で簡単に解説する) が,直接 REST API を入力するのは面倒であるので,その手間を解消するための様々なツールが提供されている.</p><p>例えば, <a href="https://docs.aws.amazon.com/cli/latest/index.html" target="_blank" rel="noreferrer">AWS CLI</a> は, UNIX コンソールから AWS API を実行するための CLI (Command Line Interface) である. CLI に加えて,いろいろなプログラミング言語での SDK (Software Development Kit) が提供されている.以下に一例を挙げる.</p><ul><li><p>Python ⇒ <a href="https://boto3.amazonaws.com/v1/documentation/api/latest/index.html" target="_blank" rel="noreferrer">boto3</a></p></li><li><p>Ruby ⇒ <a href="https://aws.amazon.com/sdk-for-ruby/" target="_blank" rel="noreferrer">AWS SDK for Ruby</a></p></li><li><p>Node.js ⇒ <a href="https://aws.amazon.com/sdk-for-node-js/" target="_blank" rel="noreferrer">AWS SDK for Node.js</a></p></li></ul><p>具体的な API の使用例を見てみよう.</p><p>S3 に新しい保存領域 (<code>Bucket (バケット)</code> とよばれる) を追加したいとしよう. AWS CLI を使った場合は,次のようなコマンドを打てばよい.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">s3</span><span style="color:#839496;"> </span><span style="color:#2AA198;">mb</span><span style="color:#839496;"> </span><span style="color:#2AA198;">s3://my-bucket</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--region</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ap-northeast-1</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">s3</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">mb</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">s3://my-bucket</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--region</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ap-northeast-1</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>上記のコマンドは, <code>my-bucket</code> という名前のバケットを, <code>ap-northeast-1</code> のリージョンに作成する.</p><p>Python からこれと同じ操作を実行するには, <code>boto3</code> ライブラリを使って,次のようなスクリプトを実行する.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> boto3</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;">s3_client </span><span style="color:#859900;">=</span><span style="color:#839496;"> boto3.client(</span><span style="color:#2AA198;">&quot;s3&quot;</span><span style="color:#839496;">, region_name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;ap-northeast-1&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">s3_client.create_bucket(Bucket</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;my-bucket&quot;</span><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> boto3</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;">s3_client </span><span style="color:#859900;">=</span><span style="color:#657B83;"> boto3.client(</span><span style="color:#2AA198;">&quot;s3&quot;</span><span style="color:#657B83;">, region_name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;ap-northeast-1&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">s3_client.create_bucket(Bucket</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;my-bucket&quot;</span><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>もう一つ例をあげよう.</p><p>新しい EC2 のインスタンス(インスタンスとは,起動状態にある仮想サーバーの意味である)を起動するには,次のようなコマンドを打てば良い.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ec2</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run-instances</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--image-id</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ami-xxxxxxxx</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--count</span><span style="color:#839496;"> </span><span style="color:#D33682;">1</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--instance-type</span><span style="color:#839496;"> </span><span style="color:#2AA198;">t2.micro</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--key-name</span><span style="color:#839496;"> </span><span style="color:#2AA198;">MyKeyPair</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--security-group-ids</span><span style="color:#839496;"> </span><span style="color:#2AA198;">sg-903004f8</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--subnet-id</span><span style="color:#839496;"> </span><span style="color:#2AA198;">subnet-6e7f829e</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ec2</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run-instances</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--image-id</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ami-xxxxxxxx</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--count</span><span style="color:#657B83;"> </span><span style="color:#D33682;">1</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--instance-type</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">t2.micro</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--key-name</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">MyKeyPair</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--security-group-ids</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">sg-903004f8</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--subnet-id</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">subnet-6e7f829e</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>このコマンドにより, <a href="https://aws.amazon.com/ec2/instance-types/t2/" target="_blank" rel="noreferrer">t2.micro</a> というタイプ (1 vCPU, 1.0 GB RAM) のインスタンスが起動する. ここではその他のパラメータの詳細の説明は省略する (ハンズオン (<a href="#sec_first_ec2">Hands-on #1: 初めての EC2 インスタンスを起動する</a>) で詳しく解説する)</p><p>Python から上記と同じ操作を実行するには,以下のようなスクリプトを使う.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> boto3</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;">ec2_client </span><span style="color:#859900;">=</span><span style="color:#839496;"> boto3.client(</span><span style="color:#2AA198;">&quot;ec2&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">ec2_client.run_instances(</span></span>
<span class="line"><span style="color:#839496;"> ImageId</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;ami-xxxxxxxxx&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> MinCount</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> MaxCount</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> KeyName</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;MyKeyPair&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> InstanceType</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;t2.micro&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> SecurityGroupIds</span><span style="color:#859900;">=</span><span style="color:#839496;">[</span><span style="color:#2AA198;">&quot;sg-903004f8&quot;</span><span style="color:#839496;">],</span></span>
<span class="line"><span style="color:#839496;"> SubnetId</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;subnet-6e7f829e&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> boto3</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;">ec2_client </span><span style="color:#859900;">=</span><span style="color:#657B83;"> boto3.client(</span><span style="color:#2AA198;">&quot;ec2&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">ec2_client.run_instances(</span></span>
<span class="line"><span style="color:#657B83;"> ImageId</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;ami-xxxxxxxxx&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> MinCount</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> MaxCount</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> KeyName</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;MyKeyPair&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> InstanceType</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;t2.micro&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> SecurityGroupIds</span><span style="color:#859900;">=</span><span style="color:#657B83;">[</span><span style="color:#2AA198;">&quot;sg-903004f8&quot;</span><span style="color:#657B83;">],</span></span>
<span class="line"><span style="color:#657B83;"> SubnetId</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;subnet-6e7f829e&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>以上の例を通じてAPI によるクラウドのリソースの操作のイメージがつかめてきただろうか? コマンド一つで,新しい仮想サーバーを起動したり,データの保存領域を追加したり,任意の操作を実行できるわけである. 基本的に,このようなコマンドを複数組み合わせていくことで,自分の望む CPU・RAM・ネットワーク・ストレージが備わった計算環境を構築することができる もちろん,逆の操作 (リソースの削除) も API を使って実行できる.</p><h3 id="ミニ・ハンズオン-aws-cli-を使ってみよう" tabindex="-1">ミニ・ハンズオン: AWS CLI を使ってみよう <a class="header-anchor" href="#ミニ・ハンズオン-aws-cli-を使ってみよう" aria-label="Permalink to &quot;ミニ・ハンズオン: AWS CLI を使ってみよう&quot;"></a></h3><p>ここではミニ・ハンズオンとしてAWS CLI を実際に使ってみる. AWS CLI は先述のとおり, AWS 上の任意のリソースの操作が可能であるが,ここでは一番シンプルな,<strong>S3 を使ったファイルの読み書きを実践する</strong> (EC2 の操作は少し複雑なので,第一回ハンズオンで行う) <code>aws s3</code> コマンドの詳しい使い方は <a href="https://docs.aws.amazon.com/cli/latest/reference/s3/index.html#cli-aws-s3" target="_blank" rel="noreferrer">公式ドキュメンテーション</a>を参照.</p><p>AWS CLI のインストールについては, <a href="#aws_cli_install">AWS CLI のインストール</a> を参照.</p><p>以下に紹介するハンズオンは,基本的に <a href="https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&amp;all-free-tier.sort-order=asc" target="_blank" rel="noreferrer">S3 の無料枠</a> の範囲内で実行することができる.</p><p>以下のコマンドを実行する前にAWS の認証情報が正しく設定されていることを確認する. これには <code>~/.aws/credentials</code> のファイルに設定が書き込まれているか,環境変数 (<code>AWS_ACCESS_KEY_ID</code>, <code>AWS_SECRET_ACCESS_KEY</code>, <code>AWS_DEFAULT_REGION</code>) が定義されている必要がある. 詳しくは <a href="#aws_cli_install">AWS CLI のインストール</a> を参照.</p><p>まずはS3 にデータの格納領域 (<code>Bucket</code> とよばれる.一般的な OS での&quot;ドライブ&quot;に相当する) を作成するところから始めよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">bucketName=&quot;mybucket-$(</span><span style="color:#268BD2;">openssl</span><span style="color:#2AA198;"> rand </span><span style="color:#CB4B16;">-hex</span><span style="color:#2AA198;"> </span><span style="color:#D33682;">12</span><span style="color:#2AA198;">)&quot;</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">echo</span><span style="color:#839496;"> </span><span style="color:#268BD2;">$bucketName</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">s3</span><span style="color:#839496;"> </span><span style="color:#2AA198;">mb</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;s3://</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">bucketName</span><span style="color:#859900;">}</span><span style="color:#2AA198;">&quot;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">bucketName=&quot;mybucket-$(</span><span style="color:#268BD2;">openssl</span><span style="color:#2AA198;"> rand </span><span style="color:#CB4B16;">-hex</span><span style="color:#2AA198;"> </span><span style="color:#D33682;">12</span><span style="color:#2AA198;">)&quot;</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">echo</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">$bucketName</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">s3</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">mb</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;s3://</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">bucketName</span><span style="color:#859900;">}</span><span style="color:#2AA198;">&quot;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>S3 のバケットの名前は, AWS 全体で一意的でなければならないことから,前述のコマンドではランダムな文字列を含んだバケットの名前を生成し,<code>bucketName</code> という変数に格納している. そして, <code>aws s3 mb</code> (<code>mb</code> は make bucket の略) によって,新しいバケットを作成する.</p><p>次に,バケットの一覧を取得してみよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">s3</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ls</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">2020-06-07</span><span style="color:#839496;"> </span><span style="color:#D33682;">23</span><span style="color:#2AA198;">:45:44</span><span style="color:#839496;"> </span><span style="color:#2AA198;">mybucket-c6f93855550a72b5b66f5efe</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">s3</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ls</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">2020-06-07</span><span style="color:#657B83;"> </span><span style="color:#D33682;">23</span><span style="color:#2AA198;">:45:44</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">mybucket-c6f93855550a72b5b66f5efe</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>先ほど作成したバケットがリストにあることを確認できる.</p><p>本書のノーテーションとして,コマンドラインに入力するコマンドは,それがコマンドであると明示する目的で先頭に <code>$</code> がつけてある. <code>$</code> はコマンドをコピー&amp;ペーストするときは除かなければならない. 逆に,コマンドの出力は <code>$</code> なしで表示されている.</p><p>次に,バケットにファイルをアップロードする.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">echo</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;Hello world&quot;</span><span style="color:#839496;"> </span><span style="color:#859900;">&gt;</span><span style="color:#839496;"> </span><span style="color:#2AA198;">hello_world.txt</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">s3</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cp</span><span style="color:#839496;"> </span><span style="color:#2AA198;">hello_world.txt</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;s3://</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">bucketName</span><span style="color:#859900;">}</span><span style="color:#2AA198;">/hello_world.txt&quot;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">echo</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;Hello world&quot;</span><span style="color:#657B83;"> </span><span style="color:#859900;">&gt;</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">hello_world.txt</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">s3</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cp</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">hello_world.txt</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;s3://</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">bucketName</span><span style="color:#859900;">}</span><span style="color:#2AA198;">/hello_world.txt&quot;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>上では <code>hello_world.txt</code> というダミーのファイルを作成して,それをアップロードした.</p><p>それでは,バケットの中にあるファイルの一覧を取得してみる.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">s3</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ls</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;s3://</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">bucketName</span><span style="color:#859900;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--human-readable</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">2020-06-07</span><span style="color:#839496;"> </span><span style="color:#D33682;">23</span><span style="color:#2AA198;">:54:19</span><span style="color:#839496;"> </span><span style="color:#D33682;">13</span><span style="color:#839496;"> </span><span style="color:#2AA198;">Bytes</span><span style="color:#839496;"> </span><span style="color:#2AA198;">hello_world.txt</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">s3</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ls</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;s3://</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">bucketName</span><span style="color:#859900;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--human-readable</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">2020-06-07</span><span style="color:#657B83;"> </span><span style="color:#D33682;">23</span><span style="color:#2AA198;">:54:19</span><span style="color:#657B83;"> </span><span style="color:#D33682;">13</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">Bytes</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">hello_world.txt</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>先ほどアップロードしたファイルがたしかに存在することがわかる.</p><p>最後に,使い終わったバケットを削除する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">s3</span><span style="color:#839496;"> </span><span style="color:#2AA198;">rb</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;s3://</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">bucketName</span><span style="color:#859900;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--force</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">s3</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">rb</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;s3://</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">bucketName</span><span style="color:#859900;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--force</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p><code>rb</code> は remove bucket の略である. デフォルトでは,バケットの中にファイルが存在すると削除できない. 空でないバケットを強制的に削除するには <code>--force</code> のオプションを付ける.</p><p>以上のようにAWS CLI を使って S3 バケットに対しての一連の操作を実行できた. EC2 や Lambda, DynamoDB などについても同様に AWS CLI を使ってあらゆる操作を実行できる.</p><p><strong>Amazon Resource Name (ARN)</strong></p><p>AWS 上のあらゆるリソースには, Amazon Resource Name (ARN) という固有の ID が付与されている. ARN は <code>arn:aws:s3:::my_bucket/</code> のようなフォーマットで記述されARN を使用することで,特定の AWS リソース (S3 のバケットや EC2 のインスタンス) を一意的に参照することができる.</p><p>S3 バケットや EC2 インスタンスなどには ARN に加えて,人間が読みやすい名前を定義することも可能である. この場合はARN または名前のどちらを用いても同じリソースを参照することが可能である.</p><h2 id="cloudformation-と-aws-cdk" tabindex="-1">CloudFormation と AWS CDK <a class="header-anchor" href="#cloudformation-と-aws-cdk" aria-label="Permalink to &quot;CloudFormation と AWS CDK&quot;"></a></h2><h3 id="cloudformation-による-infrastructure-as-code-iac" tabindex="-1">CloudFormation による Infrastructure as Code (IaC) <a class="header-anchor" href="#cloudformation-による-infrastructure-as-code-iac" aria-label="Permalink to &quot;CloudFormation による Infrastructure as Code (IaC)&quot;"></a></h3><p>前節で述べたようにAWS API を使うことでクラウドの<strong>あらゆる</strong>リソースの作成・管理が可能である. よって,原理上は, API のコマンドを組み合わせていくことで,自分の作りたいクラウドを設計することができる.</p><p>しかし,ここで実用上考慮しなければならない点が一つある. AWS API には大きく分けて,<strong>リソースを操作する</strong>コマンドと,<strong>タスクを実行する</strong>コマンドがあることである (<a href="#fig_aws_iac">figure_title</a>)</p><p><img src="`+h+`" alt="AWS APIはリソースを操作するコマンドとタスクを実行するコマンドに大きく分けられるリソースを記述・管理するのに使われるのが CloudFormation と CDK である."></p><p><strong>リソースを操作する</strong>とはEC2 のインスタンスを起動したりS3 のバケットを作成したり,データベースに新たなテーブルを追加する,などの<strong>静的なリソースを準備する</strong> 操作を指す. &quot;ハコ&quot;を作る操作とよんでも良いだろう. このようなコマンドは,<strong>クラウドのデプロイ時にのみ,一度だけ実行されればよい</strong></p><p><strong>タスクを実行するコマンド</strong> とは, EC2 のインスタンスにジョブを投入したり, S3 のバケットにデータを読み書きするなどの操作を指す. これは, EC2 や S3 などのリソース (&quot;ハコ&quot;) を前提として,その内部で実行されるべき計算を記述するものである. 前者に比べてこちらは<strong>動的な操作</strong>を担当する,と捉えることもできる.</p><p>そのような観点から,<strong>インフラを記述するプログラム</strong>と<strong>タスクを実行するプログラム</strong>はある程度分けて管理されるべきである. クラウドの開発は,クラウドの(静的な)リソースを記述するプログラムを作成するステップと,インフラ上で動く動的な操作を行うプログラムを作成するステップの二段階に分けて考えることができる.</p><p>AWS での静的リソースを管理するための仕組みが, <a href="https://aws.amazon.com/cloudformation/" target="_blank" rel="noreferrer">CloudFormation</a> である. CloudFormation とは, CloudFormation の文法に従ったテキストファイルを使ってAWS のインフラを記述する仕組みである. CloudFormation を使ってたとえばEC2 のインスタンスをどれくらいのスペックで,何個起動するか,インスタンス間はどのようなネットワークで結び,どのようなアクセス権限を付与するか,などのリソースの要件を逐次的に記述することができる. 一度 CloudFormation ファイルができ上がれば,それにしたがったクラウドシステムをコマンド一つで AWS 上に展開することができる. またCloudFormation ファイルを交換することで,全く同一のクラウド環境を他者が簡単に再現することも可能になる. このように,本来は物理的な実体のあるハードウェアを,プログラムによって記述し,管理するという考え方を,**Infrastructure as Code (IaC)**とよぶ.</p><p>CloudFormation を記述するには,基本的に <strong>JSON</strong> (JavaScript Object Notation) とよばれるフォーマットを使う. 次のコードはJSON で記述された CloudFormation ファイルの一例 (抜粋) である.</p><div class="language-json vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#2AA198;">&quot;Resources&quot;</span><span style="color:#839496;"> : {</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#DC322F;">...</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">&quot;WebServer&quot;</span><span style="color:#839496;">: {</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">&quot;Type&quot;</span><span style="color:#839496;"> : </span><span style="color:#2AA198;">&quot;AWS::EC2::Instance&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">&quot;Properties&quot;</span><span style="color:#839496;">: {</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">&quot;ImageId&quot;</span><span style="color:#839496;"> : { </span><span style="color:#859900;">&quot;Fn::FindInMap&quot;</span><span style="color:#839496;"> : [ </span><span style="color:#2AA198;">&quot;AWSRegionArch2AMI&quot;</span><span style="color:#839496;">, { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#839496;"> : </span><span style="color:#2AA198;">&quot;AWS::Region&quot;</span><span style="color:#839496;"> },</span></span>
<span class="line"><span style="color:#839496;"> { </span><span style="color:#859900;">&quot;Fn::FindInMap&quot;</span><span style="color:#839496;"> : [ </span><span style="color:#2AA198;">&quot;AWSInstanceType2Arch&quot;</span><span style="color:#839496;">, { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#839496;"> : </span><span style="color:#2AA198;">&quot;InstanceType&quot;</span><span style="color:#839496;"> }, </span><span style="color:#2AA198;">&quot;Arch&quot;</span><span style="color:#839496;"> ] } ] },</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">&quot;InstanceType&quot;</span><span style="color:#839496;"> : { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#839496;"> : </span><span style="color:#2AA198;">&quot;InstanceType&quot;</span><span style="color:#839496;"> },</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">&quot;SecurityGroups&quot;</span><span style="color:#839496;"> : [ {</span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#839496;"> : </span><span style="color:#2AA198;">&quot;WebServerSecurityGroup&quot;</span><span style="color:#839496;">} ],</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">&quot;KeyName&quot;</span><span style="color:#839496;"> : { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#839496;"> : </span><span style="color:#2AA198;">&quot;KeyName&quot;</span><span style="color:#839496;"> },</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">&quot;UserData&quot;</span><span style="color:#839496;"> : { </span><span style="color:#859900;">&quot;Fn::Base64&quot;</span><span style="color:#839496;"> : { </span><span style="color:#859900;">&quot;Fn::Join&quot;</span><span style="color:#839496;"> : [</span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#839496;">, [</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;#!/bin/bash -xe</span><span style="color:#CB4B16;">\\n</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;yum update -y aws-cfn-bootstrap</span><span style="color:#CB4B16;">\\n</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;/opt/aws/bin/cfn-init -v &quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot; --stack &quot;</span><span style="color:#839496;">, { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#839496;"> : </span><span style="color:#2AA198;">&quot;AWS::StackName&quot;</span><span style="color:#839496;"> },</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot; --resource WebServer &quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot; --configsets wordpress_install &quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot; --region &quot;</span><span style="color:#839496;">, { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#839496;"> : </span><span style="color:#2AA198;">&quot;AWS::Region&quot;</span><span style="color:#839496;"> }, </span><span style="color:#2AA198;">&quot;</span><span style="color:#CB4B16;">\\n</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;/opt/aws/bin/cfn-signal -e $? &quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot; --stack &quot;</span><span style="color:#839496;">, { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#839496;"> : </span><span style="color:#2AA198;">&quot;AWS::StackName&quot;</span><span style="color:#839496;"> },</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot; --resource WebServer &quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot; --region &quot;</span><span style="color:#839496;">, { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#839496;"> : </span><span style="color:#2AA198;">&quot;AWS::Region&quot;</span><span style="color:#839496;"> }, </span><span style="color:#2AA198;">&quot;</span><span style="color:#CB4B16;">\\n</span><span style="color:#2AA198;">&quot;</span></span>
<span class="line"><span style="color:#839496;"> ]]}}</span></span>
<span class="line"><span style="color:#839496;"> },</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#DC322F;">...</span></span>
<span class="line"><span style="color:#839496;"> },</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#DC322F;">...</span></span>
<span class="line"><span style="color:#839496;">},</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#2AA198;">&quot;Resources&quot;</span><span style="color:#657B83;"> : {</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#DC322F;">...</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">&quot;WebServer&quot;</span><span style="color:#657B83;">: {</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">&quot;Type&quot;</span><span style="color:#657B83;"> : </span><span style="color:#2AA198;">&quot;AWS::EC2::Instance&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">&quot;Properties&quot;</span><span style="color:#657B83;">: {</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">&quot;ImageId&quot;</span><span style="color:#657B83;"> : { </span><span style="color:#859900;">&quot;Fn::FindInMap&quot;</span><span style="color:#657B83;"> : [ </span><span style="color:#2AA198;">&quot;AWSRegionArch2AMI&quot;</span><span style="color:#657B83;">, { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#657B83;"> : </span><span style="color:#2AA198;">&quot;AWS::Region&quot;</span><span style="color:#657B83;"> },</span></span>
<span class="line"><span style="color:#657B83;"> { </span><span style="color:#859900;">&quot;Fn::FindInMap&quot;</span><span style="color:#657B83;"> : [ </span><span style="color:#2AA198;">&quot;AWSInstanceType2Arch&quot;</span><span style="color:#657B83;">, { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#657B83;"> : </span><span style="color:#2AA198;">&quot;InstanceType&quot;</span><span style="color:#657B83;"> }, </span><span style="color:#2AA198;">&quot;Arch&quot;</span><span style="color:#657B83;"> ] } ] },</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">&quot;InstanceType&quot;</span><span style="color:#657B83;"> : { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#657B83;"> : </span><span style="color:#2AA198;">&quot;InstanceType&quot;</span><span style="color:#657B83;"> },</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">&quot;SecurityGroups&quot;</span><span style="color:#657B83;"> : [ {</span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#657B83;"> : </span><span style="color:#2AA198;">&quot;WebServerSecurityGroup&quot;</span><span style="color:#657B83;">} ],</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">&quot;KeyName&quot;</span><span style="color:#657B83;"> : { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#657B83;"> : </span><span style="color:#2AA198;">&quot;KeyName&quot;</span><span style="color:#657B83;"> },</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">&quot;UserData&quot;</span><span style="color:#657B83;"> : { </span><span style="color:#859900;">&quot;Fn::Base64&quot;</span><span style="color:#657B83;"> : { </span><span style="color:#859900;">&quot;Fn::Join&quot;</span><span style="color:#657B83;"> : [</span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#657B83;">, [</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;#!/bin/bash -xe</span><span style="color:#CB4B16;">\\n</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;yum update -y aws-cfn-bootstrap</span><span style="color:#CB4B16;">\\n</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;/opt/aws/bin/cfn-init -v &quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot; --stack &quot;</span><span style="color:#657B83;">, { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#657B83;"> : </span><span style="color:#2AA198;">&quot;AWS::StackName&quot;</span><span style="color:#657B83;"> },</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot; --resource WebServer &quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot; --configsets wordpress_install &quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot; --region &quot;</span><span style="color:#657B83;">, { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#657B83;"> : </span><span style="color:#2AA198;">&quot;AWS::Region&quot;</span><span style="color:#657B83;"> }, </span><span style="color:#2AA198;">&quot;</span><span style="color:#CB4B16;">\\n</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;/opt/aws/bin/cfn-signal -e $? &quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot; --stack &quot;</span><span style="color:#657B83;">, { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#657B83;"> : </span><span style="color:#2AA198;">&quot;AWS::StackName&quot;</span><span style="color:#657B83;"> },</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot; --resource WebServer &quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot; --region &quot;</span><span style="color:#657B83;">, { </span><span style="color:#859900;">&quot;Ref&quot;</span><span style="color:#657B83;"> : </span><span style="color:#2AA198;">&quot;AWS::Region&quot;</span><span style="color:#657B83;"> }, </span><span style="color:#2AA198;">&quot;</span><span style="color:#CB4B16;">\\n</span><span style="color:#2AA198;">&quot;</span></span>
<span class="line"><span style="color:#657B83;"> ]]}}</span></span>
<span class="line"><span style="color:#657B83;"> },</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#DC322F;">...</span></span>
<span class="line"><span style="color:#657B83;"> },</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#DC322F;">...</span></span>
<span class="line"><span style="color:#657B83;">},</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br></div></div><p>ここでは, &quot;WebServer&quot; という名前のつけられた EC2 インスタンスを定義しているかなり長大で複雑な記述であるがこれによって所望のスペック・OS をもつ EC2 インスタンスを自動的に生成することが可能になる.</p><h3 id="aws-cdk" tabindex="-1">AWS CDK <a class="header-anchor" href="#aws-cdk" aria-label="Permalink to &quot;AWS CDK&quot;"></a></h3><p>前節で紹介した CloudFormation は,見てわかるとおり大変記述が複雑であり,またそれのどれか一つにでも誤りがあってはいけない. また,基本的に&quot;テキスト&quot;を書いていくことになるので,プログラミング言語で使うような変数やクラスといった便利な概念が使えない (厳密には, CloudFormation にも変数に相当するような機能は存在する) また,記述の多くの部分は繰り返しが多く,自動化できる部分も多い.</p><p>そのような悩みを解決してくれるのが, <a href="https://aws.amazon.com/cdk/" target="_blank" rel="noreferrer">AWS Cloud Development Kit (CDK)</a> である. <strong>CDK は Python などのプログラミング言語を使って CloudFormation を自動的に生成してくれるツールである.</strong> CDK は 2019 年にリリースされたばかりの比較的新しいツールで,日々改良が進められている (<a href="https://github.com/aws/aws-cdk/releases" target="_blank" rel="noreferrer">GitHub リポジトリ</a> のリリースを見ればその開発のスピードの速さがわかるだろう) CDK は TypeScript (JavaScript), Python, Java など複数の言語でサポートされている.</p><p>CDK を使うことでCloudFormation に相当するクラウドリソースの記述を,より親しみのあるプログラミング言語を使って行うことができる. かつ,典型的なリソース操作に関してはパラメータの多くの部分を自動で決定してくれるので,記述しなければならない量もかなり削減される.</p><p>以下に Python を使った CDK のコードの一例 (抜粋) を示す.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#859900;">from</span><span style="color:#839496;"> aws_cdk </span><span style="color:#859900;">import</span><span style="color:#839496;"> (</span></span>
<span class="line"><span style="color:#839496;"> core,</span></span>
<span class="line"><span style="color:#839496;"> aws_ec2 </span><span style="color:#859900;">as</span><span style="color:#839496;"> ec2,</span></span>
<span class="line"><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-weight:bold;">class</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">MyFirstEc2</span><span style="color:#839496;">(</span><span style="color:#6C71C4;">core</span><span style="color:#839496;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#839496;">):</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(self, scope, name, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs):</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">super</span><span style="color:#839496;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> vpc </span><span style="color:#859900;">=</span><span style="color:#839496;"> ec2.Vpc(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#CB4B16;">...</span><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># some parameters</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> sg </span><span style="color:#859900;">=</span><span style="color:#839496;"> ec2.SecurityGroup(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#CB4B16;">...</span><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># some parameters</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> host </span><span style="color:#859900;">=</span><span style="color:#839496;"> ec2.Instance(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;MyGreatEc2&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> instance_type</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.InstanceType(</span><span style="color:#2AA198;">&quot;t2.micro&quot;</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> machine_image</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.MachineImage.latest_amazon_linux(),</span></span>
<span class="line"><span style="color:#839496;"> vpc</span><span style="color:#859900;">=</span><span style="color:#839496;">vpc,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#CB4B16;">...</span></span>
<span class="line"><span style="color:#839496;"> )</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#859900;">from</span><span style="color:#657B83;"> aws_cdk </span><span style="color:#859900;">import</span><span style="color:#657B83;"> (</span></span>
<span class="line"><span style="color:#657B83;"> core,</span></span>
<span class="line"><span style="color:#657B83;"> aws_ec2 </span><span style="color:#859900;">as</span><span style="color:#657B83;"> ec2,</span></span>
<span class="line"><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-weight:bold;">class</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">MyFirstEc2</span><span style="color:#657B83;">(</span><span style="color:#6C71C4;">core</span><span style="color:#657B83;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#657B83;">):</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(self, scope, name, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs):</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">super</span><span style="color:#657B83;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> vpc </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ec2.Vpc(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#CB4B16;">...</span><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># some parameters</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> sg </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ec2.SecurityGroup(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#CB4B16;">...</span><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># some parameters</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> host </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ec2.Instance(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;MyGreatEc2&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> instance_type</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.InstanceType(</span><span style="color:#2AA198;">&quot;t2.micro&quot;</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> machine_image</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.MachineImage.latest_amazon_linux(),</span></span>
<span class="line"><span style="color:#657B83;"> vpc</span><span style="color:#859900;">=</span><span style="color:#657B83;">vpc,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#CB4B16;">...</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br></div></div><p>このコードは,一つ前に示した JSON を使った CloudFormation と実質的に同じことを記述している. とても煩雑だった CloudFormation ファイルに比べて, CDK と Python を使うことで格段に短く,わかりやすく記述できることができるのがわかるだろう.</p><p>本書の主題は,<strong>CDK を使って,コードを書きながら AWS の概念や開発方法を学んでいくことである</strong> 後の章では CDK を使って様々なハンズオンを実施していく. 早速,最初のハンズオンでは, CDK を使って EC2 インスタンスを作成する方法を学んでいこう.</p><ul><li><a href="https://github.com/aws-samples/aws-cdk-examples" target="_blank" rel="noreferrer">AWS CDK Examples</a>: CDK を使ったプロジェクトの例が多数紹介されている. ここにある例をテンプレートに自分のアプリケーションの開発を進めるとよい.</li></ul><h1 id="hands-on-1-初めての-ec2-インスタンスを起動する" tabindex="-1">Hands-on #1: 初めての EC2 インスタンスを起動する <a class="header-anchor" href="#hands-on-1-初めての-ec2-インスタンスを起動する" aria-label="Permalink to &quot;Hands-on \\#1: 初めての EC2 インスタンスを起動する&quot;"></a></h1><p>ハンズオンの第一回では, CDK を使って EC2 のインスタンス(仮想サーバー)を作成しSSH でサーバーにログインする,という演習を行う. このハンズオンを終えれば,あなたは自分だけのサーバーを AWS 上に立ち上げ,自由に計算を走らせることができるようになるのである!</p><h2 id="準備" tabindex="-1">準備 <a class="header-anchor" href="#準備" aria-label="Permalink to &quot;準備&quot;"></a></h2><p>ハンズオンのソースコードは GitHub の <a href="https://github.com/andatoshiki/toshiki-notebooktree/main/handson/ec2-get-started" target="_blank" rel="noreferrer">handson/ec2-get-started</a> に置いてある.</p><p>このハンズオンは,基本的に <a href="https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&amp;all-free-tier.sort-order=asc" target="_blank" rel="noreferrer">AWS の無料枠</a> の範囲内で実行することができる.</p><p>まずは,ハンズオンを実行するための環境を整える. これらの環境整備は,後のハンズオンでも前提となるものなので確実にミスなく行っていただきたい.</p><ul><li><strong>AWS Account</strong>: ハンズオンを実行するには個人の AWS アカウントが必要である. AWS アカウントの取得については <a href="#sec:create_aws_account">AWS アカウントの取得</a> を参照のこと.</li><li><strong>Python と Node.js</strong>: 本ハンズオンを実行するにはPython (3.6 以上)Node.js (12.0 以上) がインストールされていなければならない.</li><li><strong>AWS CLI</strong>: AWS CLI のインストールについては, <a href="#aws_cli_install">AWS CLI のインストール</a> を参照. ここに記載されている認証鍵の設定も済ませておくこと.</li><li><strong>AWS CDK</strong>: AWS CDK のインストールについては, <a href="#aws_cdk_install">AWS CDK のインストール</a> を参照.</li><li><strong>ソースコードのダウンロード</strong>: 本ハンズオンで使用するプログラムのソースコードを,以下のコマンドを使って GitHub からダウンロードする.</li></ul><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">git</span><span style="color:#839496;"> </span><span style="color:#2AA198;">clone</span><span style="color:#839496;"> </span><span style="color:#2AA198;">https://github.com/tomomano/learn-aws-by-coding.git</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">git</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">clone</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">https://github.com/tomomano/learn-aws-by-coding.git</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>あるいは, <code>https://github.com/tomomano/learn-aws-by-coding</code> のページに行って,右上のダウンロードボタンからダウンロードすることもできる.</p><p><strong>Docker を使用する場合</strong></p><p>Python, Node.js, AWS CDK など,ハンズオンのプログラムを実行するために必要なプログラム/ライブラリがインストール済みの Docker image を用意した. また,ハンズオンのソースコードもパッケージ済みである. Docker の使い方を知っている読者は,これを使えば,諸々のインストールをする必要なく,すぐにハンズオンのプログラムを実行できる.</p><p>使用方法については <a href="#sec_handson_docker">ハンズオン実行用の Docker image の使い方</a> を参照のこと.</p><h2 id="ssh" tabindex="-1">SSH <a class="header-anchor" href="#ssh" aria-label="Permalink to &quot;SSH&quot;"></a></h2><p><strong>SSH (secure shell)</strong> は Unix 系のリモートサーバーに安全にアクセスするためのツールである. 本ハンズオンでは, SSH を使って仮想サーバーにアクセスする. SSH に慣れていない読者のため,簡単な説明をここで行おう.</p><p>SSH による通信はすべて暗号化されているので,機密情報をインターネットを介して安全に送受信することができる. 本ハンズオンで,リモートのサーバーにアクセスするための SSH クライアントがローカルマシンにインストールされている必要がある. SSH クライアントは Linux/Mac には標準搭載されている. Windows の場合は WSL をインストールすることで SSH クライアントを利用することを推奨する (<a href="#environments">環境構築</a> を参照)</p><p>SSH コマンドの基本的な使い方を次に示す. <code>&lt;host name&gt;</code> はアクセスする先のサーバーの IP アドレスや DNS によるホストネームが入る. <code>&lt;user name&gt;</code> は接続する先のユーザー名である.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ssh</span><span style="color:#839496;"> </span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">user</span><span style="color:#839496;"> </span><span style="color:#2AA198;">nam</span><span style="color:#839496;">e</span><span style="color:#859900;">&gt;</span><span style="color:#2AA198;">@</span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">host</span><span style="color:#839496;"> </span><span style="color:#2AA198;">nam</span><span style="color:#839496;">e</span><span style="color:#859900;">&gt;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ssh</span><span style="color:#657B83;"> </span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">user</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">nam</span><span style="color:#657B83;">e</span><span style="color:#859900;">&gt;</span><span style="color:#2AA198;">@</span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">host</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">nam</span><span style="color:#657B83;">e</span><span style="color:#859900;">&gt;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>SSH は平文のパスワードによる認証を行うこともできるが,より強固なセキュリティを施すため,<strong>公開鍵暗号方式(Public Key Cryptography)による認証</strong>を行うことが強く推奨されており, EC2 はこの方法でしかアクセスを許していない. 公開鍵暗号方式の仕組みについては各自勉強してほしい. 本ハンズオンにおいて大事なことは,<strong>EC2 インスタンスが公開鍵(Public key)を保持し,クライアントとなるコンピュータ(読者自身のコンピュータ)が秘密鍵(Private key)を保持する</strong>,という点である. EC2 のインスタンスには秘密鍵を持ったコンピュータのみがアクセスすることができる.逆に言うと,秘密鍵が漏洩すると第三者もサーバーにアクセスできることになるので,<strong>秘密鍵は絶対に漏洩することのないよう注意して管理する</strong></p><p>SSH コマンドでは,ログインのために使用する秘密鍵ファイルを <code>-i</code> もしくは <code>--identity_file</code> のオプションで指定することができる. たとえば,次のように使う.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ssh</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-i</span><span style="color:#839496;"> </span><span style="color:#2AA198;">Ec2SecretKey.pem</span><span style="color:#839496;"> </span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">user</span><span style="color:#839496;"> </span><span style="color:#2AA198;">nam</span><span style="color:#839496;">e</span><span style="color:#859900;">&gt;</span><span style="color:#2AA198;">@</span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">host</span><span style="color:#839496;"> </span><span style="color:#2AA198;">nam</span><span style="color:#839496;">e</span><span style="color:#859900;">&gt;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ssh</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-i</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">Ec2SecretKey.pem</span><span style="color:#657B83;"> </span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">user</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">nam</span><span style="color:#657B83;">e</span><span style="color:#859900;">&gt;</span><span style="color:#2AA198;">@</span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">host</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">nam</span><span style="color:#657B83;">e</span><span style="color:#859900;">&gt;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><h2 id="アプリケーションの説明" tabindex="-1">アプリケーションの説明 <a class="header-anchor" href="#アプリケーションの説明" aria-label="Permalink to &quot;アプリケーションの説明&quot;"></a></h2><p>このハンズオンで作成するアプリケーションの概要を <a href="#handson_01_architecture">figure_title</a> に示す.</p><p><img src="`+B+`" alt="ハンズオン#1で作製するアプリケーションのアーキテクチャ"></p><p>このアプリケーションではまず,<strong>VPC (Virtual Private Cloud)</strong> を使ってプライベートな仮想ネットワーク環境を立ち上げている. その VPC の public subnet の内側に,<strong>EC2 (Elatic Compute Cloud)</strong> の仮想サーバーを配置する. さらに,セキュリティのため, <strong>Security Group</strong> による EC2 インスタンスへのアクセス制限を設定している. このようにして作成された仮想サーバーにSSH を使ってアクセスし,簡単な計算を行う.</p><p><a href="#handson_01_architecture">figure_title</a> のようなアプリケーションをCDK を使って構築する.</p><p>早速ではあるが,今回のハンズオンで使用するプログラムを見てみよう (<a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/ec2-get-started/app.py" target="_blank" rel="noreferrer">handson/ec2-get-started/app.py</a>)</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#93A1A1;font-weight:bold;">class</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">MyFirstEc2</span><span style="color:#839496;">(</span><span style="color:#6C71C4;">core</span><span style="color:#839496;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#839496;">):</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#839496;">, key_name: </span><span style="color:#859900;">str</span><span style="color:#839496;">, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs) -&gt; </span><span style="color:#B58900;">None</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">super</span><span style="color:#839496;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> vpc </span><span style="color:#859900;">=</span><span style="color:#839496;"> ec2.Vpc(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;MyFirstEc2-Vpc&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> max_azs</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> cidr</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;10.10.0.0/23&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> subnet_configuration</span><span style="color:#859900;">=</span><span style="color:#839496;">[</span></span>
<span class="line"><span style="color:#839496;"> ec2.SubnetConfiguration(</span></span>
<span class="line"><span style="color:#839496;"> name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;public&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> subnet_type</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.SubnetType.</span><span style="color:#CB4B16;">PUBLIC</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> ],</span></span>
<span class="line"><span style="color:#839496;"> nat_gateways</span><span style="color:#859900;">=</span><span style="color:#D33682;">0</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> sg </span><span style="color:#859900;">=</span><span style="color:#839496;"> ec2.SecurityGroup(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;MyFirstEc2Vpc-Sg&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> vpc</span><span style="color:#859900;">=</span><span style="color:#839496;">vpc,</span></span>
<span class="line"><span style="color:#839496;"> allow_all_outbound</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> sg.add_ingress_rule(</span></span>
<span class="line"><span style="color:#839496;"> peer</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.Peer.any_ipv4(),</span></span>
<span class="line"><span style="color:#839496;"> connection</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.Port.tcp(</span><span style="color:#D33682;">22</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> host </span><span style="color:#859900;">=</span><span style="color:#839496;"> ec2.Instance(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;MyFirstEc2Instance&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> instance_type</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.InstanceType(</span><span style="color:#2AA198;">&quot;t2.micro&quot;</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> machine_image</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.MachineImage.latest_amazon_linux(),</span></span>
<span class="line"><span style="color:#839496;"> vpc</span><span style="color:#859900;">=</span><span style="color:#839496;">vpc,</span></span>
<span class="line"><span style="color:#839496;"> vpc_subnets</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.SubnetSelection(subnet_type</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.SubnetType.</span><span style="color:#CB4B16;">PUBLIC</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> security_group</span><span style="color:#859900;">=</span><span style="color:#839496;">sg,</span></span>
<span class="line"><span style="color:#839496;"> key_name</span><span style="color:#859900;">=</span><span style="color:#839496;">key_name</span></span>
<span class="line"><span style="color:#839496;"> )</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#586E75;font-weight:bold;">class</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">MyFirstEc2</span><span style="color:#657B83;">(</span><span style="color:#6C71C4;">core</span><span style="color:#657B83;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#657B83;">):</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#657B83;">, key_name: </span><span style="color:#859900;">str</span><span style="color:#657B83;">, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs) -&gt; </span><span style="color:#B58900;">None</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">super</span><span style="color:#657B83;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> vpc </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ec2.Vpc(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;MyFirstEc2-Vpc&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> max_azs</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> cidr</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;10.10.0.0/23&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> subnet_configuration</span><span style="color:#859900;">=</span><span style="color:#657B83;">[</span></span>
<span class="line"><span style="color:#657B83;"> ec2.SubnetConfiguration(</span></span>
<span class="line"><span style="color:#657B83;"> name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;public&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> subnet_type</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.SubnetType.</span><span style="color:#CB4B16;">PUBLIC</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> ],</span></span>
<span class="line"><span style="color:#657B83;"> nat_gateways</span><span style="color:#859900;">=</span><span style="color:#D33682;">0</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> sg </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ec2.SecurityGroup(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;MyFirstEc2Vpc-Sg&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> vpc</span><span style="color:#859900;">=</span><span style="color:#657B83;">vpc,</span></span>
<span class="line"><span style="color:#657B83;"> allow_all_outbound</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> sg.add_ingress_rule(</span></span>
<span class="line"><span style="color:#657B83;"> peer</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.Peer.any_ipv4(),</span></span>
<span class="line"><span style="color:#657B83;"> connection</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.Port.tcp(</span><span style="color:#D33682;">22</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> host </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ec2.Instance(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;MyFirstEc2Instance&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> instance_type</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.InstanceType(</span><span style="color:#2AA198;">&quot;t2.micro&quot;</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> machine_image</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.MachineImage.latest_amazon_linux(),</span></span>
<span class="line"><span style="color:#657B83;"> vpc</span><span style="color:#859900;">=</span><span style="color:#657B83;">vpc,</span></span>
<span class="line"><span style="color:#657B83;"> vpc_subnets</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.SubnetSelection(subnet_type</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.SubnetType.</span><span style="color:#CB4B16;">PUBLIC</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> security_group</span><span style="color:#859900;">=</span><span style="color:#657B83;">sg,</span></span>
<span class="line"><span style="color:#657B83;"> key_name</span><span style="color:#859900;">=</span><span style="color:#657B83;">key_name</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br></div></div><ul><li><p>まず最初にVPC を定義する.</p></li><li><p>次に, security group (SG) を定義している. ここでは,任意の IPv4 のアドレスからの,ポート 22 (SSH の接続に使用される)への接続を許可している. それ以外の接続は拒絶される.</p></li><li><p>最後に,上記で作った VPC と SG が付与された EC2 インスタンスを作成している. インスタンスタイプは <code>t2.micro</code> を選択し, <a href="https://aws.amazon.com/amazon-linux-ami/" target="_blank" rel="noreferrer">Amazon Linux</a> を OS として設定している.</p></li></ul><p>それぞれについて,もう少し詳しく説明しよう.</p><h3 id="vpc-virtual-private-cloud" tabindex="-1">VPC (Virtual Private Cloud) <a class="header-anchor" href="#vpc-virtual-private-cloud" aria-label="Permalink to &quot;VPC (Virtual Private Cloud)&quot;"></a></h3><p><strong>VPC のアイコン.</strong></p><p><img src="`+a+`" alt="VPC"></p><p>VPC は AWS 上にプライベートな仮想ネットワーク環境を構築するツールである.高度な計算システムを構築するには,複数のサーバーを連動させて計算を行う必要があるが,そのような場合に互いのアドレスなどを管理する必要があり,そういった目的で VPC は有用である.</p><p>本ハンズオンではサーバーは一つしか起動しないのでVPC の恩恵はよく分からないかもしれないしかしEC2 インスタンスは必ず VPC の中に配置されなければならない,という制約があるので,このハンズオンでもミニマルな VPC を構成している.</p><p>興味のある読者のためにVPC のコードについてもう少し詳しく説明しよう.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">vpc </span><span style="color:#859900;">=</span><span style="color:#839496;"> ec2.Vpc(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;MyFirstEc2-Vpc&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> max_azs</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> cidr</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;10.10.0.0/23&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> subnet_configuration</span><span style="color:#859900;">=</span><span style="color:#839496;">[</span></span>
<span class="line"><span style="color:#839496;"> ec2.SubnetConfiguration(</span></span>
<span class="line"><span style="color:#839496;"> name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;public&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> subnet_type</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.SubnetType.</span><span style="color:#CB4B16;">PUBLIC</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> ],</span></span>
<span class="line"><span style="color:#839496;"> nat_gateways</span><span style="color:#859900;">=</span><span style="color:#D33682;">0</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">vpc </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ec2.Vpc(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;MyFirstEc2-Vpc&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> max_azs</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> cidr</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;10.10.0.0/23&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> subnet_configuration</span><span style="color:#859900;">=</span><span style="color:#657B83;">[</span></span>
<span class="line"><span style="color:#657B83;"> ec2.SubnetConfiguration(</span></span>
<span class="line"><span style="color:#657B83;"> name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;public&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> subnet_type</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.SubnetType.</span><span style="color:#CB4B16;">PUBLIC</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> ],</span></span>
<span class="line"><span style="color:#657B83;"> nat_gateways</span><span style="color:#859900;">=</span><span style="color:#D33682;">0</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><ul><li><p><code>max_azs=1</code> : このパラメータは,前章で説明した avaialibility zone (AZ) を設定している. このハンズオンでは,特にデータセンターの障害などを気にする必要はないので <code>1</code> にしている.</p></li><li><p><code>cidr=&quot;10.10.0.0/23&quot;</code> : このパラメータはVPC 内の IPv4 のレンジを指定している. CIDR 記法については, <a href="https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing" target="_blank" rel="noreferrer">Wikipedia</a>などを参照. <code>10.10.0.0/23</code> は <code>10.10.0.0</code> から <code>10.10.1.255</code> までの 512 個の連続したアドレス範囲を指している. つまり,この VPC では最大で 512 個のユニークな IPv4 アドレスが使えることになる. 今回はサーバーは一つなので 512 個は明らかに多すぎるがVPC はアドレスの数はどれだけ作成しても無料なので,多めに作成した.</p></li><li><p><code>subnet_configuration=...</code> : このパラメータはVPC にどのようなサブネットを作るか,を決めている. サブネットの種類には <strong>private subnet</strong> と <strong>public subnet</strong> の二種類がある. private subnet は基本的にインターネットとは遮断されたサブネット環境である. インターネットと繋がっていないので,セキュリティは極めて高く, VPC 内のサーバーとのみ通信を行えばよい EC2 インスタンスはここに配置する. Public subnet とはインターネットに繋がったサブネットである. 本ハンズオンで作成するサーバーは,外から SSH でログインを行いたいので, Public subnet 内に配置する. より詳細な記述は <a href="https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html#vpc-subnet-basics" target="_blank" rel="noreferrer">公式ドキュメンテーション</a> を参照.</p></li><li><p><code>natgateways=0</code> : これは少し高度な内容なので省略する (興味のある読者は <a href="https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html" target="_blank" rel="noreferrer">公式ドキュメンテーション</a>を参照) が,<strong>これを 0 にしておかないとNAT Gateway の利用料金が発生してしまうので,注意!</strong></p></li></ul><h3 id="security-group" tabindex="-1">Security Group <a class="header-anchor" href="#security-group" aria-label="Permalink to &quot;Security Group&quot;"></a></h3><p>Security group (SG) は, EC2 インスタンスに付与することのできる仮想ファイアーウォールである. たとえば,特定の IP アドレスから来た接続を許可・拒絶したり (インバウンド・トラフィックの制限) ,逆に特定の IP アドレスへのアクセスを禁止したり (アウトバウンド・トラフィックの制限) することができる.</p><p>コードの該当部分を見てみよう.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">sg </span><span style="color:#859900;">=</span><span style="color:#839496;"> ec2.SecurityGroup(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;MyFirstEc2Vpc-Sg&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> vpc</span><span style="color:#859900;">=</span><span style="color:#839496;">vpc,</span></span>
<span class="line"><span style="color:#839496;"> allow_all_outbound</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">sg.add_ingress_rule(</span></span>
<span class="line"><span style="color:#839496;"> peer</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.Peer.any_ipv4(),</span></span>
<span class="line"><span style="color:#839496;"> connection</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.Port.tcp(</span><span style="color:#D33682;">22</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">sg </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ec2.SecurityGroup(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;MyFirstEc2Vpc-Sg&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> vpc</span><span style="color:#859900;">=</span><span style="color:#657B83;">vpc,</span></span>
<span class="line"><span style="color:#657B83;"> allow_all_outbound</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">sg.add_ingress_rule(</span></span>
<span class="line"><span style="color:#657B83;"> peer</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.Peer.any_ipv4(),</span></span>
<span class="line"><span style="color:#657B83;"> connection</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.Port.tcp(</span><span style="color:#D33682;">22</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><p>本ハンズオンでは, SSH による外部からの接続を許容するため, <code>sg.add_ingress_rule(peer=ec2.Peer.any_ipv4(), connection=ec2.Port.tcp(22))</code> により,すべての IPv4 アドレスからのポート 22 番へのアクセスを許容している. また, SSH で EC2 インスタンスにログインしたのち,インターネットからプログラムなどをダウンロードできるよう, <code>allow_all_outbound=True</code> のパラメータを設定している.</p><p>SSH はデフォルトでは 22 番ポートを使用するのが慣例である.</p><p>セキュリティ上の観点からはSSH の接続は自宅や大学・職場など特定の地点からの接続のみを許す方が望ましい.</p><h3 id="ec2-elastic-compute-cloud" tabindex="-1">EC2 (Elastic Compute Cloud) <a class="header-anchor" href="#ec2-elastic-compute-cloud" aria-label="Permalink to &quot;EC2 (Elastic Compute Cloud)&quot;"></a></h3><p><strong>EC2 のアイコン.</strong></p><p><img src="`+s+`" alt="EC2"></p><p>EC2 は AWS 上に仮想サーバーを立ち上げるサービスである. 個々の起動状態にある仮想サーバーのことをインスタンス (instance) とよぶ (しかし,口語的なコミュニケーションにおいては,サーバーとインスタンスという言葉は相互互換的に用いられることが多い)</p><p>EC2 では用途に応じて様々なインスタンスタイプが提供されている. <a href="#ec2_instance_types">table_title</a> に,代表的なインスタンスタイプの例を挙げる (執筆時点での情報) EC2 のインスタンスタイプのすべてのリストは <a href="https://aws.amazon.com/ec2/instance-types/" target="_blank" rel="noreferrer">公式ドキュメンテーション &quot;Amazon EC2 Instance Types&quot;</a> で見ることができる.</p><table><caption>EC2 instance types</caption><colgroup><col style="width:20%;"><col style="width:20%;"><col style="width:20%;"><col style="width:20%;"><col style="width:20%;"></colgroup><thead><tr class="header"><th>Instance</th><th>vCPU</th><th>Memory (GiB)</th><th>Network bandwidth (Gbps)</th><th>Price per hour ($)</th></tr></thead><tbody><tr class="odd"><td><p>t2.micro</p></td><td><p>1</p></td><td><p>1</p></td><td><p>-</p></td><td><p>0.0116</p></td></tr><tr class="even"><td><p>t2.small</p></td><td><p>1</p></td><td><p>2</p></td><td><p>-</p></td><td><p>0.023</p></td></tr><tr class="odd"><td><p>t2.medium</p></td><td><p>2</p></td><td><p>4</p></td><td><p>-</p></td><td><p>0.0464</p></td></tr><tr class="even"><td><p>c5.24xlarge</p></td><td><p>96</p></td><td><p>192</p></td><td><p>25</p></td><td><p>4.08</p></td></tr><tr class="odd"><td><p>c5n.18xlarge</p></td><td><p>72</p></td><td><p>192</p></td><td><p>100</p></td><td><p>3.888</p></td></tr><tr class="even"><td><p>x1e.16xlarge</p></td><td><p>64</p></td><td><p>1952</p></td><td><p>10</p></td><td><p>13.344</p></td></tr></tbody></table><p><a href="#ec2_instance_types">table_title</a> からわかるように, CPU は 1 コアから 96 コアまで,メモリーは 1GB から 2TB 以上まで,ネットワーク帯域は最大で 100Gbps まで,幅広く選択することができる. また時間あたりの料金はCPU・メモリーの占有数にほぼ比例する形で増加する EC2 はサーバーの起動時間を秒単位で記録しており,<strong>利用料金は使用時間に比例する形で決定される</strong> 例えば, <code>t2.medium</code> のインスタンスを 10 時間起動した場合0.0464 * 10 = 0.464 ドルの料金が発生する.</p><p>AWS には <a href="https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&amp;all-free-tier.sort-order=asc" target="_blank" rel="noreferrer">無料利用枠</a> というものがあり, <code>t2.micro</code> であれば月に 750 時間までは無料で利用することができる.</p><p><a href="#ec2_instance_types">table_title</a> の価格は <code>us-east-1</code> のものである. リージョンによって多少価格設定が異なる.</p><p>上記で t2.micro の $0.0116 / hour という金額は, On-demand インスタンスというタイプを選択した場合の価格である. EC2 ではほかに, <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances.html" target="_blank" rel="noreferrer">Spot instance</a> とよばれるインスタンスも存在しする. Spot instance はAWS のデータセンターの負荷が増えた場合,ユーザーのプログラムが実行中であっても AWS の判断により強制シャットダウンされる,という不便さを抱えているのだが,その分大幅に安い料金設定になっている. AWS で一時的に生じた余剰な空き CPU をユーザーに割安で貸し出す,という発想である. 科学計算やウェブサーバーなどの用途でコストを削減する目的で, Spot Instance を活用する事例も多数報告されている.</p><p>EC2 インスタンスを定義しているコードの該当部分を見てみよう.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">host </span><span style="color:#859900;">=</span><span style="color:#839496;"> ec2.Instance(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;MyFirstEc2Instance&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> instance_type</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.InstanceType(</span><span style="color:#2AA198;">&quot;t2.micro&quot;</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> machine_image</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.MachineImage.latest_amazon_linux(),</span></span>
<span class="line"><span style="color:#839496;"> vpc</span><span style="color:#859900;">=</span><span style="color:#839496;">vpc,</span></span>
<span class="line"><span style="color:#839496;"> vpc_subnets</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.SubnetSelection(subnet_type</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.SubnetType.</span><span style="color:#CB4B16;">PUBLIC</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> security_group</span><span style="color:#859900;">=</span><span style="color:#839496;">sg,</span></span>
<span class="line"><span style="color:#839496;"> key_name</span><span style="color:#859900;">=</span><span style="color:#839496;">key_name</span></span>
<span class="line"><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">host </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ec2.Instance(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;MyFirstEc2Instance&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> instance_type</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.InstanceType(</span><span style="color:#2AA198;">&quot;t2.micro&quot;</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> machine_image</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.MachineImage.latest_amazon_linux(),</span></span>
<span class="line"><span style="color:#657B83;"> vpc</span><span style="color:#859900;">=</span><span style="color:#657B83;">vpc,</span></span>
<span class="line"><span style="color:#657B83;"> vpc_subnets</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.SubnetSelection(subnet_type</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.SubnetType.</span><span style="color:#CB4B16;">PUBLIC</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> security_group</span><span style="color:#859900;">=</span><span style="color:#657B83;">sg,</span></span>
<span class="line"><span style="color:#657B83;"> key_name</span><span style="color:#859900;">=</span><span style="color:#657B83;">key_name</span></span>
<span class="line"><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><p>ここでは, <code>t2.micro</code> というインスタンスタイプを選択している. さらに, <code>machine_image</code> として, <a href="https://aws.amazon.com/amazon-linux-ami/" target="_blank" rel="noreferrer">Amazon Linux</a> を選択している (Machine image は OS と似た概念である. Machine image については, <a href="#sec_jupyter_and_deep_learning">Hands-on #2: AWS でディープラーニングを実践</a> でより詳しく触れる) さらに,上で定義した VPC, SG をこのインスタンスに付与している.</p><p>以上が,今回使用するプログラムの簡単な解説であった. ミニマルな形のプログラムではあるが,仮想サーバーを作成するのに必要なステップがおわかりいただけただろうか?</p><h2 id="プログラムを実行する" tabindex="-1">プログラムを実行する <a class="header-anchor" href="#プログラムを実行する" aria-label="Permalink to &quot;プログラムを実行する&quot;"></a></h2><p>さて,ハンズオンのコードの理解ができたところで,プログラムを実際に実行してみよう.繰り返しになるが, <a href="#handson_01_prep">準備</a> での準備ができていることが前提である.</p><h3 id="python-の依存ライブラリのインストール" tabindex="-1">Python の依存ライブラリのインストール <a class="header-anchor" href="#python-の依存ライブラリのインストール" aria-label="Permalink to &quot;Python の依存ライブラリのインストール&quot;"></a></h3><p>まずはPython の依存ライブラリをインストールする以下ではPython のライブラリを管理するツールとして, <a href="https://docs.python.org/3/library/venv.html" target="_blank" rel="noreferrer">venv</a> を使用する.</p><p>まずは, <code>handson/ec2-get-started</code> のディレクトリに移動しよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cd</span><span style="color:#839496;"> </span><span style="color:#2AA198;">handson/ec2-get-started</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cd</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">handson/ec2-get-started</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>ディレクトリを移動したら, <code>venv</code> で新しい仮想環境を作成し,インストールを実行する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python3</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#839496;"> </span><span style="color:#2AA198;">venv</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">source</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pip</span><span style="color:#839496;"> </span><span style="color:#2AA198;">install</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#839496;"> </span><span style="color:#2AA198;">requirements.txt</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python3</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">venv</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">source</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pip</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">install</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">requirements.txt</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>これで Python の環境構築は完了だ.</p><p><code>venv</code> の簡単な説明は <a href="#venv_quick_guide">Python クイックガイド</a> に記述してある.</p><p>環境によっては <code>pip</code> ではなく <code>pip3</code> あるいは <code>python3 -m pip</code> に置き換える必要がある.</p><h3 id="aws-のシークレットキーをセットする" tabindex="-1">AWS のシークレットキーをセットする <a class="header-anchor" href="#aws-のシークレットキーをセットする" aria-label="Permalink to &quot;AWS のシークレットキーをセットする&quot;"></a></h3><p>AWS CLI および AWS CDK を使うには, AWS のシークレットキーが設定されている必要がある. シークレットキーの発行については <a href="#aws_secrets">AWS のシークレットキーの作成</a> を参照のこと. シークレットキーを発行したら, <a href="#aws_cli_install">AWS CLI のインストール</a> を参照し,コマンドラインの設定を行う.</p><p>手順をここに短く要約すると,一つ目の方法は <code>AWS_ACCESS_KEY_ID</code> などの環境変数を設定するやり方である. もう一つの方法は, <code>~/.aws/credentials</code> に認証情報を保存しておく方式である. シークレットキーの設定は AWS CLI/CDK を使用するうえで共通のステップになるので,しっかりと理解しておくように.</p><h3 id="ssh-鍵を生成" tabindex="-1">SSH 鍵を生成 <a class="header-anchor" href="#ssh-鍵を生成" aria-label="Permalink to &quot;SSH 鍵を生成&quot;"></a></h3><p>EC2 インスタンスには SSH を使ってログインする. EC2 インスタンスを作成するのに先行して,今回のハンズオンで専用に使う SSH の公開鍵・秘密鍵のペアを準備する必要がある.</p><p>次の AWS CLI コマンドにより, <code>HirakeGoma</code> という名前のついた鍵を生成する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">export</span><span style="color:#839496;"> </span><span style="color:#2AA198;">KEY_NAME=&quot;HirakeGoma&quot;</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ec2</span><span style="color:#839496;"> </span><span style="color:#2AA198;">create-key-pair</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--key-name</span><span style="color:#839496;"> </span><span style="color:#859900;">\${</span><span style="color:#268BD2;">KEY_NAME</span><span style="color:#859900;">}</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--query</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&#39;KeyMaterial&#39;</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--output</span><span style="color:#839496;"> </span><span style="color:#2AA198;">text</span><span style="color:#839496;"> </span><span style="color:#859900;">&gt;</span><span style="color:#839496;"> </span><span style="color:#859900;">\${</span><span style="color:#268BD2;">KEY_NAME</span><span style="color:#859900;">}</span><span style="color:#2AA198;">.pem</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">export</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">KEY_NAME=&quot;HirakeGoma&quot;</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ec2</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">create-key-pair</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--key-name</span><span style="color:#657B83;"> </span><span style="color:#859900;">\${</span><span style="color:#268BD2;">KEY_NAME</span><span style="color:#859900;">}</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--query</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&#39;KeyMaterial&#39;</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--output</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">text</span><span style="color:#657B83;"> </span><span style="color:#859900;">&gt;</span><span style="color:#657B83;"> </span><span style="color:#859900;">\${</span><span style="color:#268BD2;">KEY_NAME</span><span style="color:#859900;">}</span><span style="color:#2AA198;">.pem</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>このコマンドを実行すると,現在のディレクトリに <code>HirakeGoma.pem</code> というファイルが作成される.これが,サーバーにアクセスするための秘密鍵である. SSH でこの鍵を使うため, <code>~/.ssh/</code> のディレクトリに鍵を移動する. さらに,秘密鍵が書き換えられたり第三者に閲覧されないよう,ファイルのアクセス権限を <code>400</code> に設定する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">mv</span><span style="color:#839496;"> </span><span style="color:#2AA198;">HirakeGoma.pem</span><span style="color:#839496;"> </span><span style="color:#2AA198;">~/.ssh/</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">chmod</span><span style="color:#839496;"> </span><span style="color:#D33682;">400</span><span style="color:#839496;"> </span><span style="color:#2AA198;">~/.ssh/HirakeGoma.pem</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">mv</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">HirakeGoma.pem</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">~/.ssh/</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">chmod</span><span style="color:#657B83;"> </span><span style="color:#D33682;">400</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">~/.ssh/HirakeGoma.pem</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h3 id="デプロイを実行" tabindex="-1">デプロイを実行 <a class="header-anchor" href="#デプロイを実行" aria-label="Permalink to &quot;デプロイを実行&quot;"></a></h3><p>これまでのステップで, EC2 インスタンスをデプロイするための準備が整った! 早速,次のコマンドによりアプリケーションを AWS にデプロイしよう. <code>-c key_name=&quot;HirakeGoma&quot;</code> というオプションで,先ほど生成した <code>HirakeGoma</code> という名前の鍵を使うよう指定している.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">deploy</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-c</span><span style="color:#839496;"> </span><span style="color:#2AA198;">key_name=&quot;HirakeGoma&quot;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">deploy</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-c</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">key_name=&quot;HirakeGoma&quot;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>このコマンドを実行すると, VPC EC2 などが AWS 上に展開される. そして,コマンドの出力の最後に <a href="#handson_01_cdk_output">figure_title</a> のような出力が得られるはずである. <strong>出力の中で <code>InstancePublicIp</code> に続く数字が,起動したインスタンスのパブリック IP アドレスである.</strong> IP アドレスはデプロイごとにランダムなアドレスが割り当てられる.</p><p><img src="`+g+'" alt="CDKデプロイ実行後の出力"></p><h3 id="ssh-でログイン" tabindex="-1">SSH でログイン <a class="header-anchor" href="#ssh-でログイン" aria-label="Permalink to &quot;SSH でログイン&quot;"></a></h3><p>早速SSH  で接続してみよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ssh</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-i</span><span style="color:#839496;"> </span><span style="color:#2AA198;">~/.ssh/HirakeGoma.pem</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ec2-user@</span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">IP</span><span style="color:#839496;"> </span><span style="color:#2AA198;">addres</span><span style="color:#839496;">s</span><span style="color:#859900;">&gt;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ssh</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-i</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">~/.ssh/HirakeGoma.pem</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ec2-user@</span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">IP</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">addres</span><span style="color:#657B83;">s</span><span style="color:#859900;">&gt;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p><code>-i</code> オプションで,先ほど生成した秘密鍵を指定している. EC2 インスタンスにはデフォルトで <code>ec2-user</code> という名前のユーザーが作られているので,それを使用する. 最後に, <code>&lt;IP address&gt;</code> の部分は自身が作成した EC2 インスタンスの IP アドレスで置き換える (<code>12.345.678.9</code> など).</p><p>ログインに成功すると, <a href="#fig_handson_01_ssh_login">figure_title</a> のような画面が表示される. リモートのサーバーにログインしているので,プロンプトが <code>[ec2-user@ip-10-10-1-217 ~]$</code> のようになっていることを確認しよう.</p><p><img src="'+_+`" alt="SSH で EC2 インスタンスにログイン"></p><p><strong>おめでとう!これで,めでたく AWS 上に EC2 仮想サーバーを起動し,リモートからアクセスできるようになった!</strong></p><h3 id="起動した-ec2-インスタンスで遊んでみる" tabindex="-1">起動した EC2 インスタンスで遊んでみる <a class="header-anchor" href="#起動した-ec2-インスタンスで遊んでみる" aria-label="Permalink to &quot;起動した EC2 インスタンスで遊んでみる&quot;"></a></h3><p>せっかく新しいインスタンスを起動したので,少し遊んでみよう.</p><p>ログインした EC2 インスタンスで,次のコマンドを実行してみよう. CPU の情報を取得することができる.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cat</span><span style="color:#839496;"> </span><span style="color:#2AA198;">/proc/cpuinfo</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">processor</span><span style="color:#839496;"> </span><span style="color:#2AA198;">:</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span></span>
<span class="line"><span style="color:#268BD2;">vendor_id</span><span style="color:#839496;"> </span><span style="color:#2AA198;">:</span><span style="color:#839496;"> </span><span style="color:#2AA198;">GenuineIntel</span></span>
<span class="line"><span style="color:#268BD2;">cpu</span><span style="color:#839496;"> </span><span style="color:#2AA198;">family</span><span style="color:#839496;"> </span><span style="color:#2AA198;">:</span><span style="color:#839496;"> </span><span style="color:#D33682;">6</span></span>
<span class="line"><span style="color:#268BD2;">model</span><span style="color:#839496;"> </span><span style="color:#2AA198;">:</span><span style="color:#839496;"> </span><span style="color:#D33682;">63</span></span>
<span class="line"><span style="color:#268BD2;">model</span><span style="color:#839496;"> </span><span style="color:#2AA198;">name</span><span style="color:#839496;"> </span><span style="color:#2AA198;">:</span><span style="color:#839496;"> </span><span style="color:#2AA198;">Intel</span><span style="color:#839496;">(</span><span style="color:#268BD2;">R</span><span style="color:#839496;">) </span><span style="color:#2AA198;">Xeon</span><span style="color:#839496;">(</span><span style="color:#268BD2;">R</span><span style="color:#839496;">) </span><span style="color:#2AA198;">CPU</span><span style="color:#839496;"> </span><span style="color:#2AA198;">E5-2676</span><span style="color:#839496;"> </span><span style="color:#2AA198;">v3</span><span style="color:#839496;"> </span><span style="color:#2AA198;">@</span><span style="color:#839496;"> </span><span style="color:#D33682;">2.40</span><span style="color:#2AA198;">GHz</span></span>
<span class="line"><span style="color:#268BD2;">stepping</span><span style="color:#839496;"> </span><span style="color:#2AA198;">:</span><span style="color:#839496;"> </span><span style="color:#D33682;">2</span></span>
<span class="line"><span style="color:#268BD2;">microcode</span><span style="color:#839496;"> </span><span style="color:#2AA198;">:</span><span style="color:#839496;"> </span><span style="color:#D33682;">0x43</span></span>
<span class="line"><span style="color:#268BD2;">cpu</span><span style="color:#839496;"> </span><span style="color:#2AA198;">MHz</span><span style="color:#839496;"> </span><span style="color:#2AA198;">:</span><span style="color:#839496;"> </span><span style="color:#D33682;">2400.096</span></span>
<span class="line"><span style="color:#268BD2;">cache</span><span style="color:#839496;"> </span><span style="color:#2AA198;">size</span><span style="color:#839496;"> </span><span style="color:#2AA198;">:</span><span style="color:#839496;"> </span><span style="color:#D33682;">30720</span><span style="color:#839496;"> </span><span style="color:#2AA198;">KB</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cat</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">/proc/cpuinfo</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">processor</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span></span>
<span class="line"><span style="color:#268BD2;">vendor_id</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">:</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">GenuineIntel</span></span>
<span class="line"><span style="color:#268BD2;">cpu</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">family</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">6</span></span>
<span class="line"><span style="color:#268BD2;">model</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">63</span></span>
<span class="line"><span style="color:#268BD2;">model</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">name</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">:</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">Intel</span><span style="color:#657B83;">(</span><span style="color:#268BD2;">R</span><span style="color:#657B83;">) </span><span style="color:#2AA198;">Xeon</span><span style="color:#657B83;">(</span><span style="color:#268BD2;">R</span><span style="color:#657B83;">) </span><span style="color:#2AA198;">CPU</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">E5-2676</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">v3</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">@</span><span style="color:#657B83;"> </span><span style="color:#D33682;">2.40</span><span style="color:#2AA198;">GHz</span></span>
<span class="line"><span style="color:#268BD2;">stepping</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">2</span></span>
<span class="line"><span style="color:#268BD2;">microcode</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0x43</span></span>
<span class="line"><span style="color:#268BD2;">cpu</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">MHz</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">2400.096</span></span>
<span class="line"><span style="color:#268BD2;">cache</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">size</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">30720</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">KB</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><p>次に,実行中のプロセスやメモリの消費を見てみよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">top</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-n</span><span style="color:#839496;"> </span><span style="color:#D33682;">1</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">top</span><span style="color:#839496;"> </span><span style="color:#2AA198;">-</span><span style="color:#839496;"> </span><span style="color:#D33682;">09</span><span style="color:#2AA198;">:29:19</span><span style="color:#839496;"> </span><span style="color:#2AA198;">up</span><span style="color:#839496;"> </span><span style="color:#D33682;">43</span><span style="color:#839496;"> </span><span style="color:#2AA198;">min,</span><span style="color:#839496;"> </span><span style="color:#D33682;">1</span><span style="color:#839496;"> </span><span style="color:#2AA198;">user,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">load</span><span style="color:#839496;"> </span><span style="color:#2AA198;">average:</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.00</span><span style="color:#2AA198;">,</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.00</span><span style="color:#2AA198;">,</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.00</span></span>
<span class="line"><span style="color:#268BD2;">Tasks:</span><span style="color:#839496;"> </span><span style="color:#D33682;">76</span><span style="color:#839496;"> </span><span style="color:#2AA198;">total,</span><span style="color:#839496;"> </span><span style="color:#D33682;">1</span><span style="color:#839496;"> </span><span style="color:#2AA198;">running,</span><span style="color:#839496;"> </span><span style="color:#D33682;">51</span><span style="color:#839496;"> </span><span style="color:#2AA198;">sleeping,</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#839496;"> </span><span style="color:#2AA198;">stopped,</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#839496;"> </span><span style="color:#2AA198;">zombie</span></span>
<span class="line"><span style="color:#268BD2;">Cpu(s</span><span style="color:#839496;">): 0.3%us, 0.3%sy, 0.1%ni, 98.9%id, 0.2%wa, 0.0%hi, 0.0%si, 0.2%st</span></span>
<span class="line"><span style="color:#268BD2;">Mem:</span><span style="color:#839496;"> </span><span style="color:#D33682;">1009140</span><span style="color:#2AA198;">k</span><span style="color:#839496;"> </span><span style="color:#2AA198;">total,</span><span style="color:#839496;"> </span><span style="color:#D33682;">270760</span><span style="color:#2AA198;">k</span><span style="color:#839496;"> </span><span style="color:#2AA198;">used,</span><span style="color:#839496;"> </span><span style="color:#D33682;">738380</span><span style="color:#2AA198;">k</span><span style="color:#839496;"> </span><span style="color:#2AA198;">free,</span><span style="color:#839496;"> </span><span style="color:#D33682;">14340</span><span style="color:#2AA198;">k</span><span style="color:#839496;"> </span><span style="color:#2AA198;">buffers</span></span>
<span class="line"><span style="color:#268BD2;">Swap:</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#2AA198;">k</span><span style="color:#839496;"> </span><span style="color:#2AA198;">total,</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#2AA198;">k</span><span style="color:#839496;"> </span><span style="color:#2AA198;">used,</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#2AA198;">k</span><span style="color:#839496;"> </span><span style="color:#2AA198;">free,</span><span style="color:#839496;"> </span><span style="color:#D33682;">185856</span><span style="color:#2AA198;">k</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cached</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">PID</span><span style="color:#839496;"> </span><span style="color:#2AA198;">USER</span><span style="color:#839496;"> </span><span style="color:#2AA198;">PR</span><span style="color:#839496;"> </span><span style="color:#2AA198;">NI</span><span style="color:#839496;"> </span><span style="color:#2AA198;">VIRT</span><span style="color:#839496;"> </span><span style="color:#2AA198;">RES</span><span style="color:#839496;"> </span><span style="color:#2AA198;">SHR</span><span style="color:#839496;"> </span><span style="color:#2AA198;">S</span><span style="color:#839496;"> </span><span style="color:#2AA198;">%CPU</span><span style="color:#839496;"> </span><span style="color:#2AA198;">%MEM</span><span style="color:#839496;"> </span><span style="color:#2AA198;">TIME+</span><span style="color:#839496;"> </span><span style="color:#2AA198;">COMMAND</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">1</span><span style="color:#839496;"> </span><span style="color:#2AA198;">root</span><span style="color:#839496;"> </span><span style="color:#D33682;">20</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#839496;"> </span><span style="color:#D33682;">19696</span><span style="color:#839496;"> </span><span style="color:#D33682;">2596</span><span style="color:#839496;"> </span><span style="color:#D33682;">2268</span><span style="color:#839496;"> </span><span style="color:#2AA198;">S</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.0</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.3</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#2AA198;">:01.21</span><span style="color:#839496;"> </span><span style="color:#2AA198;">init</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">2</span><span style="color:#839496;"> </span><span style="color:#2AA198;">root</span><span style="color:#839496;"> </span><span style="color:#D33682;">20</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#839496;"> </span><span style="color:#2AA198;">S</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.0</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.0</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#2AA198;">:00.00</span><span style="color:#839496;"> </span><span style="color:#2AA198;">kthreadd</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">3</span><span style="color:#839496;"> </span><span style="color:#2AA198;">root</span><span style="color:#839496;"> </span><span style="color:#D33682;">20</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#839496;"> </span><span style="color:#2AA198;">I</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.0</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.0</span><span style="color:#839496;"> </span><span style="color:#D33682;">0</span><span style="color:#2AA198;">:00.00</span><span style="color:#839496;"> </span><span style="color:#2AA198;">kworker/0:0</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">top</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-n</span><span style="color:#657B83;"> </span><span style="color:#D33682;">1</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">top</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">-</span><span style="color:#657B83;"> </span><span style="color:#D33682;">09</span><span style="color:#2AA198;">:29:19</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">up</span><span style="color:#657B83;"> </span><span style="color:#D33682;">43</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">min,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">1</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">user,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">load</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">average:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.00</span><span style="color:#2AA198;">,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.00</span><span style="color:#2AA198;">,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.00</span></span>
<span class="line"><span style="color:#268BD2;">Tasks:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">76</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">total,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">1</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">running,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">51</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">sleeping,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">stopped,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">zombie</span></span>
<span class="line"><span style="color:#268BD2;">Cpu(s</span><span style="color:#657B83;">): 0.3%us, 0.3%sy, 0.1%ni, 98.9%id, 0.2%wa, 0.0%hi, 0.0%si, 0.2%st</span></span>
<span class="line"><span style="color:#268BD2;">Mem:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">1009140</span><span style="color:#2AA198;">k</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">total,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">270760</span><span style="color:#2AA198;">k</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">used,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">738380</span><span style="color:#2AA198;">k</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">free,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">14340</span><span style="color:#2AA198;">k</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">buffers</span></span>
<span class="line"><span style="color:#268BD2;">Swap:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#2AA198;">k</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">total,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#2AA198;">k</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">used,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#2AA198;">k</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">free,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">185856</span><span style="color:#2AA198;">k</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cached</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">PID</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">USER</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">PR</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">NI</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">VIRT</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">RES</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">SHR</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">S</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">%CPU</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">%MEM</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">TIME+</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">COMMAND</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">1</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">root</span><span style="color:#657B83;"> </span><span style="color:#D33682;">20</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#657B83;"> </span><span style="color:#D33682;">19696</span><span style="color:#657B83;"> </span><span style="color:#D33682;">2596</span><span style="color:#657B83;"> </span><span style="color:#D33682;">2268</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">S</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.0</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.3</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#2AA198;">:01.21</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">init</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">2</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">root</span><span style="color:#657B83;"> </span><span style="color:#D33682;">20</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">S</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.0</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.0</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#2AA198;">:00.00</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">kthreadd</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">3</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">root</span><span style="color:#657B83;"> </span><span style="color:#D33682;">20</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">I</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.0</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.0</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0</span><span style="color:#2AA198;">:00.00</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">kworker/0:0</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p><code>t2.micro</code> インスタンスなので, 1009140k = 1GB のメモリーがあることがわかる.</p><p>今回起動したインスタンスには Python 2 はインストール済みだが, Python 3 は入っていない. Python 3.6 のインストールを行ってみよう. インストールは簡単である.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">sudo</span><span style="color:#839496;"> </span><span style="color:#2AA198;">yum</span><span style="color:#839496;"> </span><span style="color:#2AA198;">update</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-y</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">sudo</span><span style="color:#839496;"> </span><span style="color:#2AA198;">yum</span><span style="color:#839496;"> </span><span style="color:#2AA198;">install</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-y</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python36</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">sudo</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">yum</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">update</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-y</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">sudo</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">yum</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">install</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-y</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python36</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>インストールした Python を起動してみよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python3</span></span>
<span class="line"><span style="color:#268BD2;">Python</span><span style="color:#839496;"> </span><span style="color:#D33682;">3.6</span><span style="color:#2AA198;">.10</span><span style="color:#839496;"> (default, </span><span style="color:#2AA198;">Feb</span><span style="color:#839496;"> </span><span style="color:#D33682;">10</span><span style="color:#839496;"> </span><span style="color:#D33682;">2020</span><span style="color:#2AA198;">,</span><span style="color:#839496;"> </span><span style="color:#D33682;">19</span><span style="color:#2AA198;">:55:14</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">[GCC </span><span style="color:#D33682;">4.8</span><span style="color:#839496;">.5 </span><span style="color:#D33682;">20150623</span><span style="color:#839496;"> (Red Hat </span><span style="color:#D33682;">4.8</span><span style="color:#839496;">.5-28)] on linux</span></span>
<span class="line"><span style="color:#268BD2;">Type</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;help&quot;,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;copyright&quot;,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;credits&quot;</span><span style="color:#839496;"> </span><span style="color:#2AA198;">or</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;license&quot;</span><span style="color:#839496;"> </span><span style="color:#2AA198;">for</span><span style="color:#839496;"> </span><span style="color:#2AA198;">more</span><span style="color:#839496;"> </span><span style="color:#2AA198;">information.</span></span>
<span class="line"><span style="color:#839496;">&gt;&gt;&gt;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python3</span></span>
<span class="line"><span style="color:#268BD2;">Python</span><span style="color:#657B83;"> </span><span style="color:#D33682;">3.6</span><span style="color:#2AA198;">.10</span><span style="color:#657B83;"> (default, </span><span style="color:#2AA198;">Feb</span><span style="color:#657B83;"> </span><span style="color:#D33682;">10</span><span style="color:#657B83;"> </span><span style="color:#D33682;">2020</span><span style="color:#2AA198;">,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">19</span><span style="color:#2AA198;">:55:14</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">[GCC </span><span style="color:#D33682;">4.8</span><span style="color:#657B83;">.5 </span><span style="color:#D33682;">20150623</span><span style="color:#657B83;"> (Red Hat </span><span style="color:#D33682;">4.8</span><span style="color:#657B83;">.5-28)] on linux</span></span>
<span class="line"><span style="color:#268BD2;">Type</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;help&quot;,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;copyright&quot;,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;credits&quot;</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">or</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;license&quot;</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">for</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">more</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">information.</span></span>
<span class="line"><span style="color:#657B83;">&gt;&gt;&gt;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>Python のインタープリタが起動した! <code>Ctrl + D</code> あるいは <code>exit()</code> と入力することで,インタープリタを閉じることができる.</p><p>さて,サーバーでのお遊びはこんなところにしておこう (興味があれば各自いろいろと試してみると良い) 次のコマンドでログアウトする.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">exit</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">exit</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><h3 id="aws-コンソールから確認" tabindex="-1">AWS コンソールから確認 <a class="header-anchor" href="#aws-コンソールから確認" aria-label="Permalink to &quot;AWS コンソールから確認&quot;"></a></h3><p>これまでは,すべてコマンドラインから EC2 に関連する操作を行ってきた. EC2 インスタンスの状態を確認したりサーバーをシャットダウンするなどの操作はAWS コンソールから実行することもできる. 軽くこれを紹介しよう.</p><p>まず,ウェブブラウザを開いて AWS コンソールにログインする. ログインしたら, <code>Services</code> から <code>EC2</code> を検索(選択)する. 次に,左のサイドバーの <code>Instances</code> とページをたどる. すると, <a href="#aws_ec2_console">figure_title</a> のような画面が得られるはずである. この画面で,自分のアカウントの管理下にあるインスタンスを確認できる. 同様にVPC・SG についてもコンソールから確認できる.</p><p><img src="`+f+'" alt="EC2 コンソール画面"></p><p><strong>コンソール右上で,正しいリージョン (今回の場合は ap-northeast-1, Tokyo) が選択されているか,注意する!</strong></p><p>前章で CloudFormation について触れたが今回デプロイしたアプリケーションもCloudFormation のスタックとして管理されている. <strong>スタック (stack)</strong> とは, AWS リソースの集合のことを指す. 今回の場合は, VPC/EC2/SG などがスタックの中に含まれている. コンソールで <code>CloudFormation</code> のページに行ってみよう (<a href="#aws_cloudformation_console">figure_title</a>)</p><p><img src="'+k+'" alt="CloudFormation コンソール画面"></p><p>&quot;MyFirstEc2&quot; という名前のスタックがあることが確認できる. クリックをして中身を見てみるとEC2, VPC などのリソースがこのスタックに紐付いていることがわかる.</p><h3 id="スタックを削除" tabindex="-1">スタックを削除 <a class="header-anchor" href="#スタックを削除" aria-label="Permalink to &quot;スタックを削除&quot;"></a></h3><p>これにて,第一回のハンズオンで説明すべき事柄はすべて完了した. 最後に,使わなくなったスタックを削除しよう. スタックの削除には,二つの方法がある.</p><p>一つ目の方法は,前節の Cloudformation のコンソール画面で, &quot;Delete&quot; ボタンを押すことである (<a href="#cloudformation_delete">figure_title</a>) すると,スタックの状態が <code>&quot;DELETE_IN_PROGRESS&quot;</code> に変わり,削除が完了すると CloudFormation のスタックの一覧から消える.</p><p><img src="'+v+'" alt="CloudFormationコンソール画面からスタックを削除"></p><p>二つ目の方法は,コマンドラインから行う方法である. 先ほど,デプロイを行ったコマンドラインに戻ろう. そうしたら,次のコマンドを実行する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>このコマンドを実行すると,スタックの削除が始まる. 削除した後はVPC, EC2 など,すべて跡形もなく消え去っていることを自身で確かめよう. CloudFormation を用いることで関連するすべての AWS リソースを一度に管理・削除することができるので,大変便利である.</p><p><strong>スタックの削除は各自で必ず行うこと!</strong> 行わなかった場合, EC2 インスタンスの料金が発生し続けることになる!</p><p>また,本ハンズオンのために作成した SSH 鍵ペアも不要なので,削除しておく. まず, EC2 側に登録してある公開鍵を削除する. これも,コンソールおよびコマンドラインの二つの方法で実行できる.</p><p>コンソールから実行するには, <code>EC2</code> の画面に行き,左のサイドバーの <code>Key Pairs</code> を選択する. 鍵の一覧が表示されるので, <code>HirakeGoma</code> とある鍵にチェックを入れ,画面右上の <code>Actions</code> から, <code>Delete</code> を実行する (<a href="#delete_ec2_key_pair">figure_title</a>)</p><p><img src="'+q+'" alt="EC2でSSH鍵ペアを削除"></p><p>コマンドラインから実行するには,次のコマンドを使う.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ec2</span><span style="color:#839496;"> </span><span style="color:#2AA198;">delete-key-pair</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--key-name</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;HirakeGoma&quot;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ec2</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">delete-key-pair</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--key-name</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;HirakeGoma&quot;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>最後に,ローカルのコンピュータから鍵を削除する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">rm</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-f</span><span style="color:#839496;"> </span><span style="color:#2AA198;">~/.ssh/HirakeGoma.pem</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">rm</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-f</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">~/.ssh/HirakeGoma.pem</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>これで,クラウドの片付けもすべて終了だ.</p><p>なお,頻繁に EC2 インスタンスを起動したりする場合は,いちいち SSH 鍵を削除する必要はない.</p><h2 id="小括" tabindex="-1">小括 <a class="header-anchor" href="#小括" aria-label="Permalink to &quot;小括&quot;"></a></h2><p>ここまでが,本書の第一部の内容である. 盛りだくさんの内容であったが,ついてこれたであろうか?</p><p><a href="#chap_cloud_basics">クラウド概論</a> では,クラウドの定義と用語の説明を行ったあと,なぜクラウドを使うのか,という点を議論した. 続いて <a href="#sec_aws_general_introduction">AWS 入門</a> では,クラウドを学ぶ具体的なプラットフォームとして AWS を取り上げ, AWS を使用するにあたり最低限必要な知識と用語の説明を行った. さらに, <a href="#sec_first_ec2">Hands-on #1: 初めての EC2 インスタンスを起動する</a> のハンズオンでは AWS CLI と AWS CDK を使って,自身のプライベートなサーバーを AWS 上に立ち上げる演習を行った.</p><p>これらを通じて,いかに簡単に (たった数行のコマンドで!) 仮想サーバーを立ち上げたり,削除したりすることができるか,体験できただろう. 筆者は,<a href="#chap_cloud_basics">クラウド概論</a> でクラウドの最も重要な側面はダイナミックに計算リソースを拡大・縮小できることである,と述べた. この言葉の意味が,ハンズオンを通じてより明らかになっただろうか? ここで学んだ技術を少し応用するだけで,自分のウェブページをホストする仮想サーバーを作成したり,大量のコアを搭載した EC2 インスタンスを用意して科学計算を実行するなど,いろいろなアプリケーションが実現できる.</p><p>次章からは,今回学んだクラウドの技術を基に,より現実に即した問題を解くことを体験してもらう. お楽しみに!</p><h1 id="クラウドで行う科学計算・機械学習" tabindex="-1">クラウドで行う科学計算・機械学習 <a class="header-anchor" href="#クラウドで行う科学計算・機械学習" aria-label="Permalink to &quot;クラウドで行う科学計算・機械学習&quot;"></a></h1><p>計算機が発達した現代では,計算機によるシミュレーションやビッグデータの解析は,科学・エンジニアリングの研究の主要な柱である. これらの大規模な計算を実行するには,クラウドは最適である. 本章から始まる第二部では,どのようにしてクラウド上で科学計算を実行するのかを,ハンズオンとともに体験してもらう. 科学計算の具体的な題材として,今回は機械学習(深層学習)を取り上げる.</p><p>なお,本書では <a href="https://pytorch.org/" target="_blank" rel="noreferrer">PyTorch</a> ライブラリを使って深層学習のアルゴリズムを実装するが,深層学習および PyTorch の知識は不要である. 講義ではなぜ・どうやって深層学習をクラウドで実行するかに主眼を置いているので,実行するプログラムの詳細には立ち入らない. 将来,自分で深層学習を使う機会が来たときに,詳しく学んでもらいたい.</p><h2 id="なぜ機械学習をクラウドで行うのか" tabindex="-1">なぜ機械学習をクラウドで行うのか? <a class="header-anchor" href="#なぜ機械学習をクラウドで行うのか" aria-label="Permalink to &quot;なぜ機械学習をクラウドで行うのか?&quot;"></a></h2><p>2010 年頃に始まった第三次 AI ブームのおかげで,学術研究だけでなく社会・ビジネスの文脈でも機械学習に高い関心が寄せられている. とくに,<strong>深層学習 (ディープラーニング)</strong> とよばれる多層のレイヤーからなるニューラルネットワークを用いたアルゴリズムは,画像認識や自然言語処理などの分野で圧倒的に高い性能を実現し,革命をもたらしている.</p><p>深層学習の特徴は,なんといってもそのパラメータの多さである. 層が深くなるほど,層間のニューロンを結ぶ重みパラメータの数が増大していく. たとえば,最新の言語モデルである <a href="https://arxiv.org/abs/2005.14165" target="_blank" rel="noreferrer">GPT-3</a> には<strong>1750 億個</strong>ものパラメータが含まれている. このような膨大なパラメータを有することで,深層学習は高い表現力と汎化性能を実現しているのである.</p><p>GPT-3 に限らず,最近の SOTA (State-of-the-art) の性能を達成するニューラルネットワークでは,百万から億のオーダーのパラメータを内包することは頻繁になってきている. そのような巨大なニューラルネットを訓練 (最適化) させるのは,当然のことながら膨大な計算コストがかかる. 結果として,ひとつの計算機では丸一日以上の時間がかかる場合も珍しくない. 深層学習の発展の速度は目覚ましく,研究・ビジネス両方の観点からも,いかにスループットよくニューラルネットワークの最適化を行えるかが鍵となってくる. そのような問題を解決するのにとても有効な手段が,クラウドである! <a href="#sec_first_ec2">Hands-on #1: 初めての EC2 インスタンスを起動する</a> でその片鱗を見たように,クラウドを使用することでゼロから数千に至るまでの数のインスタンスを動的に起動し,並列に計算を実行することができる. さらに,深層学習を加速させる目的で,深層学習の演算に専用設計された計算チップ (GPU など) がある. クラウドを利用すると,そのような専用計算チップも無尽蔵に利用することができる. 事実,先述した GPT-3 の学習も詳細は明かされていないがMicrosoft 社のクラウドを使って行われたと報告されている.</p><h2 id="gpu-による深層学習の高速化" tabindex="-1">GPU による深層学習の高速化 <a class="header-anchor" href="#gpu-による深層学習の高速化" aria-label="Permalink to &quot;GPU による深層学習の高速化&quot;"></a></h2><p>深層学習の計算で欠かすことのできない技術として, <strong>GPU (Graphics Processing Unit)</strong> について少し説明する.</p><p>GPU は,その名のとおり,元々はコンピュータグラフィックスを出力するための専用計算チップである. CPU (Central Processing Unit) に対し,グラフィックスの演算に特化した設計がなされている. 身近なところでは, XBox や PS5 などのゲームコンソールなどに搭載されているし,ハイエンドなノート型・デスクトップ型計算機にも搭載されていることがある. コンピュータグラフィックスでは,スクリーンにアレイ状に並んだ数百万個の画素をビデオレート (30 fps) 以上で処理する必要がある. そのためGPU はコアあたりの演算能力は比較的小さいかわりに,チップあたり数百から数千のコアを搭載しており (<a href="#gpu_architecture">figure_title</a>),スクリーンの画素を並列的に処理することで,リアルタイムでの描画を実現している.</p><p><img src="'+D+'" alt="GPUのアーキテクチャGPUには数百から数千の独立した計算コアが搭載されている (画像出典: https://devblogs.nvidia.com/nvidia-turing-architecture-in-depth/)"></p><p>このように,コンピュータグラフィクスの目的で生まれた GPU だが2010 年前後から,その高い並列計算能力をグラフィックス以外の計算 (科学計算など) に用いるという流れ (<strong>General-purpose computing on GPU; GPGPU</strong>) が生まれた. GPU のコアは,その設計から,行列の計算など,単純かつ規則的な演算が得意であり,そのような演算に対しては数個程度のコアしかもたない CPU に比べて圧倒的に高い計算速度を実現することができる. 現在では GPGPU は分子動力学や気象シミュレーション,そして機械学習など多くの分野で使われている.</p><p>ディープラーニングで最も頻繁に起こる演算が,ニューロンの出力を次の層のニューロンに伝える<strong>畳み込み (Convolution)</strong> 演算である (<a href="#fig:convolution">figure_title</a>) 畳み込み演算は,まさに GPU が得意とする演算であり, CPU ではなく GPU を用いることで学習を飛躍的に (最大で数百倍程度) 加速させることができる.</p><p><img src="'+C+'" alt="ニューラルネットワークにおける畳み込み演算."></p><p>このように GPU は機械学習の計算で欠かせないものであるが,なかなか高価である. たとえば,科学計算・機械学習に専用設計された NVIDIA 社の Tesla V100 というチップは,一台で約百万円の価格が設定されている. 機械学習を始めるのに,いきなり百万円の投資はなかなか大きい. だが,クラウドを使えば,初期コスト0で GPU を使用することができる.</p><p>機械学習を行うのに, V100 が必ずしも必要というわけではない. むしろ,研究者などでしばしば行われるのは,コンピュータゲームに使われるグラフィックス用の GPU を買ってきて (NVIDIA GeForce シリーズなど),開発のときはをそれを用いる,というアプローチである. グラフィックス用のいわゆる&quot;コンシューマ GPU&quot;は市場の需要が大きいおかげで10 万円前後の価格で購入することができる. V100 と比べると,コンシューマ GPU はコアの数が少なかったり,メモリーが小さかったりなどで劣る点があるが, それらを除いては計算能力にとくに制限があるわけではなく,開発の段階では十分な性能である場合がほとんどである. プログラムができあがって,ビッグデータの解析や,モデルをさらに大きくしたいときなどに,クラウドは有効だろう.</p><p>クラウドで GPU を使うには, GPU が搭載された EC2 インスタンスタイプ (<code>P3</code>, <code>P2</code>, <code>G3</code>, <code>G4</code> など) を選択しなければならない. <a href="#table_gpu_instances">table_title</a> に,代表的な GPU 搭載のインスタンスタイプを挙げる (執筆時点での情報)</p><table style="width:100%;"><caption>GPUを搭載したEC2インスタンスタイプ</caption><colgroup><col style="width:14%;"><col style="width:14%;"><col style="width:14%;"><col style="width:14%;"><col style="width:14%;"><col style="width:14%;"><col style="width:14%;"></colgroup><thead><tr class="header"><th>Instance</th><th>GPUs</th><th>GPU model</th><th>GPU Mem (GiB)</th><th>vCPU</th><th>Mem (GiB)</th><th>Price per hour ($)</th></tr></thead><tbody><tr class="odd"><td><p>p3.2xlarge</p></td><td><p>1</p></td><td><p>NVIDIA V100</p></td><td><p>16</p></td><td><p>8</p></td><td><p>61</p></td><td><p>3.06</p></td></tr><tr class="even"><td><p>p3n.16xlarge</p></td><td><p>8</p></td><td><p>NVIDIA V100</p></td><td><p>128</p></td><td><p>64</p></td><td><p>488</p></td><td><p>24.48</p></td></tr><tr class="odd"><td><p>p2.xlarge</p></td><td><p>1</p></td><td><p>NVIDIA K80</p></td><td><p>12</p></td><td><p>4</p></td><td><p>61</p></td><td><p>0.9</p></td></tr><tr class="even"><td><p>g4dn.xlarge</p></td><td><p>1</p></td><td><p>NVIDIA T4</p></td><td><p>16</p></td><td><p>4</p></td><td><p>16</p></td><td><p>0.526</p></td></tr></tbody></table><p><a href="#table_gpu_instances">table_title</a> からわかるとおり, CPU のみのインスタンスと比べると少し高い価格設定になっている. また,古い世代の GPU (V100 に対しての K80) はより安価な価格で提供されている. 1 インスタンスあたりの GPU の搭載数は 1 台から最大で 8 台まで選択することが可能である.</p><p>GPU を搭載した一番安いインスタンスタイプは, <code>g4dn.xlarge</code> であり,これには廉価かつ省エネルギー設計の NVIDIA T4 が搭載されている. 後のハンズオンでは,このインスタンスを使用して,ディープラーニングの計算を行ってみる.</p><p><a href="#table_gpu_instances">table_title</a> の価格は <code>us-east-1</code> のものである. リージョンによって多少価格設定が異なる.</p><p>V100 を一台搭載した <code>p3.2xlarge</code> の利用料金は一時間あたり $3.06 である. V100 が約百万円で売られていることを考えると,約 3000 時間 (= 124 日間),通算で計算を行った場合に,クラウドを使うよりも V100 を自分で買ったほうがお得になる,という計算になる (実際には,自前で V100 を用意する場合は, V100 だけでなく, CPU やネットワーク機器,電気使用料も必要なので,百万円よりもさらにコストがかかる)</p><p>GPT-3 で使われた計算リソースの詳細は論文でも明かされていないのだが, <a href="https://lambdalabs.com/blog/demystifying-gpt-3/" target="_blank" rel="noreferrer">Lambda 社のブログ</a>で興味深い考察が行われている (Lambda 社は機械学習に特化したクラウドサービスを提供している)</p><p>記事によると1750 億のパラメータを訓練するには,一台の GPU (NVIDIA V100) を用いた場合342 年の月日と 460 万ドルのクラウド利用料が必要となる,とのことである. GPT-3 のチームは,複数の GPU に処理を分散することで現実的な時間のうちに訓練を完了させたのであろうが,このレベルのモデルになってくるとクラウド技術の限界を攻めないと達成できないことは確かである.</p><p>深層学習を詳しく勉強したい人には以下の参考書を推薦したい. 深層学習の基礎的な概念や理論は普遍的であるが,この分野は日進月歩なので,常に最新の情報を取り入れることを忘れずに.</p><ul><li><p><a href="https://www.deeplearningbook.org/" target="_blank" rel="noreferrer">Deep Learning (Ian Goodfellow, Yoshua Bengio and Aaron Courville)</a> 出版されてから数年が経つが,深層学習の理論的な側面を学びたいならばおすすめの入門書. ウェブで無料で読むことができる. 日本語版も出版されている. 実装についてはほとんど触れられていないので,理論家向けの本.</p></li><li><p><a href="https://www.oreilly.co.jp/books/9784873117584/" target="_blank" rel="noreferrer">ゼロから作る Deep Learning (斎藤 康毅)</a> 合計三冊からなるシリーズ. 理論と実装がバランスよく説明されていて,深層学習の入門書の決定版.</p></li><li><p><a href="https://d2l.ai/" target="_blank" rel="noreferrer">Dive into Deep Learning (Aston Zhang, Zachary C. Lipton, Mu Li, and Alexander J. Smola)</a> 深層学習の基礎から最新のアルゴリズムまでを,実装を通して学んでいくスタイルの本. ウェブで無料で読むことができる1000 ページ越えの超大作. これを読破することができれば,深層学習の実装で困ることはないだろう.</p></li></ul><h1 id="hands-on-2-aws-でディープラーニングを実践" tabindex="-1">Hands-on #2: AWS でディープラーニングを実践 <a class="header-anchor" href="#hands-on-2-aws-でディープラーニングを実践" aria-label="Permalink to &quot;Hands-on \\#2: AWS でディープラーニングを実践&quot;"></a></h1><h2 id="準備-1" tabindex="-1">準備 <a class="header-anchor" href="#準備-1" aria-label="Permalink to &quot;準備&quot;"></a></h2><p>ハンズオン第二回では, GPU を搭載した EC2 インスタンスを起動し,深層学習モデルの学習と推論を実行する演習を行う.</p><p>ハンズオンのソースコードは GitHub の <a href="https://github.com/andatoshiki/toshiki-notebooktree/main/handson/mnist" target="_blank" rel="noreferrer">handson/mnist</a> に置いてある.</p><p>本ハンズオンの実行には,第一回ハンズオンで説明した準備 (<a href="#handson_01_prep">準備</a>) が整っていることを前提とする. それ以外に必要な準備はない.</p><p>初期状態の AWS アカウントでは, GPU 搭載の G タイプのインスタンスの起動上限が 0 になっていることがある. これを確認するには, AWS コンソールから EC2 の画面を開き,左のメニューから <code>Limits</code> を選択する. その中の <code>Running On-Demand All G instances</code> という数字が G インスタンスの起動上限を表している.</p><p>もし,これが 0 になっていた場合は, AWS の自動申請フォームから上限緩和のリクエストを送る必要がある. 詳しくは <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-resource-limits.html" target="_blank" rel="noreferrer">公式ドキュメンテーション &quot;Amazon EC2 service quotas&quot;</a> を参照のこと.</p><p>このハンズオンは, <code>g4dn.xlarge</code> タイプの EC2 インスタンスを使うので,東京 (<code>ap-northeast-1</code>) リージョンでは 0.71 $/hour のコストが発生する.</p><p>AWS Educate Starter Account を使用している読者へ: 執筆時点においては, Starter Account には GPU 搭載型インスタンスを起動できないという制限が設けられている. したがって, Starter Account のユーザーはこのハンズオンを実行することはできない. 興味のある読者は,制限のない一般アカウントを自分自身で取得する必要があることに注意.</p><h2 id="アプリケーションの説明-1" tabindex="-1">アプリケーションの説明 <a class="header-anchor" href="#アプリケーションの説明-1" aria-label="Permalink to &quot;アプリケーションの説明&quot;"></a></h2><p>このハンズオンで作成するアプリケーションの概要を <a href="#handson_02_architecture">figure_title</a> に示す.</p><p><img src="'+S+`" alt="ハンズオン#2で作製するアプリケーションのアーキテクチャ"></p><p>図の多くの部分が,第一回ハンズオンで作成したアプリケーションと共通していることに気がつくだろう. 少しの変更で,簡単にディープラーニングを走らせる環境を構築することができるのである!主な変更点は次の3点である.</p><ul><li><p>GPU を搭載した <code>g4dn.xlarge</code> インスタンスタイプを使用</p></li><li><p>ディープラーニングに使うプログラムがあらかじめインストールされた DLAMI (後述) を使用</p></li><li><p>SSH にポートフォワーディングのオプションつけてサーバーに接続し,サーバーで起動している Jupyter Notebook (後述) を使ってプログラムを書いたり実行したりする</p></li></ul><p>ハンズオンで使用するプログラムのコードをみてみよう <a href="https://github.com/andatoshiki/toshiki-notebooktree/main/handson/mnist/app.py" target="_blank" rel="noreferrer">handson/mnist/app.py</a>) コードは第一回目とほとんど共通である.変更点のみ解説を行う.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#93A1A1;font-weight:bold;">class</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">Ec2ForDl</span><span style="color:#839496;">(</span><span style="color:#6C71C4;">core</span><span style="color:#839496;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#839496;">):</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#839496;">, key_name: </span><span style="color:#859900;">str</span><span style="color:#839496;">, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs) -&gt; </span><span style="color:#B58900;">None</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">super</span><span style="color:#839496;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> vpc </span><span style="color:#859900;">=</span><span style="color:#839496;"> ec2.Vpc(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;Ec2ForDl-Vpc&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> max_azs</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> cidr</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;10.10.0.0/23&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> subnet_configuration</span><span style="color:#859900;">=</span><span style="color:#839496;">[</span></span>
<span class="line"><span style="color:#839496;"> ec2.SubnetConfiguration(</span></span>
<span class="line"><span style="color:#839496;"> name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;public&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> subnet_type</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.SubnetType.</span><span style="color:#CB4B16;">PUBLIC</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> ],</span></span>
<span class="line"><span style="color:#839496;"> nat_gateways</span><span style="color:#859900;">=</span><span style="color:#D33682;">0</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> sg </span><span style="color:#859900;">=</span><span style="color:#839496;"> ec2.SecurityGroup(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;Ec2ForDl-Sg&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> vpc</span><span style="color:#859900;">=</span><span style="color:#839496;">vpc,</span></span>
<span class="line"><span style="color:#839496;"> allow_all_outbound</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> sg.add_ingress_rule(</span></span>
<span class="line"><span style="color:#839496;"> peer</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.Peer.any_ipv4(),</span></span>
<span class="line"><span style="color:#839496;"> connection</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.Port.tcp(</span><span style="color:#D33682;">22</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> host </span><span style="color:#859900;">=</span><span style="color:#839496;"> ec2.Instance(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;Ec2ForDl-Instance&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> instance_type</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.InstanceType(</span><span style="color:#2AA198;">&quot;g4dn.xlarge&quot;</span><span style="color:#839496;">), </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> machine_image</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.MachineImage.generic_linux({</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;us-east-1&quot;</span><span style="color:#839496;">: </span><span style="color:#2AA198;">&quot;ami-060f07284bb6f9faf&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;ap-northeast-1&quot;</span><span style="color:#839496;">: </span><span style="color:#2AA198;">&quot;ami-09c0c16fc46a29ed9&quot;</span></span>
<span class="line"><span style="color:#839496;"> }), </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> vpc</span><span style="color:#859900;">=</span><span style="color:#839496;">vpc,</span></span>
<span class="line"><span style="color:#839496;"> vpc_subnets</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.SubnetSelection(subnet_type</span><span style="color:#859900;">=</span><span style="color:#839496;">ec2.SubnetType.</span><span style="color:#CB4B16;">PUBLIC</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> security_group</span><span style="color:#859900;">=</span><span style="color:#839496;">sg,</span></span>
<span class="line"><span style="color:#839496;"> key_name</span><span style="color:#859900;">=</span><span style="color:#839496;">key_name</span></span>
<span class="line"><span style="color:#839496;"> )</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#586E75;font-weight:bold;">class</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">Ec2ForDl</span><span style="color:#657B83;">(</span><span style="color:#6C71C4;">core</span><span style="color:#657B83;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#657B83;">):</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#657B83;">, key_name: </span><span style="color:#859900;">str</span><span style="color:#657B83;">, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs) -&gt; </span><span style="color:#B58900;">None</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">super</span><span style="color:#657B83;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> vpc </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ec2.Vpc(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;Ec2ForDl-Vpc&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> max_azs</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> cidr</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;10.10.0.0/23&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> subnet_configuration</span><span style="color:#859900;">=</span><span style="color:#657B83;">[</span></span>
<span class="line"><span style="color:#657B83;"> ec2.SubnetConfiguration(</span></span>
<span class="line"><span style="color:#657B83;"> name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;public&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> subnet_type</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.SubnetType.</span><span style="color:#CB4B16;">PUBLIC</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> ],</span></span>
<span class="line"><span style="color:#657B83;"> nat_gateways</span><span style="color:#859900;">=</span><span style="color:#D33682;">0</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> sg </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ec2.SecurityGroup(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;Ec2ForDl-Sg&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> vpc</span><span style="color:#859900;">=</span><span style="color:#657B83;">vpc,</span></span>
<span class="line"><span style="color:#657B83;"> allow_all_outbound</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> sg.add_ingress_rule(</span></span>
<span class="line"><span style="color:#657B83;"> peer</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.Peer.any_ipv4(),</span></span>
<span class="line"><span style="color:#657B83;"> connection</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.Port.tcp(</span><span style="color:#D33682;">22</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> host </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ec2.Instance(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;Ec2ForDl-Instance&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> instance_type</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.InstanceType(</span><span style="color:#2AA198;">&quot;g4dn.xlarge&quot;</span><span style="color:#657B83;">), </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> machine_image</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.MachineImage.generic_linux({</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;us-east-1&quot;</span><span style="color:#657B83;">: </span><span style="color:#2AA198;">&quot;ami-060f07284bb6f9faf&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;ap-northeast-1&quot;</span><span style="color:#657B83;">: </span><span style="color:#2AA198;">&quot;ami-09c0c16fc46a29ed9&quot;</span></span>
<span class="line"><span style="color:#657B83;"> }), </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> vpc</span><span style="color:#859900;">=</span><span style="color:#657B83;">vpc,</span></span>
<span class="line"><span style="color:#657B83;"> vpc_subnets</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.SubnetSelection(subnet_type</span><span style="color:#859900;">=</span><span style="color:#657B83;">ec2.SubnetType.</span><span style="color:#CB4B16;">PUBLIC</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> security_group</span><span style="color:#859900;">=</span><span style="color:#657B83;">sg,</span></span>
<span class="line"><span style="color:#657B83;"> key_name</span><span style="color:#859900;">=</span><span style="color:#657B83;">key_name</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br></div></div><ul><li><p>ここで, <code>g4dn.xlarge</code> インスタンスタイプを選択している (第一回では, CPU のみの <code>t2.micro</code> だった) <code>g4dn.xlarge</code> のインスタンスタイプは, <a href="#sec_scientific_computing">クラウドで行う科学計算・機械学習</a> ですでに触れた通り, <code>NVIDIA T4</code> と呼ばれる廉価版モデルの GPU を搭載したインスタンスである. CPU は 4 core, メインメモリーは 16GB が割り当てあられている.</p></li><li><p>ここではDeep Learning 用の諸々のソフトウェアがプリンストールされた AMI (<a href="https://docs.aws.amazon.com/dlami/latest/devguide/what-is-dlami.html" target="_blank" rel="noreferrer">Deep Learning Amazon Machine Image; DLAMI</a>) を選択している (第一回ではAmazon Linux という AMI を使用していた) 使用する AMI の ID は リージョンごとに指定する必要があり,ここでは <code>us-east-1</code> と <code>ap-northeast-1</code> でそれぞれ定義している.</p></li></ul><p>DLAMI という新しい概念が出てきたので,説明しよう.</p><p>AMI が <code>us-east-1</code> と <code>ap-northeast-1</code> でしか定義されていないので,提供されているコードはこの二つのリージョンのみでデプロイ可能である. もしほかのリージョンを利用したい場合は, AMI の ID を自身で検索し,コードに書き込む必要がある.</p><h3 id="dlami-deep-learning-amazon-machine-image" tabindex="-1">DLAMI (Deep Learning Amazon Machine Image) <a class="header-anchor" href="#dlami-deep-learning-amazon-machine-image" aria-label="Permalink to &quot;DLAMI (Deep Learning Amazon Machine Image)&quot;"></a></h3><p><strong>AMI (Amazon Machine Image)</strong> とは,大まかには OS (Operating System) に相当する概念である. 当然のことながら, OS がなければコンピュータはなにもできないのでEC2 インスタンスを起動するときには必ずなにかの OS を&quot;インストール&quot;する必要がある. EC2 が起動したときにロードされる OS に相当するものが, AMI である. AMI には,たとえば <a href="https://ubuntu.com/" target="_blank" rel="noreferrer">Ubuntu</a> などの Linux 系 OS に加えてWindows Server を選択することもできる. また, EC2 での使用に最適化された <a href="https://aws.amazon.com/amazon-linux-ami/" target="_blank" rel="noreferrer">Amazon Linux</a> という AMI も提供されている.</p><p>しかしながら, AMI を単なる OS と理解するのは過剰な単純化である. AMI には,ベースとなる (空っぽの) OS を選択することもできるが,それに加えて,各種のプログラムがインストール済みの AMI も定義することができる. 必要なプログラムがインストールされている AMI を見つけることができれば,自身でインストールを行ったり環境設定したりする手間が大幅に省ける. 具体例を挙げると,ハンズオン第一回では EC2 インスタンスに Python 3.6 をインストールする例を示したが,そのような操作をインスタンスが起動するたびに行うのは手間である!</p><p>AMI は, AWS 公式のものに加えて,サードパーティから提供されているものもある. また,自分自身の AMI を作って登録することも可能である (<a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/creating-an-ami-instance-store.html" target="_blank" rel="noreferrer">参考</a>) AMI は EC2 のコンソールから検索することが可能である. あるいはAWS CLI を使って,次のコマンドでリストを取得することができる (<a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html" target="_blank" rel="noreferrer">参考</a>)</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ec2</span><span style="color:#839496;"> </span><span style="color:#2AA198;">describe-images</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--owners</span><span style="color:#839496;"> </span><span style="color:#2AA198;">amazon</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ec2</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">describe-images</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--owners</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">amazon</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>ディープラーニングで頻繁に使われるプログラムがあらかじめインストールしてある AMI が, <a href="https://docs.aws.amazon.com/dlami/latest/devguide/what-is-dlami.html" target="_blank" rel="noreferrer">DLAMI (Deep Learning AMI)</a> である. DLAMI には <code>TensorFlow</code>, <code>PyTorch</code> などの人気の高いディープラーニングのフレームワーク・ライブラリがすでにインストールされているため, EC2 インスタンスを起動してすぐさまディープラーニングの計算を実行できる.</p><p>本ハンズオンでは, Amazon Linux 2 をベースにした DLAMI を使用する (AMI ID = ami-09c0c16fc46a29ed9この AMI は ap-northeast-1 でしか使用できない点に注意) AWS CLI を使って,この AMI の詳細情報を取得してみよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ec2</span><span style="color:#839496;"> </span><span style="color:#2AA198;">describe-images</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--owners</span><span style="color:#839496;"> </span><span style="color:#2AA198;">amazon</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--image-ids</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;ami-09c0c16fc46a29ed9&quot;</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--region</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ap-northeast-1</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ec2</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">describe-images</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--owners</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">amazon</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--image-ids</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;ami-09c0c16fc46a29ed9&quot;</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--region</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ap-northeast-1</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p><img src="`+w+`" alt="AMI ID = ami-09c0c16fc46a29ed9 の詳細情報"></p><p><a href="#handson_02_ami-info">figure_title</a> のような出力が得られるはずである.得られた出力から,この DLAMI には PyTorch のバージョン 1.4.0 と 1.5.0 がインストールされていることがわかる. この DLAMI を使って,早速ディープラーニングの計算を実行してみよう.</p><p>DLAMI には具体的には何がインストールされているのだろうか? 興味のある読者のために,簡単な解説をしよう (参考: <a href="https://docs.aws.amazon.com/dlami/latest/devguide/what-is-dlami.html" target="_blank" rel="noreferrer">公式ドキュメンテーション &quot;What Is the AWS Deep Learning AMI?&quot;</a>)</p><p>最も low-level なレイヤーとしては, GPU ドライバー がインストールされている. GPU ドライバーなしには OS は GPU とコマンドのやり取りをすることができない. 次のレイヤーが <a href="https://developer.nvidia.com/about-cuda" target="_blank" rel="noreferrer">CUDA</a> と <a href="https://developer.nvidia.com/cudnn" target="_blank" rel="noreferrer">cuDNN</a> である. CUDA は, NVIDIA 社が開発した, GPU 上で汎用コンピューティングを行うための言語であり, C++ 言語を拡張したシンタックスを備える. cuDNN は CUDA で書かれたディープラーニングのライブラリでありn 次元の畳み込みなどの演算が実装されている. ここまでが, &quot;Base&quot; とよばれるタイプの DLAMI の中身である.</p><p>これに加えて, &quot;Conda&quot; とよばれるタイプには, &quot;Base&quot; のプログラム基盤の上に, <code>TensorFlow</code> や <code>PyTorch</code> などのライブラリがインストールされている. さらに, <a href="https://docs.conda.io/projects/conda/en/latest/index.html" target="_blank" rel="noreferrer">Anaconda</a> による仮想環境を使うことによって, <code>TensorFlow</code> の環境・ <code>PyTorch</code> の環境・ <code>MxNet</code> の環境など,フレームワークを簡単に切り替えることができる (これについては,後のハンズオンで触れる) また, Jupyter Notebook もインストール済みである.</p><h2 id="スタックのデプロイ" tabindex="-1">スタックのデプロイ <a class="header-anchor" href="#スタックのデプロイ" aria-label="Permalink to &quot;スタックのデプロイ&quot;"></a></h2><p>スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.</p><p>デプロイの手順は,ハンズオン 1 とほとんど共通である. ここでは,コマンドのみ列挙する (<code>#</code> で始まる行はコメントである) それぞれのコマンドの意味を忘れてしまった場合は,ハンズオン 1 に戻って復習していただきたい. シークレットキーの設定も忘れずに (<a href="#aws_cli_install">AWS CLI のインストール</a>)</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># プロジェクトのディレクトリに移動</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cd</span><span style="color:#839496;"> </span><span style="color:#2AA198;">handson/mnist</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># venv を作成し,依存ライブラリのインストールを行う</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python3</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#839496;"> </span><span style="color:#2AA198;">venv</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">source</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pip</span><span style="color:#839496;"> </span><span style="color:#2AA198;">install</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#839496;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># SSH鍵を生成</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">export</span><span style="color:#839496;"> </span><span style="color:#2AA198;">KEY_NAME=&quot;HirakeGoma&quot;</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ec2</span><span style="color:#839496;"> </span><span style="color:#2AA198;">create-key-pair</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--key-name</span><span style="color:#839496;"> </span><span style="color:#859900;">\${</span><span style="color:#268BD2;">KEY_NAME</span><span style="color:#859900;">}</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--query</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&#39;KeyMaterial&#39;</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--output</span><span style="color:#839496;"> </span><span style="color:#2AA198;">text</span><span style="color:#839496;"> </span><span style="color:#859900;">&gt;</span><span style="color:#839496;"> </span><span style="color:#859900;">\${</span><span style="color:#268BD2;">KEY_NAME</span><span style="color:#859900;">}</span><span style="color:#2AA198;">.pem</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">mv</span><span style="color:#839496;"> </span><span style="color:#2AA198;">HirakeGoma.pem</span><span style="color:#839496;"> </span><span style="color:#2AA198;">~/.ssh/</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">chmod</span><span style="color:#839496;"> </span><span style="color:#D33682;">400</span><span style="color:#839496;"> </span><span style="color:#2AA198;">~/.ssh/HirakeGoma.pem</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># デプロイを実行</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">deploy</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-c</span><span style="color:#839496;"> </span><span style="color:#2AA198;">key_name=&quot;HirakeGoma&quot;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># プロジェクトのディレクトリに移動</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cd</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">handson/mnist</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># venv を作成し,依存ライブラリのインストールを行う</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python3</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">venv</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">source</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pip</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">install</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># SSH鍵を生成</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">export</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">KEY_NAME=&quot;HirakeGoma&quot;</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ec2</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">create-key-pair</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--key-name</span><span style="color:#657B83;"> </span><span style="color:#859900;">\${</span><span style="color:#268BD2;">KEY_NAME</span><span style="color:#859900;">}</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--query</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&#39;KeyMaterial&#39;</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--output</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">text</span><span style="color:#657B83;"> </span><span style="color:#859900;">&gt;</span><span style="color:#657B83;"> </span><span style="color:#859900;">\${</span><span style="color:#268BD2;">KEY_NAME</span><span style="color:#859900;">}</span><span style="color:#2AA198;">.pem</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">mv</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">HirakeGoma.pem</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">~/.ssh/</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">chmod</span><span style="color:#657B83;"> </span><span style="color:#D33682;">400</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">~/.ssh/HirakeGoma.pem</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># デプロイを実行</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">deploy</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-c</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">key_name=&quot;HirakeGoma&quot;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p>ハンズオン 1 で作成した SSH 鍵の削除を行わなかった場合は, SSH 鍵を改めて作成する必要はない. 逆に言うと,同じ名前の SSH がすでに存在する場合は,鍵生成のコマンドはエラーを出力する.</p><p>デプロイのコマンドが無事に実行されれば, <a href="#handson_02_cdk_output">figure_title</a> のような出力が得られるはずであるAWS により割り振られた IP アドレス (<code>InstancePublicIp</code> に続く文字列) をメモしておこう.</p><p><img src="`+P+'" alt="CDKデプロイ実行後の出力"></p><h2 id="ログイン" tabindex="-1">ログイン <a class="header-anchor" href="#ログイン" aria-label="Permalink to &quot;ログイン&quot;"></a></h2><p>早速,デプロイしたインスタンスに SSH でログインしてみよう. ここでは,この後で使う Jupyter Notebook に接続するため,<strong>ポートフォワーディング (port forwarding)</strong> のオプション (<code>-L</code>) をつけてログインする.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ssh</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-i</span><span style="color:#839496;"> </span><span style="color:#2AA198;">~/.ssh/HirakeGoma.pem</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-L</span><span style="color:#839496;"> </span><span style="color:#2AA198;">localhost:8931:localhost:8888</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ec2-user@</span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">IP</span><span style="color:#839496;"> </span><span style="color:#2AA198;">addres</span><span style="color:#839496;">s</span><span style="color:#859900;">&gt;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ssh</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-i</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">~/.ssh/HirakeGoma.pem</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-L</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">localhost:8931:localhost:8888</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ec2-user@</span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">IP</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">addres</span><span style="color:#657B83;">s</span><span style="color:#859900;">&gt;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>ポートフォワーディングとは,クライアントマシンの特定のアドレスへの接続を, SSH の暗号化された通信を介して,リモートマシンの特定のアドレスへ転送する,という意味である. このコマンドの <code>-L localhost:8931:localhost:8888</code> は,自分のローカルマシンの <code>localhost:8931</code> へのアクセスを,リモートサーバーの <code>localhost:8888</code> のアドレスに転送せよ,という意味である (<code>:</code> につづく数字は TCP/IP ポートの番号を意味している) リモートサーバーのポート 8888 には,後述する Jupyter Notebook が起動している. したがって,ローカルマシンの <code>localhost:8931</code> にアクセスすることで,リモートサーバーの Jupyter Notebook にアクセスすることができるのである (<a href="#fig:ssh_port_forwarding">figure_title</a>) このような SSH による接続方式を<strong>トンネル接続</strong>とよぶ.</p><p><img src="'+E+'" alt="SSH のポートフォワーディングによる Jupyter Notebook へのアクセス"></p><p>ポートフォワーディングのオプションで,ポートの番号 (<code>:8931</code>, <code>:8888</code> など) には 1 から 65535 までの任意の整数を指定できる. しかし,たとえば ポート 22 (SSH) やポート 80 (HTTP) など,いくつかすでに使われているポート番号もあることに注意する. また, Jupyter Notebook はデフォルトではポート 8888 番を使用する. したがってリモート側のポート番号は8888 を使うのがよい.</p><p>SSH ログインコマンドの <code>&lt;IP address&gt;</code> 部分は自身のインスタンスの IP アドレスを代入することを忘れずに.</p><p><strong>本書の提供している Docker を使ってデプロイを実行した人へ</strong></p><p>SSH によるログインは, <strong>Docker の外</strong> (すなわちクライアントマシン本体) から行わなければならない. なぜならJupyter を開くウェブブラウザは Docker の外にあるからである.</p><p>その際,秘密鍵を Docker の外にもってこなければならない. 手っ取り早い方法は, <code>cat ~/.ssh/HirakeGoma</code> と打って,出力結果をコピーしてホストマシンのファイルに書き込む方法である. あるいは <code>-v</code> オプションをつけて,ファイルシステムをマウントしてもよい (詳しくは <a href="https://docs.docker.com/storage/volumes/" target="_blank" rel="noreferrer">Docker 公式ドキュメンテーション &quot;Use volumes&quot;</a> を参照)</p><p>SSH によるログインができたら,早速, GPU の状態を確認してみよう. 次のコマンドを実行する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">nvidia-smi</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">nvidia-smi</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p><a href="#handson_02_nvidia-smi">figure_title</a> のような出力が得られるはずである. 出力を見ると, Tesla T4 型の GPU が 1 台搭載されていることが確認できる. その他GPU Driver や CUDA のバージョン, GPU の負荷・メモリー使用率などの情報を確認することができる.</p><p><img src="'+I+'" alt="nvidia-smi の出力"></p><h2 id="jupyter-notebook-の起動" tabindex="-1">Jupyter Notebook の起動 <a class="header-anchor" href="#jupyter-notebook-の起動" aria-label="Permalink to &quot;Jupyter Notebook の起動&quot;"></a></h2><p><a href="https://jupyter.org/" target="_blank" rel="noreferrer">Jupyter Notebook</a> とは,インタラクティブに Python のプログラムを書いたり実行したりするためのツールである. Jupyter は GUI としてウェブブラウザを介してアクセスする形式をとっており,まるでノートを書くように,プロットやテーブルのデータも美しく表示することができる (<a href="#handson_02_welcome_jupyter">figure_title</a>) Python に慣れている読者は,きっと一度は使ったことがあるだろう.</p><p><img src="'+z+`" alt="Jupyter Notebook の画面"></p><p>このハンズオンでは, Jupyter Notebook を使ってディープラーニングのプログラムをインタラクティブに実行していく. DLAMI には既に Jupyter がインストールされているので,特段の設定なしに使い始めることができる.</p><p>早速, Jupyter を起動しよう. SSH でログインした先の EC2 インスタンスで,次のコマンドを実行すればよい.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cd</span><span style="color:#839496;"> </span><span style="color:#2AA198;">~</span><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># go to home directory</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">jupyter</span><span style="color:#839496;"> </span><span style="color:#2AA198;">notebook</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cd</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">~</span><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># go to home directory</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">jupyter</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">notebook</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>このコマンドを実行すると, <a href="#handson_02_jupyter_launch">figure_title</a> のような出力が確認できるだろう. この出力からJupyter のサーバーが EC2 インスタンスの <code>localhost:8888</code> というアドレスに起動していることがわかる. また, <code>localhost:8888</code> に続く <code>?token=XXXX</code> は,アクセスに使うための一時的なトークンである.</p><p><img src="`+x+'" alt="Jupyter Notebook サーバーを起動"></p><p>Jupyter Notebook を初回に起動するときは,起動に数分程度の時間がかかることがある. ほかの動作も起動直後は遅く,いくつかプログラムを走らせていくうちに俊敏に反応するようになってくる. これは, AWS の GPU 搭載型仮想マシンの運用方法に起因する現象だと考えられる.</p><p>先ほど,ポートフォワーディングのオプションをつけて SSH 接続をしているので, Jupyter の起動している <code>localhost:8888</code> には,ローカルマシンの <code>localhost:8931</code> からアクセスすることができる. したがって,ローカルマシンから Jupyter にアクセスするには,ウェブブラウザ (Chrome, FireFox など)から次のアドレスにアクセスすれば良い.</p><p><a href="http://localhost:8931/?token=XXXX&amp;lt;/programlisting&amp;gt" target="_blank" rel="noreferrer">http://localhost:8931/?token=XXXX&amp;lt;/programlisting&amp;gt</a>;</p><p><code>?token=XXXX</code> の部分は,上で Jupyter を起動したときに発行されたトークンの値に置き換える.</p><p>上のアドレスにアクセスすると, Jupyter のホーム画面が起動するはずである (<a href="#handson_02_jupyter_home">figure_title</a>) これで, Jupyter の準備が整った!</p><p><img src="'+T+'" alt="Jupyter ホーム画面"></p><p>Jupyter Notebook の使い方 (超簡易版)</p><ul><li><p><code>Shift</code> + <code>Enter</code>: セルを実行</p></li><li><p><code>Esc</code>: <strong>Command mode</strong> に遷移</p></li><li><p>メニューバーの &quot;+&quot; ボタン または Command mode で <code>A</code> ⇒ セルを追加</p></li><li><p>メニューバーの &quot;ハサミ&quot; ボタン または Command mode で <code>X</code> ⇒ セルを削除</p></li></ul><p>ショートカットの一覧などは <a href="https://towardsdatascience.com/jypyter-notebook-shortcuts-bf0101a98330" target="_blank" rel="noreferrer">Ventsislav Yordanov 氏によるブログ</a> が参考になる.</p><h2 id="pytorch-はじめの一歩" tabindex="-1">PyTorch はじめの一歩 <a class="header-anchor" href="#pytorch-はじめの一歩" aria-label="Permalink to &quot;PyTorch はじめの一歩&quot;"></a></h2><p><a href="https://pytorch.org/" target="_blank" rel="noreferrer">PyTorch</a> は Facebook AI Research LAB (FAIR) が中心となって開発を進めている,オープンソースのディープラーニングのライブラリである. PyTorch は 有名な例で言えば Tesla 社の自動運転プロジェクトなどで使用されており,執筆時点において最も人気の高いディープラーニングライブラリの一つである. 本ハンズオンでは, PyTorch を使ってディープラーニングの実践を行う.</p><p>PyTorch の歴史のお話</p><p>Facebook は PyTorch のほかに Caffe2 とよばれるディープラーニングのフレームワークを開発していた (初代 Caffe は UC Berkley の博士課程学生だった Yangqing Jia によって創られた) Caffe2 は 2018 年に PyTorch プロジェクトに合併された.</p><p>また2019 年 12 月,日本の Preferred Networks 社が開発していた <a href="https://chainer.org/" target="_blank" rel="noreferrer">Chainer</a> も開発を終了しPyTorch の開発チームと協業していくことが発表された (詳しくは <a href="https://chainer.org/announcement/2019/12/05/released-v7-ja.html" target="_blank" rel="noreferrer">プレスリリース</a> を参照) PyTorch には,開発統合前から Chainer からインスパイアされた API がいくつもあり, Chainer の DNA は今も PyTorch に引き継がれているのである…!</p><p>本格的なディープラーニングの計算に移る前に, PyTorch ライブラリを使って, GPU で計算を行うとはどういうものか,その入り口に触れてみよう.</p><p>まずは,新しいノートブックを作成する. Jupyter のホーム画面の右上の &quot;New&quot; を押し,&quot;conda_pytorch_p36&quot; という環境を選択したうえで,新規ノートブックを作成する (<a href="#handson_02_jupyeter_new">figure_title</a>) &quot;conda_pytorch_p36&quot; の仮想環境には, PyTorch がインストール済みである.</p><p><img src="'+W+'" alt="新規ノートブックの作成. &quot;conda_pytorch_p36&quot; の環境を選択する."></p><p>ここでは,次のようなプログラムを書いて,実行していく. (<a href="#handson_02_jupyeter_pytorch">figure_title</a>)</p><p><img src="'+$+`" alt="PyTorch始めの一歩"></p><p>まずは, PyTorch をインポートする.さらに, GPU が使える環境にあるか,確認する.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> torch</span></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#839496;">(</span><span style="color:#2AA198;">&quot;Is CUDA ready?&quot;</span><span style="color:#839496;">, torch.cuda.is_available())</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> torch</span></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#657B83;">(</span><span style="color:#2AA198;">&quot;Is CUDA ready?&quot;</span><span style="color:#657B83;">, torch.cuda.is_available())</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>出力:</p><p>Is CUDA ready? True&lt;/programlisting&gt;</p><p>次に3x3 のランダムな行列を <strong>CPU</strong> 上に作ってみよう.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">x </span><span style="color:#859900;">=</span><span style="color:#839496;"> torch.rand(</span><span style="color:#D33682;">3</span><span style="color:#839496;">,</span><span style="color:#D33682;">3</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#839496;">(x)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">x </span><span style="color:#859900;">=</span><span style="color:#657B83;"> torch.rand(</span><span style="color:#D33682;">3</span><span style="color:#657B83;">,</span><span style="color:#D33682;">3</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#657B83;">(x)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>出力:</p><p>tensor([[0.6896, 0.2428, 0.3269], [0.0533, 0.3594, 0.9499], [0.9764, 0.5881, 0.0203]])&lt;/programlisting&gt;</p><p>次に,行列を <strong>GPU</strong> 上に作成する.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">y </span><span style="color:#859900;">=</span><span style="color:#839496;"> torch.ones_like(x, device</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;cuda&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">x </span><span style="color:#859900;">=</span><span style="color:#839496;"> x.to(</span><span style="color:#2AA198;">&quot;cuda&quot;</span><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">y </span><span style="color:#859900;">=</span><span style="color:#657B83;"> torch.ones_like(x, device</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;cuda&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">x </span><span style="color:#859900;">=</span><span style="color:#657B83;"> x.to(</span><span style="color:#2AA198;">&quot;cuda&quot;</span><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>そして,行列 <code>x</code> と <code>y</code> の加算を,<strong>GPU 上で実行する</strong></p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">z </span><span style="color:#859900;">=</span><span style="color:#839496;"> x </span><span style="color:#859900;">+</span><span style="color:#839496;"> y</span></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#839496;">(z)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">z </span><span style="color:#859900;">=</span><span style="color:#657B83;"> x </span><span style="color:#859900;">+</span><span style="color:#657B83;"> y</span></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#657B83;">(z)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>出力:</p><p>tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]], device=&#39;cuda:0&#39;)&lt;/programlisting&gt;</p><p>最後に, GPU 上にある行列を, CPU に戻す.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">z </span><span style="color:#859900;">=</span><span style="color:#839496;"> z.to(</span><span style="color:#2AA198;">&quot;cpu&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#839496;">(z)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">z </span><span style="color:#859900;">=</span><span style="color:#657B83;"> z.to(</span><span style="color:#2AA198;">&quot;cpu&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#657B83;">(z)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>出力:</p><p>tensor([[1.6896, 1.2428, 1.3269], [1.0533, 1.3594, 1.9499], [1.9764, 1.5881, 1.0203]])&lt;/programlisting&gt;</p><p>以上の例は, GPU を使った計算の初歩の初歩であるが,雰囲気はつかめただろうか? CPU と GPU で明示的にデータを交換するのが肝である. この例はたった 3x3 の行列の足し算なので, GPU を使う意味はまったくないが,これが数千,数万のサイズの行列になったとき, GPU は格段の威力を発揮する.</p><p>完成した Jupyter Notebook は <a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/mnist/pytorch/pytorch_get_started.ipynb" target="_blank" rel="noreferrer">/handson/mnist/pytorch/pytorch_get_started.ipynb</a> にある. Jupyter の画面右上の &quot;Upload&quot; からこのファイルをアップロードして,コードを走らせることが可能である.</p><p>しなしながら,勉強のときにはコードはすべて自分の手で打つことが,記憶に残りやすくより効果的である,というのが筆者の意見である.</p><p>実際にベンチマークを取ることで GPU と CPU の速度を比較をしてみよう. 実行時間を計測するツールとして, Jupyter の提供する <a href="https://ipython.readthedocs.io/en/stable/interactive/magics.html" target="_blank" rel="noreferrer">%time</a> マジックコマンドを利用する.</p><p>まずは CPU を使用して10000x10000 の行列の行列積を計算した場合の速度を測ってみよう. 先ほどのノートブックの続きに,次のコードを実行する.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">s </span><span style="color:#859900;">=</span><span style="color:#839496;"> </span><span style="color:#D33682;">10000</span></span>
<span class="line"><span style="color:#839496;">device </span><span style="color:#859900;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;cpu&quot;</span></span>
<span class="line"><span style="color:#839496;">x </span><span style="color:#859900;">=</span><span style="color:#839496;"> torch.rand(s, s, device</span><span style="color:#859900;">=</span><span style="color:#839496;">device, dtype</span><span style="color:#859900;">=</span><span style="color:#839496;">torch.float32)</span></span>
<span class="line"><span style="color:#839496;">y </span><span style="color:#859900;">=</span><span style="color:#839496;"> torch.rand(s, s, device</span><span style="color:#859900;">=</span><span style="color:#839496;">device, dtype</span><span style="color:#859900;">=</span><span style="color:#839496;">torch.float32)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#859900;">%</span><span style="color:#839496;">time z </span><span style="color:#859900;">=</span><span style="color:#839496;"> torch.matmul(x,y)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">s </span><span style="color:#859900;">=</span><span style="color:#657B83;"> </span><span style="color:#D33682;">10000</span></span>
<span class="line"><span style="color:#657B83;">device </span><span style="color:#859900;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;cpu&quot;</span></span>
<span class="line"><span style="color:#657B83;">x </span><span style="color:#859900;">=</span><span style="color:#657B83;"> torch.rand(s, s, device</span><span style="color:#859900;">=</span><span style="color:#657B83;">device, dtype</span><span style="color:#859900;">=</span><span style="color:#657B83;">torch.float32)</span></span>
<span class="line"><span style="color:#657B83;">y </span><span style="color:#859900;">=</span><span style="color:#657B83;"> torch.rand(s, s, device</span><span style="color:#859900;">=</span><span style="color:#657B83;">device, dtype</span><span style="color:#859900;">=</span><span style="color:#657B83;">torch.float32)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#859900;">%</span><span style="color:#657B83;">time z </span><span style="color:#859900;">=</span><span style="color:#657B83;"> torch.matmul(x,y)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>出力は以下のようなものが得られるだろう. これは,行列積の計算に実時間で 5.8 秒かかったことを意味する (実行のたびに計測される時間はばらつくことに留意)</p><p>CPU times: user 11.5 s, sys: 140 ms, total: 11.6 s Wall time: 5.8 s&lt;/programlisting&gt;</p><p>次に, GPU を使用して,同じ演算を行った場合の速度を計測しよう.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">s </span><span style="color:#859900;">=</span><span style="color:#839496;"> </span><span style="color:#D33682;">10000</span></span>
<span class="line"><span style="color:#839496;">device </span><span style="color:#859900;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;cuda&quot;</span></span>
<span class="line"><span style="color:#839496;">x </span><span style="color:#859900;">=</span><span style="color:#839496;"> torch.rand(s, s, device</span><span style="color:#859900;">=</span><span style="color:#839496;">device, dtype</span><span style="color:#859900;">=</span><span style="color:#839496;">torch.float32)</span></span>
<span class="line"><span style="color:#839496;">y </span><span style="color:#859900;">=</span><span style="color:#839496;"> torch.rand(s, s, device</span><span style="color:#859900;">=</span><span style="color:#839496;">device, dtype</span><span style="color:#859900;">=</span><span style="color:#839496;">torch.float32)</span></span>
<span class="line"><span style="color:#839496;">torch.cuda.synchronize()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#859900;">%</span><span style="color:#839496;">time z </span><span style="color:#859900;">=</span><span style="color:#839496;"> torch.matmul(x,y); torch.cuda.synchronize()</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">s </span><span style="color:#859900;">=</span><span style="color:#657B83;"> </span><span style="color:#D33682;">10000</span></span>
<span class="line"><span style="color:#657B83;">device </span><span style="color:#859900;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;cuda&quot;</span></span>
<span class="line"><span style="color:#657B83;">x </span><span style="color:#859900;">=</span><span style="color:#657B83;"> torch.rand(s, s, device</span><span style="color:#859900;">=</span><span style="color:#657B83;">device, dtype</span><span style="color:#859900;">=</span><span style="color:#657B83;">torch.float32)</span></span>
<span class="line"><span style="color:#657B83;">y </span><span style="color:#859900;">=</span><span style="color:#657B83;"> torch.rand(s, s, device</span><span style="color:#859900;">=</span><span style="color:#657B83;">device, dtype</span><span style="color:#859900;">=</span><span style="color:#657B83;">torch.float32)</span></span>
<span class="line"><span style="color:#657B83;">torch.cuda.synchronize()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#859900;">%</span><span style="color:#657B83;">time z </span><span style="color:#859900;">=</span><span style="color:#657B83;"> torch.matmul(x,y); torch.cuda.synchronize()</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>出力は以下のようなものになるだろう. GPU では 553 ミリ秒 で計算を終えることができた!</p><p>CPU times: user 334 ms, sys: 220 ms, total: 554 ms Wall time: 553 ms&lt;/programlisting&gt;</p><p>PyTorch において, GPU での演算は asynchronous (非同期) で実行される. その理由で,上のベンチマークコードでは, <code>torch.cuda.synchronize()</code> というステートメントを埋め込んである.</p><p>このベンチマークでは, <code>dtype=torch.float32</code> と指定することで32bit の浮動小数点型を用いている. ディープラーニングの学習および推論の計算には32bit 型,場合によっては 16bit 型が使われるのが一般的である. これの主な理由として,教師データやミニバッチに起因するノイズが,浮動小数点の精度よりも大きいことがあげられる. 32bit/16bit を採用することで,メモリー消費を抑えたり,計算速度の向上が達成できる.</p><p>上記のベンチマークからGPU を用いることで,<strong>約 10 倍のスピードアップ</strong>を実現することができた. スピードアップの性能は,演算の種類や行列のサイズに依存する. 行列積は,そのなかでも最も速度向上が見込まれる演算の一つである.</p><h2 id="実践ディープラーニング-mnist-手書き数字認識タスク" tabindex="-1">実践ディープラーニング! MNIST 手書き数字認識タスク <a class="header-anchor" href="#実践ディープラーニング-mnist-手書き数字認識タスク" aria-label="Permalink to &quot;実践ディープラーニング! MNIST 手書き数字認識タスク&quot;"></a></h2><p>ここまでAWS 上でディープラーニングの計算をするための概念や前提知識をながながと説明してきたが,ついにここからディープラーニングの計算を実際に走らせてみる.</p><p>ここでは,機械学習のタスクで最も初歩的かつ有名な <strong>MNIST データセットを使った数字認識</strong>を扱う (<a href="#handson_02_mnist_examples">figure_title</a>) これは0 から 9 までの手書きの数字の画像が与えられ,その数字が何の数字なのかを当てる,というシンプルなタスクである.</p><p><img src="`+L+'" alt="MNIST 手書き数字データセット"></p><p>今回は, MNIST 文字認識タスクを,<strong>畳み込みニューラルネットワーク (Convolutional Neural Network; CNN)</strong> を使って解く. ソースコードは <a href="https://github.com/tomomano/learn-aws-by-coding-source-code/tree/main/handson/mnist/pytorch" target="_blank" rel="noreferrer">/handson/minist/pytorch/</a> にある <code>mnist.ipynb</code> と <code>simple_mnist.py</code> である. なお,このプログラムは, <a href="https://github.com/pytorch/examples/tree/master/mnist" target="_blank" rel="noreferrer">PyTorch の公式 Example Project 集</a> を参考に,多少の改変を行ったものである.</p><p>まずは,カスタムのクラスや関数が定義された <code>simple_mnist.py</code> をアップロードしよう (<a href="#handson_02_jupyter_upload">figure_title</a>) 画面右上の &quot;Upload&quot; ボタンをクリックし,ファイルを選択することでアップロードができる. この Python プログラムの中にCNN のモデルや,学習の各イテレーションにおけるパラメータの更新などが記述されている. 今回はこの中身を説明することはしないが,興味のある読者は自身でソースコードを読んでみるとよい.</p><p><img src="'+G+`" alt=" をアップロード"></p><p><code>simple_mnist.py</code> をアップロードできたら,次に新しい notebook を作成しよう. &quot;conda_pytorch_p36&quot; の環境を選択することを忘れずに.</p><p>新しいノートブックが起動したら,まずは必要なライブラリをインポートしよう.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> torch</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> torch.optim </span><span style="color:#859900;">as</span><span style="color:#839496;"> optim</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> torchvision</span></span>
<span class="line"><span style="color:#859900;">from</span><span style="color:#839496;"> torchvision </span><span style="color:#859900;">import</span><span style="color:#839496;"> datasets, transforms</span></span>
<span class="line"><span style="color:#859900;">from</span><span style="color:#839496;"> matplotlib </span><span style="color:#859900;">import</span><span style="color:#839496;"> pyplot </span><span style="color:#859900;">as</span><span style="color:#839496;"> plt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># custom functions and classes</span></span>
<span class="line"><span style="color:#859900;">from</span><span style="color:#839496;"> simple_mnist </span><span style="color:#859900;">import</span><span style="color:#839496;"> Model, train, evaluate</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> torch</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> torch.optim </span><span style="color:#859900;">as</span><span style="color:#657B83;"> optim</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> torchvision</span></span>
<span class="line"><span style="color:#859900;">from</span><span style="color:#657B83;"> torchvision </span><span style="color:#859900;">import</span><span style="color:#657B83;"> datasets, transforms</span></span>
<span class="line"><span style="color:#859900;">from</span><span style="color:#657B83;"> matplotlib </span><span style="color:#859900;">import</span><span style="color:#657B83;"> pyplot </span><span style="color:#859900;">as</span><span style="color:#657B83;"> plt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># custom functions and classes</span></span>
<span class="line"><span style="color:#859900;">from</span><span style="color:#657B83;"> simple_mnist </span><span style="color:#859900;">import</span><span style="color:#657B83;"> Model, train, evaluate</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p><a href="https://pytorch.org/docs/stable/torchvision/index.html" target="_blank" rel="noreferrer">torchvision</a> パッケージにはMNIST データセットをロードするなどの便利な関数が含まれている. また,今回のハンズオンで使うカスタムのクラス・関数 (<code>Model</code>, <code>train</code>, <code>evaluate</code>) のインポートを行っている.</p><p>次にMNIST テストデータをダウンロードしよう. 同時に,画像データの輝度の正規化も行っている.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">transf </span><span style="color:#859900;">=</span><span style="color:#839496;"> transforms.Compose([transforms.ToTensor(),</span></span>
<span class="line"><span style="color:#839496;"> transforms.Normalize((</span><span style="color:#D33682;">0.1307</span><span style="color:#839496;">,), (</span><span style="color:#D33682;">0.3081</span><span style="color:#839496;">,))])</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;">trainset </span><span style="color:#859900;">=</span><span style="color:#839496;"> datasets.MNIST(root</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&#39;./data&#39;</span><span style="color:#839496;">, train</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">, download</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">, transform</span><span style="color:#859900;">=</span><span style="color:#839496;">transf)</span></span>
<span class="line"><span style="color:#839496;">trainloader </span><span style="color:#859900;">=</span><span style="color:#839496;"> torch.utils.data.DataLoader(trainset, batch_size</span><span style="color:#859900;">=</span><span style="color:#D33682;">64</span><span style="color:#839496;">, shuffle</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;">testset </span><span style="color:#859900;">=</span><span style="color:#839496;"> datasets.MNIST(root</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&#39;./data&#39;</span><span style="color:#839496;">, train</span><span style="color:#859900;">=</span><span style="color:#B58900;">False</span><span style="color:#839496;">, download</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">, transform</span><span style="color:#859900;">=</span><span style="color:#839496;">transf)</span></span>
<span class="line"><span style="color:#839496;">testloader </span><span style="color:#859900;">=</span><span style="color:#839496;"> torch.utils.data.DataLoader(testset, batch_size</span><span style="color:#859900;">=</span><span style="color:#D33682;">1000</span><span style="color:#839496;">, shuffle</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">transf </span><span style="color:#859900;">=</span><span style="color:#657B83;"> transforms.Compose([transforms.ToTensor(),</span></span>
<span class="line"><span style="color:#657B83;"> transforms.Normalize((</span><span style="color:#D33682;">0.1307</span><span style="color:#657B83;">,), (</span><span style="color:#D33682;">0.3081</span><span style="color:#657B83;">,))])</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;">trainset </span><span style="color:#859900;">=</span><span style="color:#657B83;"> datasets.MNIST(root</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&#39;./data&#39;</span><span style="color:#657B83;">, train</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">, download</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">, transform</span><span style="color:#859900;">=</span><span style="color:#657B83;">transf)</span></span>
<span class="line"><span style="color:#657B83;">trainloader </span><span style="color:#859900;">=</span><span style="color:#657B83;"> torch.utils.data.DataLoader(trainset, batch_size</span><span style="color:#859900;">=</span><span style="color:#D33682;">64</span><span style="color:#657B83;">, shuffle</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;">testset </span><span style="color:#859900;">=</span><span style="color:#657B83;"> datasets.MNIST(root</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&#39;./data&#39;</span><span style="color:#657B83;">, train</span><span style="color:#859900;">=</span><span style="color:#B58900;">False</span><span style="color:#657B83;">, download</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">, transform</span><span style="color:#859900;">=</span><span style="color:#657B83;">transf)</span></span>
<span class="line"><span style="color:#657B83;">testloader </span><span style="color:#859900;">=</span><span style="color:#657B83;"> torch.utils.data.DataLoader(testset, batch_size</span><span style="color:#859900;">=</span><span style="color:#D33682;">1000</span><span style="color:#657B83;">, shuffle</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>今回扱う MNIST データは 28x28 ピクセルの正方形の画像(モノクロ)と,それぞれのラベル(0 - 9 の数字)の組で構成されている. いくつかのデータを抽出して,可視化してみよう. <a href="#handson_02_mnist_ground_truth">figure_title</a> のような出力が得られるはずである.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">examples </span><span style="color:#859900;">=</span><span style="color:#839496;"> </span><span style="color:#268BD2;">iter</span><span style="color:#839496;">(testloader)</span></span>
<span class="line"><span style="color:#839496;">example_data, example_targets </span><span style="color:#859900;">=</span><span style="color:#839496;"> examples.next()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#839496;">(</span><span style="color:#2AA198;">&quot;Example data size:&quot;</span><span style="color:#839496;">, example_data.shape)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;">fig </span><span style="color:#859900;">=</span><span style="color:#839496;"> plt.figure(figsize</span><span style="color:#859900;">=</span><span style="color:#839496;">(</span><span style="color:#D33682;">10</span><span style="color:#839496;">,</span><span style="color:#D33682;">4</span><span style="color:#839496;">))</span></span>
<span class="line"><span style="color:#859900;">for</span><span style="color:#839496;"> i </span><span style="color:#859900;">in</span><span style="color:#839496;"> </span><span style="color:#268BD2;">range</span><span style="color:#839496;">(</span><span style="color:#D33682;">10</span><span style="color:#839496;">):</span></span>
<span class="line"><span style="color:#839496;"> plt.subplot(</span><span style="color:#D33682;">2</span><span style="color:#839496;">,</span><span style="color:#D33682;">5</span><span style="color:#839496;">,i</span><span style="color:#859900;">+</span><span style="color:#D33682;">1</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> plt.tight_layout()</span></span>
<span class="line"><span style="color:#839496;"> plt.imshow(example_data[i][</span><span style="color:#D33682;">0</span><span style="color:#839496;">], cmap</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&#39;gray&#39;</span><span style="color:#839496;">, interpolation</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&#39;none&#39;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> plt.title(</span><span style="color:#2AA198;">&quot;Ground Truth: </span><span style="color:#CB4B16;">{}</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;">.format(example_targets[i]))</span></span>
<span class="line"><span style="color:#839496;"> plt.xticks([])</span></span>
<span class="line"><span style="color:#839496;"> plt.yticks([])</span></span>
<span class="line"><span style="color:#839496;">plt.show()</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">examples </span><span style="color:#859900;">=</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">iter</span><span style="color:#657B83;">(testloader)</span></span>
<span class="line"><span style="color:#657B83;">example_data, example_targets </span><span style="color:#859900;">=</span><span style="color:#657B83;"> examples.next()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#657B83;">(</span><span style="color:#2AA198;">&quot;Example data size:&quot;</span><span style="color:#657B83;">, example_data.shape)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;">fig </span><span style="color:#859900;">=</span><span style="color:#657B83;"> plt.figure(figsize</span><span style="color:#859900;">=</span><span style="color:#657B83;">(</span><span style="color:#D33682;">10</span><span style="color:#657B83;">,</span><span style="color:#D33682;">4</span><span style="color:#657B83;">))</span></span>
<span class="line"><span style="color:#859900;">for</span><span style="color:#657B83;"> i </span><span style="color:#859900;">in</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">range</span><span style="color:#657B83;">(</span><span style="color:#D33682;">10</span><span style="color:#657B83;">):</span></span>
<span class="line"><span style="color:#657B83;"> plt.subplot(</span><span style="color:#D33682;">2</span><span style="color:#657B83;">,</span><span style="color:#D33682;">5</span><span style="color:#657B83;">,i</span><span style="color:#859900;">+</span><span style="color:#D33682;">1</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> plt.tight_layout()</span></span>
<span class="line"><span style="color:#657B83;"> plt.imshow(example_data[i][</span><span style="color:#D33682;">0</span><span style="color:#657B83;">], cmap</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&#39;gray&#39;</span><span style="color:#657B83;">, interpolation</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&#39;none&#39;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> plt.title(</span><span style="color:#2AA198;">&quot;Ground Truth: </span><span style="color:#CB4B16;">{}</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;">.format(example_targets[i]))</span></span>
<span class="line"><span style="color:#657B83;"> plt.xticks([])</span></span>
<span class="line"><span style="color:#657B83;"> plt.yticks([])</span></span>
<span class="line"><span style="color:#657B83;">plt.show()</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p><img src="`+N+`" alt="MNIST の手書き数字画像とその教師ラベル"></p><p>次に, CNN のモデルを定義する.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">model </span><span style="color:#859900;">=</span><span style="color:#839496;"> Model()</span></span>
<span class="line"><span style="color:#839496;">model.to(</span><span style="color:#2AA198;">&quot;cuda&quot;</span><span style="color:#839496;">) </span><span style="color:#586E75;font-style:italic;"># load to GPU</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">model </span><span style="color:#859900;">=</span><span style="color:#657B83;"> Model()</span></span>
<span class="line"><span style="color:#657B83;">model.to(</span><span style="color:#2AA198;">&quot;cuda&quot;</span><span style="color:#657B83;">) </span><span style="color:#93A1A1;font-style:italic;"># load to GPU</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>今回使う <code>Model</code> は <code>simple_mnist.py</code> の中で定義されている. このモデルは,<a href="#handson_02_cnn_architecture">figure_title</a> に示したような,2層の畳み込み層と 2 層の全結合層からなるネットワークである. 出力層 (output layer) には Softmax 関数を使用し,損失関数 (Loss function) には 負の対数尤度関数 (Negative log likelyhood; NLL) を使用している.</p><p><img src="`+U+`" alt="本ハンズオンで使用するニューラルネットの構造."></p><p>続いて, CNN のパラメータを更新する最適化アルゴリズムを定義する. ここでは, <strong>確率的勾配降下法 (Stochastic Gradient Descent; SGD)</strong> を使用している.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">optimizer </span><span style="color:#859900;">=</span><span style="color:#839496;"> optim.SGD(model.parameters(), lr</span><span style="color:#859900;">=</span><span style="color:#D33682;">0.01</span><span style="color:#839496;">, momentum</span><span style="color:#859900;">=</span><span style="color:#D33682;">0.5</span><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">optimizer </span><span style="color:#859900;">=</span><span style="color:#657B83;"> optim.SGD(model.parameters(), lr</span><span style="color:#859900;">=</span><span style="color:#D33682;">0.01</span><span style="color:#657B83;">, momentum</span><span style="color:#859900;">=</span><span style="color:#D33682;">0.5</span><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>これで,準備が整った. CNN の学習ループを開始しよう!</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">train_losses </span><span style="color:#859900;">=</span><span style="color:#839496;"> []</span></span>
<span class="line"><span style="color:#859900;">for</span><span style="color:#839496;"> epoch </span><span style="color:#859900;">in</span><span style="color:#839496;"> </span><span style="color:#268BD2;">range</span><span style="color:#839496;">(</span><span style="color:#D33682;">5</span><span style="color:#839496;">):</span></span>
<span class="line"><span style="color:#839496;"> losses </span><span style="color:#859900;">=</span><span style="color:#839496;"> train(model, trainloader, optimizer, epoch)</span></span>
<span class="line"><span style="color:#839496;"> train_losses </span><span style="color:#859900;">=</span><span style="color:#839496;"> train_losses </span><span style="color:#859900;">+</span><span style="color:#839496;"> losses</span></span>
<span class="line"><span style="color:#839496;"> test_loss, test_accuracy </span><span style="color:#859900;">=</span><span style="color:#839496;"> evaluate(model, testloader)</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">print</span><span style="color:#839496;">(</span><span style="color:#93A1A1;font-weight:bold;">f</span><span style="color:#2AA198;">&quot;</span><span style="color:#CB4B16;">\\n</span><span style="color:#2AA198;">Test set: Average loss: </span><span style="color:#CB4B16;">{</span><span style="color:#839496;">test_loss</span><span style="color:#93A1A1;font-weight:bold;">:.4f</span><span style="color:#CB4B16;">}</span><span style="color:#2AA198;">, Accuracy: </span><span style="color:#CB4B16;">{</span><span style="color:#839496;">test_accuracy</span><span style="color:#93A1A1;font-weight:bold;">:.1f</span><span style="color:#CB4B16;">}</span><span style="color:#2AA198;">%</span><span style="color:#CB4B16;">\\n</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;">plt.figure(figsize</span><span style="color:#859900;">=</span><span style="color:#839496;">(</span><span style="color:#D33682;">7</span><span style="color:#839496;">,</span><span style="color:#D33682;">5</span><span style="color:#839496;">))</span></span>
<span class="line"><span style="color:#839496;">plt.plot(train_losses)</span></span>
<span class="line"><span style="color:#839496;">plt.xlabel(</span><span style="color:#2AA198;">&quot;Iterations&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">plt.ylabel(</span><span style="color:#2AA198;">&quot;Train loss&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">plt.show()</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">train_losses </span><span style="color:#859900;">=</span><span style="color:#657B83;"> []</span></span>
<span class="line"><span style="color:#859900;">for</span><span style="color:#657B83;"> epoch </span><span style="color:#859900;">in</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">range</span><span style="color:#657B83;">(</span><span style="color:#D33682;">5</span><span style="color:#657B83;">):</span></span>
<span class="line"><span style="color:#657B83;"> losses </span><span style="color:#859900;">=</span><span style="color:#657B83;"> train(model, trainloader, optimizer, epoch)</span></span>
<span class="line"><span style="color:#657B83;"> train_losses </span><span style="color:#859900;">=</span><span style="color:#657B83;"> train_losses </span><span style="color:#859900;">+</span><span style="color:#657B83;"> losses</span></span>
<span class="line"><span style="color:#657B83;"> test_loss, test_accuracy </span><span style="color:#859900;">=</span><span style="color:#657B83;"> evaluate(model, testloader)</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">print</span><span style="color:#657B83;">(</span><span style="color:#586E75;font-weight:bold;">f</span><span style="color:#2AA198;">&quot;</span><span style="color:#CB4B16;">\\n</span><span style="color:#2AA198;">Test set: Average loss: </span><span style="color:#CB4B16;">{</span><span style="color:#657B83;">test_loss</span><span style="color:#586E75;font-weight:bold;">:.4f</span><span style="color:#CB4B16;">}</span><span style="color:#2AA198;">, Accuracy: </span><span style="color:#CB4B16;">{</span><span style="color:#657B83;">test_accuracy</span><span style="color:#586E75;font-weight:bold;">:.1f</span><span style="color:#CB4B16;">}</span><span style="color:#2AA198;">%</span><span style="color:#CB4B16;">\\n</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;">plt.figure(figsize</span><span style="color:#859900;">=</span><span style="color:#657B83;">(</span><span style="color:#D33682;">7</span><span style="color:#657B83;">,</span><span style="color:#D33682;">5</span><span style="color:#657B83;">))</span></span>
<span class="line"><span style="color:#657B83;">plt.plot(train_losses)</span></span>
<span class="line"><span style="color:#657B83;">plt.xlabel(</span><span style="color:#2AA198;">&quot;Iterations&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">plt.ylabel(</span><span style="color:#2AA198;">&quot;Train loss&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">plt.show()</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>ここでは 5 エポック分の学習を行っている. GPU を使えば,これくらいの計算であれば 1 分程度で完了するだろう.</p><p>出力として, <a href="#handson_02_train_loss">figure_title</a> のようなプロットが得られるはずである. イテレーションを重ねるにつれて,損失関数 (Loss function) の値が減少している (=精度が向上している) ことがわかる.</p><p><img src="`+R+'" alt="学習の進行に対する Train loss の変化"></p><p>出力にはテキスト形式で各エポック終了後のテストデータに対する精度も表示されている. 最終的には 98% 以上の極めて高い精度を実現できていることが確認できるだろう (<a href="#handson_02_mnist_final_score">figure_title</a>)</p><p><img src="'+X+`" alt="学習したCNNのテストデータに対するスコア (5エポック後)"></p><p>学習した CNN の推論結果を可視化してみよう. 次のコードを実行することで, <a href="#handson_02_mnist_mnist_prediction">figure_title</a> のような出力が得られるだろう. この図で,下段右から二番目は,&quot;1&quot;に近い見た目をしているが,きちんと&quot;9&quot;と推論できている. なかなか賢い CNN を作り出すことができたようだ!</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">model.eval()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#859900;">with</span><span style="color:#839496;"> torch.no_grad():</span></span>
<span class="line"><span style="color:#839496;"> output </span><span style="color:#859900;">=</span><span style="color:#839496;"> model(example_data.to(</span><span style="color:#2AA198;">&quot;cuda&quot;</span><span style="color:#839496;">))</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;">fig </span><span style="color:#859900;">=</span><span style="color:#839496;"> plt.figure(figsize</span><span style="color:#859900;">=</span><span style="color:#839496;">(</span><span style="color:#D33682;">10</span><span style="color:#839496;">,</span><span style="color:#D33682;">4</span><span style="color:#839496;">))</span></span>
<span class="line"><span style="color:#859900;">for</span><span style="color:#839496;"> i </span><span style="color:#859900;">in</span><span style="color:#839496;"> </span><span style="color:#268BD2;">range</span><span style="color:#839496;">(</span><span style="color:#D33682;">10</span><span style="color:#839496;">):</span></span>
<span class="line"><span style="color:#839496;"> plt.subplot(</span><span style="color:#D33682;">2</span><span style="color:#839496;">,</span><span style="color:#D33682;">5</span><span style="color:#839496;">,i</span><span style="color:#859900;">+</span><span style="color:#D33682;">1</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> plt.tight_layout()</span></span>
<span class="line"><span style="color:#839496;"> plt.imshow(example_data[i][</span><span style="color:#D33682;">0</span><span style="color:#839496;">], cmap</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&#39;gray&#39;</span><span style="color:#839496;">, interpolation</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&#39;none&#39;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> plt.title(</span><span style="color:#2AA198;">&quot;Prediction: </span><span style="color:#CB4B16;">{}</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;">.format(output.data.max(</span><span style="color:#D33682;">1</span><span style="color:#839496;">, keepdim</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">)[</span><span style="color:#D33682;">1</span><span style="color:#839496;">][i].item()))</span></span>
<span class="line"><span style="color:#839496;"> plt.xticks([])</span></span>
<span class="line"><span style="color:#839496;"> plt.yticks([])</span></span>
<span class="line"><span style="color:#839496;">plt.show()</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">model.eval()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#859900;">with</span><span style="color:#657B83;"> torch.no_grad():</span></span>
<span class="line"><span style="color:#657B83;"> output </span><span style="color:#859900;">=</span><span style="color:#657B83;"> model(example_data.to(</span><span style="color:#2AA198;">&quot;cuda&quot;</span><span style="color:#657B83;">))</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;">fig </span><span style="color:#859900;">=</span><span style="color:#657B83;"> plt.figure(figsize</span><span style="color:#859900;">=</span><span style="color:#657B83;">(</span><span style="color:#D33682;">10</span><span style="color:#657B83;">,</span><span style="color:#D33682;">4</span><span style="color:#657B83;">))</span></span>
<span class="line"><span style="color:#859900;">for</span><span style="color:#657B83;"> i </span><span style="color:#859900;">in</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">range</span><span style="color:#657B83;">(</span><span style="color:#D33682;">10</span><span style="color:#657B83;">):</span></span>
<span class="line"><span style="color:#657B83;"> plt.subplot(</span><span style="color:#D33682;">2</span><span style="color:#657B83;">,</span><span style="color:#D33682;">5</span><span style="color:#657B83;">,i</span><span style="color:#859900;">+</span><span style="color:#D33682;">1</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> plt.tight_layout()</span></span>
<span class="line"><span style="color:#657B83;"> plt.imshow(example_data[i][</span><span style="color:#D33682;">0</span><span style="color:#657B83;">], cmap</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&#39;gray&#39;</span><span style="color:#657B83;">, interpolation</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&#39;none&#39;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> plt.title(</span><span style="color:#2AA198;">&quot;Prediction: </span><span style="color:#CB4B16;">{}</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;">.format(output.data.max(</span><span style="color:#D33682;">1</span><span style="color:#657B83;">, keepdim</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">)[</span><span style="color:#D33682;">1</span><span style="color:#657B83;">][i].item()))</span></span>
<span class="line"><span style="color:#657B83;"> plt.xticks([])</span></span>
<span class="line"><span style="color:#657B83;"> plt.yticks([])</span></span>
<span class="line"><span style="color:#657B83;">plt.show()</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p><img src="`+M+'" alt="学習した CNN によるMNIST画像の推論結果"></p><p>最後に,学習したニューラルネットワークのパラメータを <code>mnist_cnn.pt</code> というファイル名で保存しておこう. これで,将来いつでも今回学習したモデルを再現し,別の実験に使用することができる.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">torch.save(model.state_dict(), </span><span style="color:#2AA198;">&quot;mnist_cnn.pt&quot;</span><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">torch.save(model.state_dict(), </span><span style="color:#2AA198;">&quot;mnist_cnn.pt&quot;</span><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>以上が, AWS クラウドの仮想サーバーを立ち上げ,最初のディープラーニングの計算を行う一連の流れである. MNIST 文字認識のタスクを行うニューラルネットを,クラウド上の GPU を使って高速に学習させ,現実的な問題を一つ解くことができたのである. 興味のある読者は,今回のハンズオンを雛形に,自分の所望の計算を走らせてみるとよいだろう.</p><h2 id="スタックの削除" tabindex="-1">スタックの削除 <a class="header-anchor" href="#スタックの削除" aria-label="Permalink to &quot;スタックの削除&quot;"></a></h2><p>これにて,ハンズオン第二回の内容はすべて説明した. クラウドの利用料金を最小化するため,使い終わった EC2 インスタンスはすぐさま削除しよう.</p><p>ハンズオン第一回と同様に, AWS の CloudFormation コンソールか, AWS CLI により削除を実行する (詳細は <a href="#handson_01_delete_stack">スタックを削除</a> 参照)</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p><strong>スタックの削除は各自で必ず行うこと!</strong> 行わなかった場合EC2 インスタンスの料金が発生し続けることになる! <code>g4dn.xlarge</code> は $0.71 / hour の料金設定なので,一日起動しつづけると約$17 の請求が発生することになる!</p><p><strong>AWS のバジェットアラート</strong></p><p>AWS の初心者が (あるいは経験者も) しばしば陥る失敗が,インスタンスの停止忘れなどで無駄なリソースがクラウドで放置されてしまい,巨大な額の請求が届く,というミスだ. 特に,開発を行っている間はこのような事態は起こりうるものだと思って,備えておかなければならない. このような事態を未然に防ぐため, AWS Budgets という機能が無料で提供されている. AWS Budgets を利用することで,月の利用金額がある閾値を超えた場合にユーザーにメールが送信される,などのアラートを設定することができる. 詳細な手順は <a href="https://aws.amazon.com/blogs/aws-cost-management/getting-started-with-aws-budgets/" target="_blank" rel="noreferrer">AWS の公式ブログ &quot;Getting Started with AWS Budgets&quot;</a> を参照のこと. 本書の読者も,ぜひこのタイミングでアラートを設定しておくことを推奨する.</p><h1 id="docker-入門" tabindex="-1">Docker 入門 <a class="header-anchor" href="#docker-入門" aria-label="Permalink to &quot;Docker 入門&quot;"></a></h1><p>ここまでの章で扱ってきたハンズオンでは,<strong>単一のサーバー</strong>を立ち上げ,それに SSH でログインをして,コマンドを叩くことで計算を行ってきた. いわば,<em>パーソナルコンピュータの延長</em>のような形でクラウドを使ってきたわけである. このような,インターネットのどこからでもアクセスできるパーソナルコンピュータとしてのクラウドという使い方も,もちろん便利であるし,いろいろな応用の可能性がある. しかし,これだけではクラウドの本当の価値は十分に発揮されていないと言うべきだろう. <a href="#chap_cloud_basics">クラウド概論</a> で述べたように,現代的なクラウドの一番の強みは自由に計算機の規模を拡大できることにある. すなわち,<strong>多数のサーバーを同時に起動し,複数のジョブを分散並列的に実行させることで大量のデータを処理してこそ,クラウドの本領が発揮される</strong>のである.</p><p>本章からはじまる 3 章分 (<a href="#sec_docker_introduction">Docker 入門</a>, <a href="#sec_fargate_qabot">Hands-on #3: AWS で自動質問回答ボットを走らせる</a>, <a href="#sec_aws_batch">Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する</a>) を使って,クラウドを利用することでどのように大規模な計算システムを構築しビッグデータの解析に立ち向かうのか,その片鱗をお見せしたい. とくに,前章で扱った深層学習をどのようにビッグデータに適用していくかという点に焦点を絞って議論していきたい. そのための前準備として,本章では <a href="https://www.docker.com/" target="_blank" rel="noreferrer">Docker</a> とよばれる計算機環境の仮想化ソフトウェアを紹介する (<a href="#fig:docker_logo">figure_title</a>) 現代のクラウドは Docker なしには成り立たないといっても過言ではないだろう. クラウドに限らず,ローカルで行う計算処理にも Docker は大変便利である. AWS からは少し話が離れるが,しっかりと理解して前に進んでもらいたい.</p><h2 id="機械学習の大規模化" tabindex="-1">機械学習の大規模化 <a class="header-anchor" href="#機械学習の大規模化" aria-label="Permalink to &quot;機械学習の大規模化&quot;"></a></h2><p>先ほどから&quot;計算システムの大規模化&quot;と繰り返し唱えているが,それは具体的にはどのようなものを指しているのか? ここでは大規模データを処理するための計算機システムを,機械学習を例にとって見てみよう.</p><p><a href="#sec_scientific_computing">クラウドで行う科学計算・機械学習</a> で紹介した <a href="https://github.com/openai/gpt-3" target="_blank" rel="noreferrer">GPT-3</a> のような,超巨大な数のパラメータを有する深層学習モデルを学習させたいとしよう. そのような計算を行いたい場合,一つのサーバーでは計算力が到底足りない. したがって,典型的には <a href="#big_dnn_training">figure_title</a> に示すような計算システムの設計がなされる. すなわち,大量の教師データを小さなチャンクとして複数のマシンに分散し,並列的にニューラルネットのパラメータを最適化していくという構造である.</p><p><img src="'+H+'" alt="複数の計算機を使った大規模な深層学習モデルの訓練"></p><p>あるいは,学習済みのモデルを大量のデータに適用し,解析を行いたいとしよう. たとえば, SNS のプラットフォームで大量の画像が与えられて,それぞれの写真に何が写っているのかをラベルづけする,などのアプリケーションを想定できる. そのような場合は, <a href="#big_dnn_inference">figure_title</a> のようなアーキテクチャが考えられるだろう. すなわち,大量のデータを複数のマシンで分割し,それぞれのマシンで推論の計算を行うというような構造である.</p><p><img src="'+F+'" alt="複数の計算機による深層学習モデルを使った推論計算"></p><p>このような複数の計算機を同時に走らせるようなアプリケーションをクラウド上で実現するには,どのようにすればよいのだろうか?</p><p>重要なポイントとして, <a href="#big_dnn_training">figure_title</a> や <a href="#big_dnn_inference">figure_title</a> で起動している複数のマシンは,<strong>基本的に全く同一の OS・計算環境を有している</strong>点である. ここで,個人のコンピュータで行うようなインストールの操作を,各マシンで行うこともできるが,それは大変な手間であるし,メンテナンスも面倒だろう. すなわち,大規模な計算システムを構築するには,<strong>簡単に計算環境を複製できるような仕組み</strong>が必要であるということがわかる.</p><p>そのような目的を実現するために使われるのが, <a href="https://www.docker.com/" target="_blank" rel="noreferrer">Docker</a> とよばれるソフトウェアである.</p><h2 id="docker-とは" tabindex="-1">Docker とは <a class="header-anchor" href="#docker-とは" aria-label="Permalink to &quot;Docker とは&quot;"></a></h2><p><img src="'+O+'" alt="Docker のアイコン"></p><p>Docker とは, <strong>コンテナ (Container)</strong> とよばれる仮想環境下で,ホスト OS とは独立した別の計算環境を走らせるためのソフトウェアである. Docker を使うことで, OS を含めたすべてのプログラムをコンパクトにパッケージングすることが可能になる (パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ) Docker を使うことで,クラウドのサーバー上に瞬時に計算環境を複製することが可能になり, <a href="#big_dnn_inference">figure_title</a> で見たような複数の計算機を同時に走らせるためのシステムが実現できる.</p><p>Docker は 2013 年に Solomon Hykes らを中心に開発され,それ以降爆発的に普及し,クラウドコンピューティングだけでなく,機械学習・科学計算の文脈などでも欠かすことのできないソフトウェアとなった. Docker はエンタープライズ向けの製品を除き無料で使用することができ,コアの部分は <a href="https://github.com/moby/moby" target="_blank" rel="noreferrer">オープンソースプロジェクト</a> として公開されている. Docker は Linux, Windows, Mac いずれの OS でも提供されている. 概念としては, Docker は仮想マシン (Virtual machine; VM) にとても近い. ここでは, VM との対比をしながらDocker とはなにかを簡単に説明しよう.</p><p>仮想マシン (VM) とは,ホストとなるマシンの上に,仮想化された OS を走らせる技術である (<a href="#docker_vs_vm">figure_title</a>) VM には <strong>ハイパーバイザー (Hypervisor)</strong> とよばれるレイヤーが存在する. Hypervisor はまず,物理的な計算機リソース (CPU, RAM, network など) を分割し,仮想化する. たとえば, ホストマシンに物理的な CPU が 4 コアあるとして,ハイパーバイザーはそれを (2,2) 個の組に仮想的に分割することができる. VM 上で起動する OS には,ハイパーバイザーによって仮想化されたハードウェアが割り当てられる. VM 上で起動する OS は基本的に完全に独立であり,たとえば OS-A は OS-B に割り当てられた CPU やメモリー領域にアクセスすることはできない (これを isolation とよぶ) VM を作成するための有名なソフトウェアとしては, <a href="https://www.vmware.com/" target="_blank" rel="noreferrer">VMware</a> <a href="https://www.virtualbox.org/" target="_blank" rel="noreferrer">VirtualBox</a> <a href="https://xenproject.org/" target="_blank" rel="noreferrer">Xen</a> などがある. また,これまで触ってきた EC2 も,基本的に VM 技術を使うことで所望のスペックをもった仮想マシンがユーザーに提示される.</p><p>Docker も, VM と同様に,仮想化された OS をホストの OS 上に走らせるための技術である. VM に対し, Docker ではハードウェアレベルの仮想化は行われておらず,すべての<strong>仮想化はソフトウェアレベルで実現されている</strong> (<a href="#docker_vs_vm">figure_title</a>) Docker で走る仮想 OS は,<strong>多くの部分をホストの OS に依存しており,結果として非常にコンパクトである</strong> その結果, Docker で仮想 OS を起動するために要する時間は, VM に比べて圧倒的に早い. また, パッケージ化された環境 (=イメージ) のサイズも完全な OS に比べ圧倒的に小さくなるので,ネットワークを通じたやり取りが非常に高速化される点も重要である 加えて, VM のいくつかの実装では,メタル (仮想化マシンに対して,物理的なハードウェア上で直接起動する場合のこと) と比べ,ハイパーバイザーレイヤーでのオーバーヘッドなどにより性能が低下することが知られているが, Docker ではメタルとほぼ同様の性能を引き出すことができるとされている.</p><p>その他, VM との相違点などはたくさんあるのだが,ここではこれ以上詳細には立ち入らない. 大事なのは, <strong>Docker とはとてもコンパクトかつハイパフォーマンスな仮想計算環境を作るツールである</strong>,という点である. その手軽さゆえに2013 年の登場以降,クラウドシステムでの利用が急速に増加し,現代のクラウドでは欠くことのできない中心的な技術になっている.</p><p><img src="'+j+'" alt="Docker (左) と VM (右) の比較 (画像出典: https://www.docker.com/blog/containers-replacing-virtual-machines/)"></p><p>職業的プログラマーにとっての&quot;三種の神器&quot;とはなんだろうか? 多様な意見があると思うが,筆者は <strong>Git</strong>, <strong>Vim</strong> そして <strong>Docker</strong> を挙げたい.</p><p>Git は多くの読者がご存じの通り,コードの変更を追跡するためのシステムである. Linux の作成者である Linus Torvalds によって 2005 年に誕生した. チームでの開発を進める際には欠かせないツールだ.</p><p>Vim は 1991 年から 30 年以上の間プログラマーたちに愛されてきたテキストエディターである. <a href="https://insights.stackoverflow.com/survey/2019#technology-development-environments-and-tools-all-respondents" target="_blank" rel="noreferrer">Stackoverflow が行った 2019 年のアンケート</a> によると,開発環境の部門で 5 位の人気を獲得している. たくさんのショートカットと様々なカスタム設定が提供されているので,初見の人にはなかなかハードルが高いが,一度マスターすれば他のモダンなエディターや統合開発環境に負けない,あるいはそれ以上の開発体験を実現することができる.</p><p>これらの十年以上の歴史あるツールに並んで,第三番目の三種の神器として挙げたいのが Docker だ. Docker はプログラマーの開発のワークフローを一変させた. たとえば,プロジェクトごとに Docker イメージを作成することで,どの OS・コンピュータ でも全く同じ計算環境で開発・テストを実行することができるようになった. また, <a href="https://en.wikipedia.org/wiki/DevOps" target="_blank" rel="noreferrer">DevOps</a> や <a href="https://en.wikipedia.org/wiki/Continuous_integration" target="_blank" rel="noreferrer">CI</a> / <a href="https://en.wikipedia.org/wiki/Continuous_delivery" target="_blank" rel="noreferrer">CD</a> (Continuous Integration / Continuous Deployment) といった最近の開発ワークフローも Docker のようなコンテナ技術の存在に立脚している. さらにはサーバーレスコンピューティング (<a href="#sec_serverless">Serverless architecture</a>) といった概念も,コンテナ技術の生んだ大きな技術革新といえる.</p><p>あなたにとっての三種の神器はなんだろうか? また,これからの未来ではどんな新しいツールが三種の神器としてプログラマーのワークフローを革新していくだろうか?</p><h2 id="docker-チュートリアル" tabindex="-1">Docker チュートリアル <a class="header-anchor" href="#docker-チュートリアル" aria-label="Permalink to &quot;Docker チュートリアル&quot;"></a></h2><p>Docker とはなにかを理解するためには,実際に触って動かしてみるのが一番有効な手立てである. ここでは, Docker の簡単なチュートリアルを行っていく.</p><p>Docker のインストールについては, <a href="#sec:install_docker">Docker のインストール</a> および <a href="https://docs.docker.com/engine/install/" target="_blank" rel="noreferrer">公式のドキュメンテーション</a> を参照してもらいたい. Docker のインストールが完了している前提で,以下は話を進めるものとする.</p><h3 id="docker-用語集" tabindex="-1">Docker 用語集 <a class="header-anchor" href="#docker-用語集" aria-label="Permalink to &quot;Docker 用語集&quot;"></a></h3><p>Docker を使い始めるに当たり,最初に主要な用語を解説しよう. 次のパラグラフで太字で強調された用語を頭に入れた上で,続くチュートリアルに取り組んでいただきたい.</p><p>Docker を起動する際の大まかなステップを示したのが <a href="#fig:docker_image_container">figure_title</a> である. パッケージされた一つの計算環境のことを **イメージ (Image)**とよぶ. イメージは, Docker Hub などのリポジトリで配布されているものをダウンロードするか,自分でカスタムのイメージを作成することも可能である. イメージを作成するための”レシピ”を記述したファイルが <strong>Dockerfile</strong> である. Dockerfile からイメージを作成する操作を <strong>build</strong> とよぶ. イメージがホストマシンのメモリにロードされ,起動状態にある計算環境のことを <strong>コンテナ (Container)</strong> とよぶ. Container を起動するために使用されるコマンドが <strong>run</strong> である.</p><p><img src="'+V+'" alt="Image と Container"></p><h3 id="イメージをダウンロード" tabindex="-1">イメージをダウンロード <a class="header-anchor" href="#イメージをダウンロード" aria-label="Permalink to &quot;イメージをダウンロード&quot;"></a></h3><p>パッケージ化された Docker の仮想環境 (= <strong>イメージ (Image)</strong>) は, <a href="https://hub.docker.com/" target="_blank" rel="noreferrer">Docker Hub</a> からダウンロードできる. Docker Hub には,個人や企業・団体が作成した Docker イメージが集められており, GitHub などと同じ感覚で,オープンな形で公開されている.</p><p>たとえば, Ubuntu のイメージは <a href="https://hub.docker.com/_/ubuntu" target="_blank" rel="noreferrer">Ubuntu の公式リポジトリ</a> で公開されており, <code>pull</code> コマンドを使うことでローカルにダウンロードすることができる.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pull</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ubuntu:18.04</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pull</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ubuntu:18.04</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>ここで,イメージ名の <code>:</code> (コロン) 以降に続く文字列を <strong>タグ (tag)</strong> と呼び,主にバージョンを指定するなどの目的で使われる.</p><p><code>pull</code> コマンドはデフォルトでは Docker Hub でイメージを検索し,ダウンロードを行う. Docker イメージを公開するためのデータベース (レジストリ (registry) とよぶ) は Docker Hub だけではなく,たとえば GitLab や GitHub は独自のレジストリ機能を提供しているし,個人のサーバーでレジストリを立ち上げることも可能である. Docker Hub 以外のレジストリから pull するには, <code>myregistry.local:5000/testing/test-image</code> のように,イメージ名の先頭につける形でレジストリのアドレス (さらにオプションとしてポート番号) を指定する.</p><h3 id="コンテナを起動" tabindex="-1">コンテナを起動 <a class="header-anchor" href="#コンテナを起動" aria-label="Permalink to &quot;コンテナを起動&quot;"></a></h3><p>Pull してきたイメージを起動するには, <code>run</code> コマンドを使う.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-it</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ubuntu:18.04</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-it</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ubuntu:18.04</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>ここで, <code>-it</code> とは,インタラクティブな shell のセッションを開始するために必要なオプションである.</p><p>このコマンドを実行すると,仮想化された Ubuntu が起動され,コマンドラインからコマンドが打ち込めるようになる (<a href="#docker_shell">figure_title</a>) このように起動状態にある計算環境 (ランタイム) のことを <strong>Container (コンテナ)</strong> とよぶ.</p><p><img src="'+K+`" alt="Docker を使って ubuntu:18.04 イメージを起動"></p><p>ここで使用した <code>ubuntu:18.04</code> のイメージは,空の Ubuntu OS だが,すでにプログラムがインストール済みのものもある. これは, <a href="#sec_jupyter_and_deep_learning">Hands-on #2: AWS でディープラーニングを実践</a> でみた DLAMI と概念として似ている. たとえば, PyTorch がインストール済みのイメージは <a href="https://hub.docker.com/r/pytorch/pytorch" target="_blank" rel="noreferrer">PyTorch 公式の Docker Hub リポジトリ</a> で公開されている.</p><p>これを起動してみよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-it</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pytorch/pytorch</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-it</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pytorch/pytorch</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p><code>docker run</code> を実行したとき,ローカルに該当するイメージが見つからない場合は,自動的に Docker Hub からダウンロードされる.</p><p>pytorch のコンテナが起動したら, Python のシェルを立ち上げて, pytorch をインポートしてみよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python3</span></span>
<span class="line"><span style="color:#268BD2;">Python</span><span style="color:#839496;"> </span><span style="color:#D33682;">3.7</span><span style="color:#2AA198;">.7</span><span style="color:#839496;"> (default, </span><span style="color:#2AA198;">May</span><span style="color:#839496;"> </span><span style="color:#D33682;">7</span><span style="color:#839496;"> </span><span style="color:#D33682;">2020</span><span style="color:#2AA198;">,</span><span style="color:#839496;"> </span><span style="color:#D33682;">21</span><span style="color:#2AA198;">:25:33</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">[GCC </span><span style="color:#D33682;">7.3</span><span style="color:#839496;">.0] :: Anaconda, Inc. on linux</span></span>
<span class="line"><span style="color:#268BD2;">Type</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;help&quot;,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;copyright&quot;,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;credits&quot;</span><span style="color:#839496;"> </span><span style="color:#2AA198;">or</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;license&quot;</span><span style="color:#839496;"> </span><span style="color:#2AA198;">for</span><span style="color:#839496;"> </span><span style="color:#2AA198;">more</span><span style="color:#839496;"> </span><span style="color:#2AA198;">information.</span></span>
<span class="line"><span style="color:#839496;">&gt;&gt;&gt; </span><span style="color:#268BD2;">import</span><span style="color:#839496;"> </span><span style="color:#2AA198;">torch</span></span>
<span class="line"><span style="color:#839496;">&gt;&gt;&gt; </span><span style="color:#268BD2;">torch.cuda.is_available</span><span style="color:#839496;">()</span></span>
<span class="line"><span style="color:#839496;">False</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python3</span></span>
<span class="line"><span style="color:#268BD2;">Python</span><span style="color:#657B83;"> </span><span style="color:#D33682;">3.7</span><span style="color:#2AA198;">.7</span><span style="color:#657B83;"> (default, </span><span style="color:#2AA198;">May</span><span style="color:#657B83;"> </span><span style="color:#D33682;">7</span><span style="color:#657B83;"> </span><span style="color:#D33682;">2020</span><span style="color:#2AA198;">,</span><span style="color:#657B83;"> </span><span style="color:#D33682;">21</span><span style="color:#2AA198;">:25:33</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">[GCC </span><span style="color:#D33682;">7.3</span><span style="color:#657B83;">.0] :: Anaconda, Inc. on linux</span></span>
<span class="line"><span style="color:#268BD2;">Type</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;help&quot;,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;copyright&quot;,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;credits&quot;</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">or</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;license&quot;</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">for</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">more</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">information.</span></span>
<span class="line"><span style="color:#657B83;">&gt;&gt;&gt; </span><span style="color:#268BD2;">import</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">torch</span></span>
<span class="line"><span style="color:#657B83;">&gt;&gt;&gt; </span><span style="color:#268BD2;">torch.cuda.is_available</span><span style="color:#657B83;">()</span></span>
<span class="line"><span style="color:#657B83;">False</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>このように, Docker を使うことで簡単に特定の OS・プログラムの入った計算環境を再現することが可能になる</p><h3 id="自分だけのイメージを作る" tabindex="-1">自分だけのイメージを作る <a class="header-anchor" href="#自分だけのイメージを作る" aria-label="Permalink to &quot;自分だけのイメージを作る&quot;"></a></h3><p>自分の使うソフトウェア・ライブラリがインストールされた,自分だけのイメージを作ることも可能である.</p><p>たとえば, <a href="https://hub.docker.com/repository/docker/tomomano/labc" target="_blank" rel="noreferrer">本書のハンズオン実行用に提供している docker イメージ</a> には, Python, Node.js, AWS CLI, AWS CDK などのソフトウェアがインストール済みであり,ダウンロードしてくるだけですぐにハンズオンのプログラムが実行できるようになっている.</p><p>カスタムの docker イメージを作るには, <code>Dockerfile</code> という名前のついたファイルを用意し,その中にどんなプログラムをインストールするかなどを記述していく.</p><p>具体例として,本書で提供している Docker イメージのレシピを見てみよう (<a href="https://github.com/andatoshiki/toshiki-notebookblob/main/docker/Dockerfile" target="_blank" rel="noreferrer">docker/Dockerfile</a>)</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#CB4B16;">FROM</span><span style="color:#839496;"> node:</span><span style="color:#D33682;">12</span></span>
<span class="line"><span style="color:#CB4B16;">LABEL</span><span style="color:#839496;"> maintainer</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;Tomoyuki Mano&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#CB4B16;">RUN</span><span style="color:#839496;"> apt</span><span style="color:#859900;">-</span><span style="color:#839496;">get update </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#839496;"> apt</span><span style="color:#859900;">-</span><span style="color:#839496;">get install nano</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#CB4B16;">RUN</span><span style="color:#839496;"> cd </span><span style="color:#859900;">/</span><span style="color:#839496;">opt </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#839496;"> curl </span><span style="color:#859900;">-</span><span style="color:#839496;">q </span><span style="color:#2AA198;">&quot;https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz&quot;</span><span style="color:#839496;"> </span><span style="color:#859900;">-</span><span style="color:#839496;">o Python</span><span style="color:#859900;">-</span><span style="color:#D33682;">3.7</span><span style="color:#839496;">.6.tgz </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#839496;"> tar </span><span style="color:#859900;">-</span><span style="color:#839496;">xzf Python</span><span style="color:#859900;">-</span><span style="color:#D33682;">3.7</span><span style="color:#839496;">.6.tgz </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#839496;"> cd Python</span><span style="color:#859900;">-</span><span style="color:#D33682;">3.7</span><span style="color:#839496;">.6 </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#839496;"> .</span><span style="color:#859900;">/</span><span style="color:#839496;">configure </span><span style="color:#DC322F;">--</span><span style="color:#839496;">enable</span><span style="color:#859900;">-</span><span style="color:#839496;">optimizations </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#839496;"> make install</span></span>
<span class="line"></span>
<span class="line"><span style="color:#CB4B16;">RUN</span><span style="color:#839496;"> cd </span><span style="color:#859900;">/</span><span style="color:#839496;">opt </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#839496;"> curl </span><span style="color:#2AA198;">&quot;https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip&quot;</span><span style="color:#839496;"> </span><span style="color:#859900;">-</span><span style="color:#839496;">o </span><span style="color:#2AA198;">&quot;awscliv2.zip&quot;</span><span style="color:#839496;"> </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#839496;"> unzip awscliv2.zip </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#839496;"> .</span><span style="color:#859900;">/</span><span style="color:#839496;">aws</span><span style="color:#859900;">/</span><span style="color:#839496;">install</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#CB4B16;">RUN</span><span style="color:#839496;"> npm install </span><span style="color:#859900;">-</span><span style="color:#839496;">g aws</span><span style="color:#859900;">-</span><span style="color:#839496;">cdk</span><span style="color:#859900;">@</span><span style="color:#D33682;">1.100</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># clean up unnecessary files</span></span>
<span class="line"><span style="color:#CB4B16;">RUN</span><span style="color:#839496;"> rm </span><span style="color:#859900;">-</span><span style="color:#839496;">rf </span><span style="color:#859900;">/</span><span style="color:#839496;">opt</span><span style="color:#859900;">/*</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># copy hands-on source code in /root/</span></span>
<span class="line"><span style="color:#CB4B16;">COPY</span><span style="color:#839496;"> handson</span><span style="color:#859900;">/</span><span style="color:#839496;"> </span><span style="color:#859900;">/</span><span style="color:#839496;">root</span><span style="color:#859900;">/</span><span style="color:#839496;">handson</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#CB4B16;">FROM</span><span style="color:#657B83;"> node:</span><span style="color:#D33682;">12</span></span>
<span class="line"><span style="color:#CB4B16;">LABEL</span><span style="color:#657B83;"> maintainer</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;Tomoyuki Mano&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#CB4B16;">RUN</span><span style="color:#657B83;"> apt</span><span style="color:#859900;">-</span><span style="color:#657B83;">get update </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#657B83;"> apt</span><span style="color:#859900;">-</span><span style="color:#657B83;">get install nano</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#CB4B16;">RUN</span><span style="color:#657B83;"> cd </span><span style="color:#859900;">/</span><span style="color:#657B83;">opt </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#657B83;"> curl </span><span style="color:#859900;">-</span><span style="color:#657B83;">q </span><span style="color:#2AA198;">&quot;https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz&quot;</span><span style="color:#657B83;"> </span><span style="color:#859900;">-</span><span style="color:#657B83;">o Python</span><span style="color:#859900;">-</span><span style="color:#D33682;">3.7</span><span style="color:#657B83;">.6.tgz </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#657B83;"> tar </span><span style="color:#859900;">-</span><span style="color:#657B83;">xzf Python</span><span style="color:#859900;">-</span><span style="color:#D33682;">3.7</span><span style="color:#657B83;">.6.tgz </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#657B83;"> cd Python</span><span style="color:#859900;">-</span><span style="color:#D33682;">3.7</span><span style="color:#657B83;">.6 </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#657B83;"> .</span><span style="color:#859900;">/</span><span style="color:#657B83;">configure </span><span style="color:#DC322F;">--</span><span style="color:#657B83;">enable</span><span style="color:#859900;">-</span><span style="color:#657B83;">optimizations </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#657B83;"> make install</span></span>
<span class="line"></span>
<span class="line"><span style="color:#CB4B16;">RUN</span><span style="color:#657B83;"> cd </span><span style="color:#859900;">/</span><span style="color:#657B83;">opt </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#657B83;"> curl </span><span style="color:#2AA198;">&quot;https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip&quot;</span><span style="color:#657B83;"> </span><span style="color:#859900;">-</span><span style="color:#657B83;">o </span><span style="color:#2AA198;">&quot;awscliv2.zip&quot;</span><span style="color:#657B83;"> </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#657B83;"> unzip awscliv2.zip </span><span style="color:#DC322F;">\\</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#DC322F;">&amp;&amp;</span><span style="color:#657B83;"> .</span><span style="color:#859900;">/</span><span style="color:#657B83;">aws</span><span style="color:#859900;">/</span><span style="color:#657B83;">install</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#CB4B16;">RUN</span><span style="color:#657B83;"> npm install </span><span style="color:#859900;">-</span><span style="color:#657B83;">g aws</span><span style="color:#859900;">-</span><span style="color:#657B83;">cdk</span><span style="color:#859900;">@</span><span style="color:#D33682;">1.100</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># clean up unnecessary files</span></span>
<span class="line"><span style="color:#CB4B16;">RUN</span><span style="color:#657B83;"> rm </span><span style="color:#859900;">-</span><span style="color:#657B83;">rf </span><span style="color:#859900;">/</span><span style="color:#657B83;">opt</span><span style="color:#859900;">/*</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># copy hands-on source code in /root/</span></span>
<span class="line"><span style="color:#CB4B16;">COPY</span><span style="color:#657B83;"> handson</span><span style="color:#859900;">/</span><span style="color:#657B83;"> </span><span style="color:#859900;">/</span><span style="color:#657B83;">root</span><span style="color:#859900;">/</span><span style="color:#657B83;">handson</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br></div></div><p><code>Dockerfile</code> の中身の説明は詳しくは行わないが,たとえば上のコードで &lt;1&gt; で示したところは, Python 3.7 のインストールを実行している. また, &lt;2&gt; で示したところは, AWS CDK のインストールを行っていることがわかるだろう. このように,リアルな OS で行うのと同じ流れでインストールのコマンドを逐一記述していくことで,自分だけの Docker イメージを作成することができる. 一度イメージを作成すれば,それを配布することで,他者も同一の計算環境を簡単に再構成することができる.</p><p>&quot;ぼくの環境ではそのプログラム走ったのにな…&quot; というのは,プログラミング初心者ではよく耳にする会話だが, Docker を使いこなせばそのような心配とは無縁である. そのような意味で,クラウド以外の場面でも, Docker の有用性・汎用性は極めて高い.</p><p>コンテナを用いた仮想計算環境ツールとして Docker を紹介したが, ほかに選択肢はないのか? よくぞ聞いてくれた! Docker の登場以降,複数のコンテナベースの仮想環境ツールが開発されてきた. いずれのツールも,概念や API については Docker と共通するものが多いがDocker にはない独自の特徴を提供している. ここではその中でも有名ないくつかを紹介しよう.</p><p><a href="https://github.com/hpcng/singularity" target="_blank" rel="noreferrer">Singularity</a> は科学計算や HPC (High Performance Computing) の分野で人気の高いコンテナプラットフォームである. Singularity では大学・研究機関の HPC クラスターでの運用に適したような設計が施されている. たとえば, Docker は基本的には root 権限で実行されるのに対し, Singularity はユーザー権限 (コマンドを実行したユーザー自身) でプログラムが実行される. root 権限での実行は Web サーバーのように個人・企業がある特定のサービスのために運用するサーバーでは問題ないが,多数のユーザーが多様な目的で計算を実行する HPC クラスターでは問題となる. またSingularity は独自のイメージの作成方法・エコシステムをもっているが, Docker イメージを Singularity のイメージに変換し実行する機能も有している.</p><p><a href="https://github.com/containers/podman" target="_blank" rel="noreferrer">podman</a> は Red Hat 社によって開発されたもう一つのコンテナプラットフォームである. podman は基本的に Docker と同一のコマンドを採用しているが,実装は Red Hat によってスクラッチから行われた. podman では, Singularity と同様にユーザー権限でのプログラムの実行を可能であり,クラウドおよび HPC の両方の環境に対応するコンテナプラットフォームを目指して作られた. また,その名前にあるとおり pod とよばれる独自の概念が導入されている.</p><p>著者の個人的な意見としては,現時点では Docker をマスターしておけば当面は困ることはないと考えるが,興味のある読者はぜひこれらのツールも試してみてはいかがだろうか?</p><h2 id="elastic-container-service-ecs" tabindex="-1">Elastic Container Service (ECS) <a class="header-anchor" href="#elastic-container-service-ecs" aria-label="Permalink to &quot;Elastic Container Service (ECS)&quot;"></a></h2><p><img src="`+Y+'" alt="ECS のアイコン"></p><p>ここまでに説明してきたように, Docker を使うことで仮想計算環境を簡単に複製・起動することが可能になる. 本章の最後の話題として, AWS 上で Docker を使った計算システムを構築する方法を解説しよう.</p><p><strong>Elastic Container Service (ECS)</strong> とは, Docker を使った計算機クラスターを AWS 上に作成するためのツールである (<a href="#fig:logo_ecs">figure_title</a>) ECS を使用することで, Docker にパッケージされたアプリケーションを計算機クラスターに投入したり,計算機クラスターのインスタンスを追加・削除する操作 (=スケーリング) を行うことができる.</p><p>ECS の概要を示したのが <a href="#ecs_overview">figure_title</a> である. ECS は,<strong>タスク (Task)</strong> と呼ばれる単位で管理された計算ジョブを受け付ける. システムにタスクが投入されるとECS は最初にタスクで指定された Docker イメージを外部レジストリからダウンロードしてくる. 外部レジストリとしては, Docker Hub や AWS 独自の Docker レジストリである <strong>ECR (Elastic Container Registry)</strong> を指定することができる.</p><p>ECS の次の重要な役割はタスクの配置である. あらかじめ定義されたクラスター内で,計算負荷が小さい仮想インスタンスを選び出し,そこに Docker イメージを配置することで指定された計算タスクが開始される. &quot;計算負荷が小さい仮想インスタンスを選び出す&quot; と言ったが,具体的にどのような戦略・ポリシーでこの選択を行うかは,ユーザーの指定したパラメータに従う.</p><p>また,クラスターのスケーリングも ECS における重要な概念である. スケーリングとは,クラスター内のインスタンスの計算負荷をモニタリングし,計算負荷に応じてインスタンスの起動・停止を行う操作を指す. クラスター全体の計算負荷が指定された閾値 (たとえば 80%の稼働率) を超えていた場合,新たな仮想インスタンスをクラスター内に立ち上げる操作を scale-out (スケールアウト) とよび, 負荷が減った場合に不要なインスタンスを停止する操作を scale-in (スケールイン) とよぶ. クラスターのスケーリングは, ECS がほかの AWS のサービスと連携することで実現される. 具体的には, EC2 の <strong>Auto scaling group (ASG)</strong> や <strong>Fargate</strong> の2つの選択肢が多くの場合選択される. <strong>ASG</strong> については <a href="#sec_aws_batch">Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する</a>, Fargate については <a href="#sec_fargate_qabot">Hands-on #3: AWS で自動質問回答ボットを走らせる</a> でより詳細に解説する.</p><p>これら一連のタスクの管理を, ECS は自動でやってくれる. クラスターのスケーリングやタスクの配置に関してのパラメータを一度指定してしまえば,ユーザーは (ほとんどなにも考えずに) 大量のタスクを投入することができる. クラスターのスケーリングによってタスクの量にちょうど十分なだけのインスタンスが起動し,タスクが完了した後は不要なインスタンスはすべて停止される.</p><p>さて,ここまで説明的な話が続いてしまったが,次章からは早速 Docker と AWS を使って大規模な並列計算システムを構築していこう!</p><p><img src="'+J+'" alt="ECS の概要"></p><h1 id="hands-on-3-aws-で自動質問回答ボットを走らせる" tabindex="-1">Hands-on #3: AWS で自動質問回答ボットを走らせる <a class="header-anchor" href="#hands-on-3-aws-で自動質問回答ボットを走らせる" aria-label="Permalink to &quot;Hands-on \\#3: AWS で自動質問回答ボットを走らせる&quot;"></a></h1><p>ハンズオン第三回では, Docker と ECS を駆使した機械学習アプリケーションを実装しよう. 具体的には,深層学習による自然言語処理を行うことで,クライアントから与えられた文章題に対して回答を生成する,自動 Question &amp; Answering ボットを作成しよう. ECS を利用することで,ジョブの数によって動的にインスタンスの数を制御し,並列にタスクを実行するようなシステムを構築しよう.</p><p>通常の機械学習のワークフローでは,モデルの訓練 ⇒ 推論 (データへの適用) が基本的な流れである. しかしながら, GPU 搭載型の EC2 クラスターを使ったモデルの訓練はやや難易度が高いため,次章 (<a href="#sec_aws_batch">Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する</a>) で取り扱う. 本章は,クラウド上でのクラスターの構築・タスクの管理などの概念に慣れるため,よりシンプルな実装で実現できる Fargate クラスターを用いた推論計算の並列化を紹介する.</p><h2 id="fargate" tabindex="-1">Fargate <a class="header-anchor" href="#fargate" aria-label="Permalink to &quot;Fargate&quot;"></a></h2><p>ハンズオンに入っていく前に, <strong>Fargate</strong> という AWS の機能を知っておく必要がある (<a href="#fig:fargate_logo">figure_title</a>)</p><p><img src="'+Q+`" alt="Fargate のアイコン"></p><p>ECS の概要を示した <a href="#ecs_overview">figure_title</a> をもう一度見てみよう. この図で, ECS の管理下にあるクラスターが示されているが,このクラスターの中で計算を行う実体としては二つの選択肢がある. <strong>EC2 あるいは Fargate</strong> のいずれかである. EC2 を用いた場合は,先の章 (<a href="#sec_first_ec2">Hands-on #1: 初めての EC2 インスタンスを起動する</a>, <a href="#sec_jupyter_and_deep_learning">Hands-on #2: AWS でディープラーニングを実践</a>) で説明したような流れでインスタンスが起動し,計算が実行される. しかし, EC2 を用いた計算機クラスターの作成・管理は技術的な難易度がやや高いので,次章 (<a href="#sec_aws_batch">Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する</a>) で説明することにする.</p><p>Fargate とは, <strong>ECS での利用に特化</strong>して設計された,<strong>コンテナを使用した計算タスク</strong>を走らせるための仕組みである. 計算を走らせるという点では EC2 と役割は似ているが, Fargate は EC2 インスタンスのような物理的実体はもたない. 物理的実体をもたないというのは,たとえば SSH でログインすることは基本的に想定されていないし,なにかのソフトウェアをインストールしたりなどの概念も存在しない. Fargate ではすべての計算は Docker コンテナを介して行われる. すなわち, Fargate を利用するには,ユーザーは最初に所望の Docker イメージを指定しておき, Fargate は <code>docker run</code> のコマンドを使用することで計算タスクを実行する. Fargate を用いる利点は, Fargate を ECS のクラスターに指定すると,スケーリングなどの操作が簡単な設定・プログラムで構築できる点である.</p><p>Fargate では, EC2 と同様に CPU とメモリーのサイズを必要な分だけ指定できる. 執筆時点では, CPU は 0.25 - 4 コア, RAM は 0.5 - 30 GB の間で選択することができる (詳しくは <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html" target="_blank" rel="noreferrer">公式ドキュメンテーション &quot;Amazon ECS on AWS Fargate&quot;</a> 参照) クラスターのスケーリングが容易な分, Fargate では EC2 ほど大きな CPU コア・ RAM 容量を単一インスタンスに付与することができず,また GPU を利用することもできない.</p><p>以上が Fargate の概要であったが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは実際に手を動かしながら, ECS と Fargate を使った並列タスクの処理の仕方を学んでいこう.</p><p>厳密には, ECS に付与するクラスターには EC2 と Fargate のハイブリッドを使用することも可能である.</p><h2 id="準備-2" tabindex="-1">準備 <a class="header-anchor" href="#準備-2" aria-label="Permalink to &quot;準備&quot;"></a></h2><p>ハンズオンのソースコードは GitHub の <a href="https://github.com/andatoshiki/toshiki-notebooktree/main/handson/qa-bot" target="_blank" rel="noreferrer">handson/qa-bot</a> にある.</p><p>本ハンズオンの実行には,第一回ハンズオンで説明した準備 (<a href="#handson_01_prep">準備</a>) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.</p><p>このハンズオンでは 1CPU/4GB RAM の Fargate インスタンスを使用する. 計算の実行には 0.025 $/hour のコストが発生することに注意.</p><h2 id="transformer-を用いた-question-answering-プログラム" tabindex="-1">Transformer を用いた question-answering プログラム <a class="header-anchor" href="#transformer-を用いた-question-answering-プログラム" aria-label="Permalink to &quot;Transformer を用いた question-answering プログラム&quot;"></a></h2><p>このハンズオンで開発する,自動質問回答システムをより具体的に定義しよう. 次のような文脈 (context) と質問 (question) が与えられた状況を想定する.</p><div class="language-txt vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">txt</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">context: Albert Einstein (14 March 1879 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his massenergy equivalence formula E = mc2, which has been dubbed \\&quot;the world&#39;s most famous equation\\&quot;. He received the 1921 Nobel Prize in Physics \\&quot;for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\\&quot;, a pivotal step in the development of quantum theory.</span></span>
<span class="line"><span style="color:#839496;"></span></span>
<span class="line"><span style="color:#839496;">question: In what year did Einstein win the Nobel prize?</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">context: Albert Einstein (14 March 1879 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his massenergy equivalence formula E = mc2, which has been dubbed \\&quot;the world&#39;s most famous equation\\&quot;. He received the 1921 Nobel Prize in Physics \\&quot;for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\\&quot;, a pivotal step in the development of quantum theory.</span></span>
<span class="line"><span style="color:#657B83;"></span></span>
<span class="line"><span style="color:#657B83;">question: In what year did Einstein win the Nobel prize?</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>今回作成する自動回答システムは,このような問題に対して, context に含まれる文字列から正解となる言葉を見つけ出すものとする. 上の問題では,次のような回答を返すべきである.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">answer:</span><span style="color:#839496;"> </span><span style="color:#D33682;">1921</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">answer:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">1921</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>人間にとっては,このような文章を理解することは容易であるが,コンピュータにそれを解かせるのは難しいことは容易に想像ができるだろう. しかし,近年の深層学習を使った自然言語処理の進歩は著しく,上で示したような例題などは極めて高い正答率で回答できるモデルを作ることができる.</p><p>今回は, <a href="https://github.com/huggingface/transformers" target="_blank" rel="noreferrer">huggingface/transformers</a> で公開されている学習済みの言語モデルを利用することで,上で定義した問題を解く Q&amp;A ボットを作る. この Q&amp;A ボットは <a href="https://en.wikipedia.org/wiki/Transformer_(machine_learning_model)" target="_blank" rel="noreferrer">Transformer</a> とよばれるモデルを使った自然言語処理に支えられえている (<a href="#transformer_architecture">figure_title</a>) このプログラムを, Docker にパッケージしたものが <a href="https://hub.docker.com/repository/docker/tomomano/qabot" target="_blank" rel="noreferrer">著者の Docker Hub リポジトリ</a> に用意してある. クラウドの設計に入る前に,まずはこのプログラムを単体で動かしてみよう.</p><p><img src="`+Z+'" alt="Transformer モデルアーキテクチャ (画像出典: Vaswani+ 2017)"></p><p>なお,今回は学習済みのモデルを用いているので,私達が行うのは与えられた入力をモデルに投入して予測を行う (推論) のみである. 推論の演算は, CPU だけでも十分高速に行うことができるので,コストの削減と,実装をシンプルにする目的で,このハンズオンでは GPU は利用しない. 一般的に, ニューラルネットは学習のほうが圧倒的に計算コストが大きく,そのような場合に GPU はより威力を発揮する.</p><p>次のコマンドで,今回使う Docker image を ローカルにダウンロード (pull) してこよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pull</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tomomano/qabot:latest</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pull</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tomomano/qabot:latest</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>pull できたら,早速この Docker に質問を投げかけてみよう. まずは context と question をコマンドラインの変数として定義する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">context=&quot;Albert Einstein (14 March 1879 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his massenergy equivalence formula E = mc2, which has been dubbed the world&#39;s most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory.&quot;</span></span>\n<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">question=&quot;In what year did Einstein win the Nobel prize ?&quot;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">context=&quot;Albert Einstein (14 March 1879 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his massenergy equivalence formula E = mc2, which has been dubbed the world&#39;s most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory.&quot;</span></span>\n<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">question=&quot;In what year did Einstein win the Nobel prize ?&quot;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>そうしたら,次のコマンドによってコンテナを実行する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tomomano/qabot</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">${</span><span style="color:#268BD2;">context</span><span style="color:#859900;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">${</span><span style="color:#268BD2;">question</span><span style="color:#859900;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;"> </span><span style="color:#2AA198;">foo</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--no_save</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tomomano/qabot</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">${</span><span style="color:#268BD2;">context</span><span style="color:#859900;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">${</span><span style="color:#268BD2;">question</span><span style="color:#859900;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">foo</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--no_save</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>今回用意した Docker image は,第一引数に context となる文字列を,第二引数に question に相当する文字列を受けつける. 第三引数,第四引数については,クラウドに展開するときの実装上の都合なので,いまは気にしなくてよい.</p><p>このコマンドを実行すると,次のような出力が得られるはずである.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">{</span><span style="color:#268BD2;">&#39;score&#39;</span><span style="color:#268BD2;">:</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.9881729286683587</span><span style="color:#2AA198;">,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&#39;start&#39;:</span><span style="color:#839496;"> </span><span style="color:#D33682;">437</span><span style="color:#2AA198;">,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&#39;end&#39;:</span><span style="color:#839496;"> </span><span style="color:#D33682;">441</span><span style="color:#2AA198;">,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&#39;answer&#39;:</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&#39;1921&#39;}</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">{</span><span style="color:#268BD2;">&#39;score&#39;</span><span style="color:#268BD2;">:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.9881729286683587</span><span style="color:#2AA198;">,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&#39;start&#39;:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">437</span><span style="color:#2AA198;">,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&#39;end&#39;:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">441</span><span style="color:#2AA198;">,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&#39;answer&#39;:</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&#39;1921&#39;}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>&quot;score&quot; は正解の自信度を表す数字で, [0,1] の範囲で与えられる. &quot;start&quot;, &quot;end&quot; は, context 中の何文字目が正解に相当するかを示しており, &quot;answer&quot; が正解と予測された文字列である. 1921 年という,正しい答えが返ってきていることに注目してほしい.</p><p>もう少し難しい質問を投げかけてみよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">question=&quot;Why did Einstein win the Nobel prize ?&quot;</span></span>\n<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tomomano/qabot</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">${</span><span style="color:#268BD2;">context</span><span style="color:#859900;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">${</span><span style="color:#268BD2;">question</span><span style="color:#859900;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;"> </span><span style="color:#2AA198;">foo</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--no_save</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">question=&quot;Why did Einstein win the Nobel prize ?&quot;</span></span>\n<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tomomano/qabot</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">${</span><span style="color:#268BD2;">context</span><span style="color:#859900;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">${</span><span style="color:#268BD2;">question</span><span style="color:#859900;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">foo</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--no_save</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>出力:</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">{</span><span style="color:#268BD2;">&#39;score&#39;</span><span style="color:#268BD2;">:</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.5235594527494207</span><span style="color:#2AA198;">,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&#39;start&#39;:</span><span style="color:#839496;"> </span><span style="color:#D33682;">470</span><span style="color:#2AA198;">,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&#39;end&#39;:</span><span style="color:#839496;"> </span><span style="color:#D33682;">506</span><span style="color:#2AA198;">,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&#39;answer&#39;:</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&#39;his services to theoretical physics,&#39;}</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">{</span><span style="color:#268BD2;">&#39;score&#39;</span><span style="color:#268BD2;">:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.5235594527494207</span><span style="color:#2AA198;">,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&#39;start&#39;:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">470</span><span style="color:#2AA198;">,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&#39;end&#39;:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">506</span><span style="color:#2AA198;">,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&#39;answer&#39;:</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&#39;his services to theoretical physics,&#39;}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>今度は, score が 0.52 と,少し自信がないようだが,それでも正しい答えにたどりつけていることがわかる.</p><p>このように, 深層学習に支えられた言語モデルを用いることで,実用にも役に立ちそうな Q&amp;A ボットを実現できていることがわかる. 以降では,このプログラムをクラウドに展開することで,大量の質問に自動で対応できるようなシステムを設計していく.</p><p>今回使用する Question &amp; Answering システムには, DistilBERT という Transformer を基にした言語モデルが用いられている. 興味のある読者は, <a href="https://arxiv.org/abs/1910.01108" target="_blank" rel="noreferrer">原著論文</a> を参照してもらいたい. また, huggingface/transformers による DistilBert の実装のドキュメンテーションは <a href="https://huggingface.co/transformers/model_doc/distilbert.html" target="_blank" rel="noreferrer">公式ドキュメンテーション</a> を参照のこと.</p><p>今回提供する Q-A ボットの Docker のソースコードは <a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/qa-bot/docker/Dockerfile" target="_blank" rel="noreferrer">https://github.com/andatoshiki/toshiki-notebookblob/main/handson/qa-bot/docker/Dockerfile</a> にある.</p><h2 id="アプリケーションの説明-2" tabindex="-1">アプリケーションの説明 <a class="header-anchor" href="#アプリケーションの説明-2" aria-label="Permalink to &quot;アプリケーションの説明&quot;"></a></h2><p>このハンズオンで作成するアプリケーションの概要を <a href="#handson_03_architecture">figure_title</a> に示す.</p><p><img src="'+ss+`" alt="アプリケーションのアーキテクチャ"></p><p>簡単にまとめると,以下のような設計である.</p><ul><li><p>クライアントは,質問を AWS 上のアプリケーションに送信する.</p></li><li><p>質問のタスクは ECS によって処理される.</p></li><li><p>ECS は, Docker Hub から,イメージをダウンロードする.</p></li><li><p>次にECS はクラスター内に新たな Fargate インスタンスを立ち上げ,ダウンロードされた Docker イメージをこの新規インスタンスに配置する.</p><ul><li>このとき,一つの質問に対し一つの Fargate インスタンスを立ち上げることで,複数の質問を並列的に処理できるようにする.</li></ul></li><li><p>ジョブが実行される.</p></li><li><p>ジョブの実行結果 (質問への回答) は, データベース (DynamoDB) に書き込まれる.</p></li><li><p>最後に,クライアントは DynamoDB から質問への回答を読み取る.</p></li></ul><p>それでは,プログラムのソースコードを見てみよう (<a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/qa-bot/app.py" target="_blank" rel="noreferrer">handson/qa-bot/app.py</a>)</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">class</span><span style="color:#839496;"> </span><span style="color:#2AA198;">EcsClusterQaBot</span><span style="color:#839496;">(</span><span style="color:#268BD2;">core.Stack</span><span style="color:#839496;">)</span><span style="color:#2AA198;">:</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">def</span><span style="color:#839496;"> </span><span style="color:#2AA198;">__init__</span><span style="color:#839496;">(</span><span style="color:#268BD2;">self,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">scope:</span><span style="color:#839496;"> </span><span style="color:#2AA198;">core.App,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">name:</span><span style="color:#839496;"> </span><span style="color:#2AA198;">str,</span><span style="color:#839496;"> </span><span style="color:#268BD2;">**</span><span style="color:#2AA198;">kwargs</span><span style="color:#839496;">) -</span><span style="color:#859900;">&gt;</span><span style="color:#839496;"> </span><span style="color:#2AA198;">None:</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">super</span><span style="color:#839496;">().__init__(</span><span style="color:#268BD2;">scope,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">name,</span><span style="color:#839496;"> </span><span style="color:#268BD2;">**</span><span style="color:#2AA198;">kwargs</span><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># dynamoDB table to store questions and answers</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">table</span><span style="color:#839496;"> </span><span style="color:#2AA198;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">dynamodb.Table</span><span style="color:#839496;">(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;EcsClusterQaBot-Table&quot;,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">partition_key</span><span style="color:#859900;">=</span><span style="color:#2AA198;">dynamodb.Attribute</span><span style="color:#839496;">(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;item_id&quot;,</span><span style="color:#839496;"> </span><span style="color:#268BD2;">type</span><span style="color:#859900;">=</span><span style="color:#2AA198;">dynamodb.AttributeType.STRING</span></span>
<span class="line"><span style="color:#839496;"> )</span><span style="color:#2AA198;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">billing_mode</span><span style="color:#859900;">=</span><span style="color:#2AA198;">dynamodb.BillingMode.PAY_PER_REQUEST,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">removal_policy</span><span style="color:#859900;">=</span><span style="color:#2AA198;">core.RemovalPolicy.DESTROY</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">vpc</span><span style="color:#839496;"> </span><span style="color:#2AA198;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ec2.Vpc</span><span style="color:#839496;">(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;EcsClusterQaBot-Vpc&quot;,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">max_azs</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#2AA198;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">cluster</span><span style="color:#839496;"> </span><span style="color:#2AA198;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ecs.Cluster</span><span style="color:#839496;">(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;EcsClusterQaBot-Cluster&quot;,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">vpc</span><span style="color:#859900;">=</span><span style="color:#2AA198;">vpc,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">taskdef</span><span style="color:#839496;"> </span><span style="color:#2AA198;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ecs.FargateTaskDefinition</span><span style="color:#839496;">(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;EcsClusterQaBot-TaskDef&quot;,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">cpu</span><span style="color:#859900;">=</span><span style="color:#D33682;">1024</span><span style="color:#2AA198;">,</span><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># 1 CPU</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">memory_limit_mib</span><span style="color:#859900;">=</span><span style="color:#D33682;">4096</span><span style="color:#2AA198;">,</span><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># 4GB RAM</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># grant permissions</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">table.grant_read_write_data(taskdef.task_role</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">taskdef.add_to_task_role_policy(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">iam.PolicyStatement(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">effect</span><span style="color:#859900;">=</span><span style="color:#2AA198;">iam.Effect.ALLOW,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">resources</span><span style="color:#859900;">=</span><span style="color:#2AA198;">[&quot;*&quot;],</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">actions</span><span style="color:#859900;">=</span><span style="color:#2AA198;">[&quot;ssm:GetParameter&quot;]</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">container</span><span style="color:#839496;"> </span><span style="color:#2AA198;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">taskdef.add_container</span><span style="color:#839496;">(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">&quot;EcsClusterQaBot-Container&quot;</span><span style="color:#268BD2;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">image</span><span style="color:#859900;">=</span><span style="color:#2AA198;">ecs.ContainerImage.from_registry</span><span style="color:#839496;">(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">&quot;tomomano/qabot:latest&quot;</span></span>
<span class="line"><span style="color:#839496;"> )</span><span style="color:#2AA198;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">class</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">EcsClusterQaBot</span><span style="color:#657B83;">(</span><span style="color:#268BD2;">core.Stack</span><span style="color:#657B83;">)</span><span style="color:#2AA198;">:</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">def</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">__init__</span><span style="color:#657B83;">(</span><span style="color:#268BD2;">self,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">scope:</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">core.App,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">name:</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">str,</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">**</span><span style="color:#2AA198;">kwargs</span><span style="color:#657B83;">) -</span><span style="color:#859900;">&gt;</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">None:</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">super</span><span style="color:#657B83;">().__init__(</span><span style="color:#268BD2;">scope,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">name,</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">**</span><span style="color:#2AA198;">kwargs</span><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># dynamoDB table to store questions and answers</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">table</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">dynamodb.Table</span><span style="color:#657B83;">(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;EcsClusterQaBot-Table&quot;,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">partition_key</span><span style="color:#859900;">=</span><span style="color:#2AA198;">dynamodb.Attribute</span><span style="color:#657B83;">(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;item_id&quot;,</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">type</span><span style="color:#859900;">=</span><span style="color:#2AA198;">dynamodb.AttributeType.STRING</span></span>
<span class="line"><span style="color:#657B83;"> )</span><span style="color:#2AA198;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">billing_mode</span><span style="color:#859900;">=</span><span style="color:#2AA198;">dynamodb.BillingMode.PAY_PER_REQUEST,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">removal_policy</span><span style="color:#859900;">=</span><span style="color:#2AA198;">core.RemovalPolicy.DESTROY</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">vpc</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ec2.Vpc</span><span style="color:#657B83;">(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;EcsClusterQaBot-Vpc&quot;,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">max_azs</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#2AA198;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">cluster</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ecs.Cluster</span><span style="color:#657B83;">(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;EcsClusterQaBot-Cluster&quot;,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">vpc</span><span style="color:#859900;">=</span><span style="color:#2AA198;">vpc,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">taskdef</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ecs.FargateTaskDefinition</span><span style="color:#657B83;">(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;EcsClusterQaBot-TaskDef&quot;,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">cpu</span><span style="color:#859900;">=</span><span style="color:#D33682;">1024</span><span style="color:#2AA198;">,</span><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># 1 CPU</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">memory_limit_mib</span><span style="color:#859900;">=</span><span style="color:#D33682;">4096</span><span style="color:#2AA198;">,</span><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># 4GB RAM</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># grant permissions</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">table.grant_read_write_data(taskdef.task_role</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">taskdef.add_to_task_role_policy(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">iam.PolicyStatement(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">effect</span><span style="color:#859900;">=</span><span style="color:#2AA198;">iam.Effect.ALLOW,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">resources</span><span style="color:#859900;">=</span><span style="color:#2AA198;">[&quot;*&quot;],</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">actions</span><span style="color:#859900;">=</span><span style="color:#2AA198;">[&quot;ssm:GetParameter&quot;]</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">container</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">taskdef.add_container</span><span style="color:#657B83;">(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">&quot;EcsClusterQaBot-Container&quot;</span><span style="color:#268BD2;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">image</span><span style="color:#859900;">=</span><span style="color:#2AA198;">ecs.ContainerImage.from_registry</span><span style="color:#657B83;">(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">&quot;tomomano/qabot:latest&quot;</span></span>
<span class="line"><span style="color:#657B83;"> )</span><span style="color:#2AA198;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br></div></div><ul><li><p>ここでは,回答の結果を書き込むためのデータベースを用意している. DynamoDB については,サーバーレスアーキテクチャの章で扱うので,今は気にしなくてよい.</p></li><li><p>ここでは,ハンズオン #1, #2 で行ったのと同様に, VPC を定義している.</p></li><li><p>ここで, ECS のクラスター (cluster) を定義している. クラスターとは,仮想サーバーのプールのことであり,クラスターの中に複数の仮想インスタンスを配置する.</p></li><li><p>ここで,実行するタスクを定義している (task definition)</p></li><li><p>ここで, タスクの実行で使用する Docker イメージを定義している.</p></li></ul><h3 id="ecs-と-fargate" tabindex="-1">ECS と Fargate <a class="header-anchor" href="#ecs-と-fargate" aria-label="Permalink to &quot;ECS と Fargate&quot;"></a></h3><p>ECS と Fargate の部分について,コードをくわしく見てみよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">cluster</span><span style="color:#839496;"> </span><span style="color:#2AA198;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ecs.Cluster</span><span style="color:#839496;">(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;EcsClusterQaBot-Cluster&quot;,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">vpc</span><span style="color:#859900;">=</span><span style="color:#2AA198;">vpc,</span></span>
<span class="line"><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">taskdef</span><span style="color:#839496;"> </span><span style="color:#2AA198;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ecs.FargateTaskDefinition</span><span style="color:#839496;">(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self,</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;EcsClusterQaBot-TaskDef&quot;,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">cpu</span><span style="color:#859900;">=</span><span style="color:#D33682;">1024</span><span style="color:#2AA198;">,</span><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># 1 CPU</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">memory_limit_mib</span><span style="color:#859900;">=</span><span style="color:#D33682;">4096</span><span style="color:#2AA198;">,</span><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># 4GB RAM</span></span>
<span class="line"><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">container</span><span style="color:#839496;"> </span><span style="color:#2AA198;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">taskdef.add_container</span><span style="color:#839496;">(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">&quot;EcsClusterQaBot-Container&quot;</span><span style="color:#268BD2;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">image</span><span style="color:#859900;">=</span><span style="color:#2AA198;">ecs.ContainerImage.from_registry</span><span style="color:#839496;">(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">&quot;tomomano/qabot:latest&quot;</span></span>
<span class="line"><span style="color:#839496;"> )</span><span style="color:#2AA198;">,</span></span>
<span class="line"><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">cluster</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ecs.Cluster</span><span style="color:#657B83;">(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;EcsClusterQaBot-Cluster&quot;,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">vpc</span><span style="color:#859900;">=</span><span style="color:#2AA198;">vpc,</span></span>
<span class="line"><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">taskdef</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ecs.FargateTaskDefinition</span><span style="color:#657B83;">(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self,</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;EcsClusterQaBot-TaskDef&quot;,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">cpu</span><span style="color:#859900;">=</span><span style="color:#D33682;">1024</span><span style="color:#2AA198;">,</span><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># 1 CPU</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">memory_limit_mib</span><span style="color:#859900;">=</span><span style="color:#D33682;">4096</span><span style="color:#2AA198;">,</span><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># 4GB RAM</span></span>
<span class="line"><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">container</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">taskdef.add_container</span><span style="color:#657B83;">(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">&quot;EcsClusterQaBot-Container&quot;</span><span style="color:#268BD2;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">image</span><span style="color:#859900;">=</span><span style="color:#2AA198;">ecs.ContainerImage.from_registry</span><span style="color:#657B83;">(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">&quot;tomomano/qabot:latest&quot;</span></span>
<span class="line"><span style="color:#657B83;"> )</span><span style="color:#2AA198;">,</span></span>
<span class="line"><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><p><code>cluster =</code> の箇所で,空の ECS クラスターを定義している.</p><p>次に, <code>taskdef=ecs.FargateTaskDefinition</code> の箇所で, Fargate インスタンスを使ったタスクを定義しており,とくにここでは 1 CPU, 4GB RAM というマシンスペックを指定している. また,このようにして定義されたタスクは,デフォルトで 1 タスクにつき 1 インスタンスが使用される.</p><p>最後に, <code>container =</code> の箇所で,タスクの実行で使用する Docker image を定義している. ここでは, Docker Hub に置いてある image をダウンロードしてくるよう指定している.</p><p>このようにわずか数行のコードであるが,これだけで前述したような,タスクのスケジューリングなどが自動で実行される.</p><p>このコードで <code>cpu=1024</code> と指定されているのに注目してほしい. これは CPU ユニットと呼ばれる数で, 以下の換算表に従って仮想 CPU (virtual CPU; vCPU) が割り当てられる. 1024 が 1 CPU に相当する. 0.25 や 0.5 vCPU などの数字は,それぞれ実効的に 1/4, 1/2 の CPU 時間が割り当てられることを意味する. また, CPU ユニットによって使用できるメモリー量も変わってくる. たとえば, 1024 CPU ユニットを選択した場合は, 2 から 8 GB の範囲でのみメモリー量を指定することができる. 最新の情報は <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html" target="_blank" rel="noreferrer">公式ドキュメンテーション &quot;Amazon ECS on AWS Fargate&quot;</a> を参照のこと.</p><table><caption>CPU ユニットと 指定可能なメモリー量の換算表</caption><colgroup><col style="width:50%;"><col style="width:50%;"></colgroup><tbody><tr class="odd"><td><p>CPU ユニット</p></td><td><p>メモリーの値</p></td></tr><tr class="even"><td><p>256 (.25 vCPU)</p></td><td><p>0.5 GB, 1 GB, 2 GB</p></td></tr><tr class="odd"><td><p>512 (.5 vCPU)</p></td><td><p>1 GB, 2 GB, 3 GB, 4 GB</p></td></tr><tr class="even"><td><p>1024 (1 vCPU)</p></td><td><p>2 GB, 3 GB, 4 GB, 5 GB, 6 GB, 7 GB, 8 GB</p></td></tr><tr class="odd"><td><p>2048 (2 vCPU)</p></td><td><p>Between 4 GB and 16 GB in 1-GB increments</p></td></tr><tr class="even"><td><p>4096 (4 vCPU)</p></td><td><p>Between 8 GB and 30 GB in 1-GB increments</p></td></tr></tbody></table><h2 id="スタックのデプロイ-1" tabindex="-1">スタックのデプロイ <a class="header-anchor" href="#スタックのデプロイ-1" aria-label="Permalink to &quot;スタックのデプロイ&quot;"></a></h2><p>スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.</p><p>デプロイの手順は,これまでのハンズオンとほとんど共通である. SSH によるログインの必要がないので,むしろ単純なくらいである. ここでは,コマンドのみ列挙する (<code>#</code> で始まる行はコメントである) それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに (<a href="#aws_cli_install">AWS CLI のインストール</a>)</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># プロジェクトのディレクトリに移動</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cd</span><span style="color:#839496;"> </span><span style="color:#2AA198;">handson/qa-bot</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># venv を作成し,依存ライブラリのインストールを行う</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python3</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#839496;"> </span><span style="color:#2AA198;">venv</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">source</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pip</span><span style="color:#839496;"> </span><span style="color:#2AA198;">install</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#839496;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># デプロイを実行</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">deploy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># プロジェクトのディレクトリに移動</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cd</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">handson/qa-bot</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># venv を作成し,依存ライブラリのインストールを行う</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python3</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">venv</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">source</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pip</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">install</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># デプロイを実行</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">deploy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>デプロイのコマンドが無事に実行されれば, <a href="#handson_03_cdk_output">figure_title</a> のような出力が得られるはずである.</p><p><img src="`+as+'" alt="CDKデプロイ実行後の出力"></p><p>AWS コンソールにログインして,デプロイされたスタックの中身を確認してみよう. コンソールからECS のページに行くと <a href="#handson_03_ecs_console">figure_title</a> のような画面が表示されるはずである. <code>EcsClusterQaBot-XXXX</code> という名前ついたクラスターを見つけよう.</p><p>Cluster というのが,先ほど説明したとおり,複数の仮想インスタンスを束ねる一つの単位である. <a href="#handson_03_ecs_console">figure_title</a> で, FARGATE という文字の下に <code>0 Running tasks</code>, <code>0 Pending tasks</code> と表示されていることを確認しよう. この時点では一つもタスクが走っていないので,数字はすべて 0 になっている.</p><p><img src="'+ns+'" alt="ECS コンソール画面"></p><p>続いて,この画面の左のメニューバーから <code>Task Definitions</code> という項目を見つけ,クリックしよう. 移動した先のページで <code>EcsClusterQaBotEcsClusterQaBotTaskDefXXXX</code> という項目が見つかるので,開く. 開いた先のページをスクロールすると <a href="#handson_03_ecs_task_definition">figure_title</a> に示したような情報が見つかるだろう. 使用する CPU ・メモリーの量や, Docker container の実行に関する設定などが,この Task Definition の画面から確認することができる.</p><p><img src="'+ls+'" alt="Task definition の確認"></p><h2 id="タスクの実行" tabindex="-1">タスクの実行 <a class="header-anchor" href="#タスクの実行" aria-label="Permalink to &quot;タスクの実行&quot;"></a></h2><p>それでは,質問をデプロイしたクラウドに提出してみよう.</p><p>ECS にタスクを投入するのはやや複雑なので,タスクの投入を簡単にするプログラム (<code>run_task.py</code>) を用意した (<a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/qa-bot/run_task.py" target="_blank" rel="noreferrer">handson/qa-bot/run_task.py</a>)</p><p>次のようなコマンドでECS クラスターに新しい質問を投入することができる.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ask</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro.&quot;</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;What is the name of the baby?&quot;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ask</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro.&quot;</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;What is the name of the baby?&quot;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p><code>run_task.py</code> を実行するには, コマンドラインで AWS の認証情報が設定されていることが前提である.</p><p>&quot;ask&quot; の引数に続き,文脈 (context) と質問 (question) を引数として渡している.</p><p>このコマンドを実行すると, &quot;Waiting for the task to finish…&quot; と出力が表示され,回答を得るまでしばらく待たされる. この間, AWS では ECS がタスクを受理し,新しい Fargate のインスタンスを起動し, Docker イメージをそのインスタンスに配置する,という一連の処理がなされている. AWS コンソールから,この一連の様子をモニタリングしてみよう.</p><p>先ほどの ECS コンソール画面にもどり,クラスターの名前をクリックすることで,クラスターの詳細画面を開く. 次に, &quot;Tasks&quot; という名前のタブがあるので,それを開く (<a href="#ecs_task_monitoring">figure_title</a>) すると,実行中のタスクの一覧が表示されるだろう.</p><p><img src="'+ps+'" alt="ECS のタスクの実行状況をモニタリング"></p><p><a href="#ecs_task_monitoring">figure_title</a> で見て取れるように, &quot;Last status = Pending&quot; となっていることから,この時点では,タスクを実行する準備をしている段階である,ということがわかる. Fargate のインスタンスを起動し, Docker image を配置するまでおよそ 1-2 分の時間がかかる.</p><p>しばらく待つうちに, Status が &quot;RUNNING&quot; に遷移し,計算が始まる. 計算が終わると, Status は &quot;STOPPED&quot; に遷移し, ECS によって Fargate インスタンスは自動的にシャットダウンされる.</p><p><a href="#ecs_task_monitoring">figure_title</a> の画面から, &quot;Task&quot; の列にあるタスク ID クリックすることで,タスクの詳細画面を開いてみよう (<a href="#ecs_task_detail">figure_title</a>) &quot;Last status&quot;, &quot;Platform version&quot; など,タスクの情報が表示されている. また, &quot;Logs&quot; のタブを開くことで,コンテナの吐き出した実行ログを閲覧することができる.</p><p><img src="'+os+'" alt="質問タスクの実行結果"></p><p>さて, <code>run_task.py</code> を実行したコマンドラインに戻ってきてみると, <a href="#ask_question_output">figure_title</a> のような出力が得られているはずである. &quot;Momotaro&quot; という正しい回答が返ってきている!</p><p><img src="'+es+'" alt="質問タスクの実行結果"></p><h2 id="タスクの同時実行" tabindex="-1">タスクの同時実行 <a class="header-anchor" href="#タスクの同時実行" aria-label="Permalink to &quot;タスクの同時実行&quot;"></a></h2><p>さて,先ほどはたった一つの質問を投入したわけだが,今回設計したアプリケーションは, ECS と Fargate を使うことで同時にたくさんの質問を処理することができる. 実際に,たくさんの質問を一度に投入してみよう. <code>run_task.py</code> に <code>ask_many</code> というオプションを付けることで,複数の質問を一度に送信できる. 質問の内容は <a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/qa-bot/problems.json" target="_blank" rel="noreferrer">handson/qa-bot/problems.json</a> に定義されている.</p><p>次のようなコマンドを実行しよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ask_many</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ask_many</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>このコマンドを実行した後で,先ほどの ECS コンソールに行き,タスクの一覧を見てみよう (<a href="#ecs_many_tasks">figure_title</a>) 複数の Fargate インスタンスが起動され,タスクが並列に実行されているのがわかる.</p><p><img src="'+ts+'" alt="複数の質問タスクを同時に投入する"></p><p>すべてのタスクのステータスが &quot;STOPPED&quot; になったことを確認した上で,質問への回答を取得しよう. それには,次のコマンドを実行する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">list_answers</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">list_answers</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>結果として, <a href="#ask_many_output">figure_title</a> のような出力が得られるだろう. 複雑な文章問題に対し,高い正答率で回答できていることがわかるだろう.</p><p><img src="'+rs+'" alt=" の実行結果"></p><p>おめでとう! ここまでついてこれた読者はとても初歩的ながらも,深層学習による言語モデルを使って自動で質問への回答を生成するシステムを創り上げることができた! それも,数百の質問にも同時に対応できるような,とても高いスケーラビリティーをもったシステムである! 今回は GUI (Graphical User Interface) を用意することはしなかったが,このシステムに簡単な GUI を追加すればなかなか立派なウェブサービスとして運用できるだろう.</p><p><code>run_task.py</code> で質問を投入し続けると,回答を記録しているデータベースにどんどんエントリーが溜まっていく. これらのエントリーをすべて消去するには,次のコマンドを使う.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">clear</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">clear</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><h2 id="スタックの削除-1" tabindex="-1">スタックの削除 <a class="header-anchor" href="#スタックの削除-1" aria-label="Permalink to &quot;スタックの削除&quot;"></a></h2><p>これにて,今回のハンズオンは終了である. 最後にスタックを削除しよう.</p><p>スタックを削除するには,前回までと同様に, AWS コンソールにログインし CloudFormation の画面から DELETE ボタンをクリックするか,コマンドラインからコマンドを実行する. コマンドラインから行う場合は,次のコマンドを使用する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><h1 id="hands-on-4-aws-batch-を使って機械学習のハイパーパラメータサーチを並列化する" tabindex="-1">Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する <a class="header-anchor" href="#hands-on-4-aws-batch-を使って機械学習のハイパーパラメータサーチを並列化する" aria-label="Permalink to &quot;Hands-on \\#4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する&quot;"></a></h1><p>ハンズオン第三回では, ECS と Fargate を使って自動質問回答システムを構築した. シンプルながらも,複数の質問が送られた場合には並列にジョブが実行され,ユーザーに答えが返されるシステムを作ることができた. ここでは,すでに学習済みの言語モデルを用いてアプリケーションを構築した. しかし,一般的に言って,機械学習のワークフローでは自分で作ったモデルを訓練することが最初のステップにあるはずである. そこで,ハンズオン第四回では,クラウドを用いて機械学習の訓練を並列化・高速化することを考える.</p><p>本ハンズオンでは深層学習におけるハイパーパラメータ最適化を取り上げる. ハイパーパラメータとは,勾配降下法によって最適化されるニューラルネットのパラメータの外にあるパラメータのことであり,具体的にはモデルの層の幅・深さなどネットワークのアーキテクチャに関わるもの,学習率やモメンタムなどパラメータの更新則に関わるものなどが含まる. 深層学習においてハイパーパラメータの調整はとても重要なタスクである. しかしながら,ハイパーパラメータを調整するには,少しずつ条件を変えながら何度もニューラルネットを学習させる必要があり,多くの計算時間がかかる. 研究・開発においては,スループットよくたくさんのモデルの可能性を探索することが生産性を決める重要なファクターであり,ハイパーパラメータ探索を高速に解くという問題は極めて関心が高い. 本ハンズオンでは,クラウドの強力な計算リソースを利用して並列的にニューラルネットの訓練を実行することで,この問題を解く方法を学んでいこう.</p><h2 id="auto-scaling-groups-asg" tabindex="-1">Auto scaling groups (ASG) <a class="header-anchor" href="#auto-scaling-groups-asg" aria-label="Permalink to &quot;Auto scaling groups (ASG)&quot;"></a></h2><p>ハンズオンに入っていく前に, <strong>Auto scaling groups (ASG)</strong> とよばれる EC2 の概念を知っておく必要がある.</p><p>ECS の概要を示した <a href="#ecs_overview">figure_title</a> を振り返って見てほしい. 前章 (<a href="#sec_fargate_qabot">Hands-on #3: AWS で自動質問回答ボットを走らせる</a>) でも説明したが, ECS のクラスターで計算を担う実体としては EC2 と Fargate を指定することができる. Fargate については前章で記述した. Fargate を用いると,自在にスケールする計算環境をとても簡単な設定で構築することができた. しかし, GPU を利用することができないなど,いくつかの制約があった. EC2 を使用した計算環境を指定することで,プログラミングの複雑度は増すが, GPU やその他のより高度かつ複雑な設定を伴ったクラスターを構築することができる.</p><p>EC2 クラスターには <strong>ASG</strong> と呼ばれるサービスが配置される. ASG は複数の EC2 インスタンスをロジカルな単位でグループ化することでクラスターを構成する. ASG はクラスター内に新しいインスタンスを起動する,あるいは不要になったインスタンスを停止するなどのスケーリングを担う. ASG で重要な概念として, <strong>desired capacity</strong>, <strong>minimum capacity</strong>, <strong>maximum capacity</strong> というパラメータがある. minimum capacity maximum capacity は,それぞれクラスター内に配置できるインスタンスの数の最小値・最大値を指定するパラメータである. 前者は,クラスターに負荷がかかっていない場合でもアイドリング状態にあるインスタンスを維持することで,急に負荷が増大した時などのバッファーとして作用することができる. 後者は,負荷が急に増えたときに,過剰な数のインスタンスが起動する事態を防ぎ,経済的なコストの上限を定める役割を果たす.</p><p>desired capacity が,その時々でシステムが要求するインスタンスの数を指定する. desired capacity は,例えば 24 時間のリズムに合わせてインスタンスの数を増減させる (昼は多く夜は少なくなど) などの決まったスケジュールに基づいた設定を適用することができる. あるいはクラスター全体にかかっている負荷に応じて, desired capacity を動的に制御することも可能である. どのような基準でクラスターのスケーリングを行うかを定めるルールのことを,<strong>スケーリングポリシー</strong>とよぶ. たとえば,クラスター全体の稼働率 (負荷) を常に 80% に維持する,などのスケーリングポリシーが想定できる. この場合,クラスター全体の負荷が 80%を下回ったときにはクラスターからインスタンスが削除され80%を超える (あるいは超えると予測される) 場合はインスタンスを追加する,という操作が ASG によって自動的に行われる.</p><p>上記のようなパラメータを検討し,ユーザーは ASG を作成する. ASG を作成したのち, ECS との連携をプログラムしてあげることで, ECS を介して ASG による EC2 クラスターにタスクを投入することが可能になる.</p><h2 id="aws-batch" tabindex="-1">AWS Batch <a class="header-anchor" href="#aws-batch" aria-label="Permalink to &quot;AWS Batch&quot;"></a></h2><p><img src="'+cs+'" alt="AWS Batch のアイコン"></p><p>先に説明したように, ECS と ASG を組み合わせることで,所望の計算クラスターを構築することが可能である. しかしながら, ECS と ASG にはかなり込み入った設定が必要であり,初心者にとっても経験者にとってもなかなか面倒なプログラミングが要求される. そこで, ECS と ASG によるクラスターの設計を自動化してくれるサービスが提供されている. それが <strong>AWS Batch</strong> である.</p><p>AWS Batch はその名のとおりバッチ (Batch) 化されたジョブ (入力データだけが異なる独立した演算が繰り返し実行されること) を想定している. 多くの科学計算や機械学習がバッチ計算に当てはまる. たとえば,初期値のパラメータを変えて複数のシミュレーションを走らせる,といったケースだ. AWS Batch を用いることの利点は,クラスターのスケーリングやジョブの割り振りはすべて自動で実行され, ユーザーはクラウドの舞台裏の詳細を気にすることなく,大量のジョブを投入できるシステムが手に入る点である. が,知識として背後では ECS/ASG/EC2 の三つ巴が協調して動作しているという点は知っておいてほしい.</p><p>AWS Batch では,ジョブの投入・管理をスムーズに行うため,次のような概念が定義されている (<a href="#fig_batch_concept">figure_title</a>) まず, <strong>ジョブ (Job)</strong> というのがAWS Batch によって実行される一つの計算の単位である. <strong>Job definitions</strong> とはジョブの内容を定義するものであり,これには実行されるべき Docker のイメージのアドレスや,割り当てる CPU・RAM の容量,環境変数などの設定が含まれる. Job definition に基づいて個々のジョブが実行される. ジョブが実行されると,ジョブは <strong>Job queues</strong> に入る. Job queues とは,実行待ち状態にあるジョブの列のことであり,時間的に最も先頭に投入されたジョブが最初に実行される. また,複数の queue を配置し, queue ごとに priority (優先度) を設定することが可能であり, priority の高い queue に溜まったジョブが優先的に実行される (筆者はこれをディズニーランドの&quot;ファストパス&quot;を連想して捉えている) <strong>Compute environment</strong> とは,先述したクラスターとほぼ同義の概念であり,計算が実行される場所 (EC2 や Fargate からなるクラスター) を指す. Compute environment には,使用する EC2 のインスタンスタイプや同時に起動するインスタンス数の上限などの簡易なスケーリングポリシーが指定されている. Job queues は Compute environment の空き状況を監視しており, それに応じてジョブを Compute environment に投下する.</p><p>以上が AWS Batch を使用するうえで理解しておかなければならない概念であるが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは,実際に自分で手を動かしながら学んでいこう.</p><p><img src="'+is+`" alt="AWS Batch の主要な概念"></p><p><strong>EC2 or Fargate?</strong></p><p>ECS でクラスターを構成する際,計算を実行する場として EC2 と Fargate の二つの選択肢があることを説明した. それぞれ長所と短所を抱えているのだが,どのような場合にどちらを使うべきだろうか? それを検討するため,まずは <a href="#tab:ec2_vs_fargate">table_title</a> を見てみよう. これは EC2 と Fargate の特徴をまとめたものである. 説明の都合上,大幅な粗視化が行われている点は留意していただきたい.</p><table><caption>EC2 vs Fargate</caption><colgroup><col style="width:33%;"><col style="width:33%;"><col style="width:33%;"></colgroup><thead><tr class="header"><th></th><th>EC2</th><th>Fargate</th></tr></thead><tbody><tr class="odd"><td><p>Compute capacity</p></td><td><p>Medium to large</p></td><td><p>Small to medium</p></td></tr><tr class="even"><td><p>GPU</p></td><td><p>Yes</p></td><td><p>No</p></td></tr><tr class="odd"><td><p>Launch speed</p></td><td><p>Slow</p></td><td><p>Fast</p></td></tr><tr class="even"><td><p>Task placement flexibility</p></td><td><p>Low</p></td><td><p>High</p></td></tr><tr class="odd"><td><p>Programming complexity</p></td><td><p>High</p></td><td><p>Low</p></td></tr></tbody></table><p>これまでに見てきたように, EC2 は最大の CPU 数・メモリーサイズが大きかったり, GPU を利用できたりするなど,単一のインスタンスでの計算能力は高い. 対して, Fargate は単一インスタンスの最大 CPU 数は 4 コアが上限である. その一方で,インスタンスの起動に要する時間は Fargate のほうが圧倒的に早く,より俊敏にクラスターのスケーリングを行うことができる. また,タスクをクラスターに投入する際のフレキシビリティも Fargate のほうが高い. フレキシビリティというのは,例えば一つのインスタンスで 2 つ以上のコンテナを走らせる,などの状況である. 単位 CPU あたりで処理されるタスクの数を最大化する際には,このような設計がしばしば採用される. プログラミングの複雑さという観点からは, Fargate のほうが一般的にシンプルな実装になる.</p><p>このように, EC2 と Fargate は互いに相補的な特性を有しており,アプリケーションによって最適な計算環境は検討される必要がある. またEC2 と Fargate を両方用いたハイブリッドクラスターというのも定義可能であり,そのような選択肢もしばしば用いられる.</p><h2 id="準備-3" tabindex="-1">準備 <a class="header-anchor" href="#準備-3" aria-label="Permalink to &quot;準備&quot;"></a></h2><p>ハンズオンのソースコードは GitHub の <a href="https://github.com/andatoshiki/toshiki-notebooktree/main/handson/aws-batch" target="_blank" rel="noreferrer">handson/aws-batch</a> にある.</p><p>本ハンズオンの実行には,第一回ハンズオンで説明した準備 (<a href="#handson_01_prep">準備</a>) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.</p><p>このハンズオンは, <code>g4dn.xlarge</code> タイプの EC2 インスタンスを使うので,アメリカ東部 (<code>us-east-1</code>) リージョンでは 0.526 $/hour のコストが発生する. 東京 (<code>ap-northeast-1</code>) を選択した場合は 0.71 $/hour のコストが発生する.</p><p><a href="#sec:jupyter_and_deep_learning_setup">準備</a> でも注意したが,このハンズオンを始める前に G タイプインスタンスの起動上限を AWS コンソールの EC2 管理画面から確認しよう. もし上限が 0 になっていた場合は,上限緩和の申請を行う必要がある. <a href="#sec:aws_batch_code">アプリケーションの説明</a> にも関連した情報を記載しているので,併せて参照されたい.</p><h2 id="mnist-手書き文字認識-再訪" tabindex="-1">MNIST 手書き文字認識 (再訪) <a class="header-anchor" href="#mnist-手書き文字認識-再訪" aria-label="Permalink to &quot;MNIST 手書き文字認識 (再訪)&quot;"></a></h2><p>今回のハンズオンでは,機械学習のハイパーパラメータ調整を取り上げると冒頭で述べた. その最もシンプルな例題として, <a href="#sec_mnist_using_jupyter">実践ディープラーニング! MNIST 手書き数字認識タスク</a> で扱った MNIST 手書き文字認識の問題を再度取り上げよう. <a href="#sec_mnist_using_jupyter">実践ディープラーニング! MNIST 手書き数字認識タスク</a> では,適当にチョイスしたハイパーパラメータを用いてモデルの訓練を行った. ここで使用したプログラムのハイパーパラメータとしては,確率的勾配降下法 (SGD) における学習率やモメンタムが含まれる. コードでいうと,次の行が該当する.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">optimizer </span><span style="color:#859900;">=</span><span style="color:#839496;"> optim.SGD(model.parameters(), lr</span><span style="color:#859900;">=</span><span style="color:#D33682;">0.01</span><span style="color:#839496;">, momentum</span><span style="color:#859900;">=</span><span style="color:#D33682;">0.5</span><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">optimizer </span><span style="color:#859900;">=</span><span style="color:#657B83;"> optim.SGD(model.parameters(), lr</span><span style="color:#859900;">=</span><span style="color:#D33682;">0.01</span><span style="color:#657B83;">, momentum</span><span style="color:#859900;">=</span><span style="color:#D33682;">0.5</span><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>ここで使用された 学習率 (<code>lr=0.01</code>) やモメンタム (<code>momentum=0.5</code>) は恣意的に選択された値であり,これがベストな数値であるのかはわからない. たまたまこのチョイスが最適であるかもしれないし,もっと高い精度を出すハイパーパラメータの組が存在するかもしれない. この問題に答えるため,ハイパーパラメータサーチを行おう. 今回は,最もシンプルなアプローチとして,<strong>グリッドサーチ</strong>によるハイパーパラメータサーチを行おう.</p><p>機械学習のハイパーパラメータの最適化には大きく3つのアプローチが挙げられる. グリッドサーチ,ランダムサーチ,そしてベイズ最適化による方法である.</p><p>グリッドサーチとは,ハイパーパラメータの組をある範囲の中で可能な組み合わせをすべて計算し,最適なパラメータの組を見出す方法である. 最もシンプルかつ確実な方法であるが,すべての組み合わせの可能性を愚直に計算するので計算コストが大きい.</p><p>ランダムサーチ法とは,ハイパーパラメータの組をある範囲の中でランダムに抽出し,大量に試行されたランダムな組の中から最適なパラメータの組を見出す方法である. すべての可能性を網羅的に探索できるわけではないが,調整すべきパラメータの数が多数ある場合に,グリッドサーチよりも効率的に広い探索空間をカバーすることができる.</p><p>ベイズ最適化を用いた方法では,過去の探索結果から次にどの組み合わせを探索すべきかという指標を計算し,次に探索するパラメータを決定する. これにより,理論的にはグリッドサーチやランダムサーチ法よりも少ない試行回数で最適なパラメータにたどり着くことができる.</p><p>並列化の観点でいうと,グリッドサーチとランダムサーチは各ハイパーパラメータの組の計算は独立に実行することができるため並列化が容易である. このように独立したジョブとして分割・並列化可能な問題を Embarrassingly parallel な問題とよぶ (直訳すると&quot;恥ずかしいほど並列化可能な問題&quot;,ということになる) Embarrassingly parallel な問題はクラウドの強力な計算リソースを用いることで,非常なシンプルな実装で解くことができる. この章ではこのようなタイプの並列計算を取り上げる.</p><p>一方,ベイズ最適化による方法は,過去の結果をもとに次の探索が決定されるので,並列化はそれほど単純ではない. 最近では <a href="https://optuna.org/" target="_blank" rel="noreferrer">optuna</a> などのハイパーパラメータ探索のためのライブラリが発達しており,ベイズ最適化の数理的な処理を自動で実行してくれるので便利である. これらのライブラリを使うと,もし一台のコンピュータ (ノード) の中に複数の GPU が存在する場合は,並列に計算を実行することができる. しかしながら,一台のノードにとどまらず,複数のノードをまたいだ並列化は,高度なプログラミングテクニックが必要とされるだけでなく,ノード間の接続様式などクラウドのアーキテクチャにも深く依存するものである. 本書ではここまで高度なクラウドの使用方法には立ち入らない.</p><p>まずは,本ハンズオンで使用する Docker イメージをローカルで実行してみよう.</p><p>Docker イメージのソースコードは <a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/aws-batch/docker" target="_blank" rel="noreferrer">handson/aws-batch/docker</a> にある. 基本的に <a href="#sec_mnist_using_jupyter">実践ディープラーニング! MNIST 手書き数字認識タスク</a> のハンズオンを元にし,本ハンズオン専用の軽微な変更が施してある. 興味のある読者はソースコードも含めて読んでいただきたい.</p><p>練習として,この Docker イメージを手元でビルドするところからはじめてみよう. <code>Dockerfile</code> が保存されているディレクトリに移動し, <code>mymnist</code> という名前 (Tag) をつけてビルドを実行する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cd</span><span style="color:#839496;"> </span><span style="color:#2AA198;">handson/aws-batch/docker</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">build</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-t</span><span style="color:#839496;"> </span><span style="color:#2AA198;">mymnist</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cd</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">handson/aws-batch/docker</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">build</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-t</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">mymnist</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p><code>docker build</code> でエラーが出たときは次の可能性を疑ってほしい. ビルドの中で, MNIST の画像データセットを <a href="http://yann.lecun.com/exdb/mnist/" target="_blank" rel="noreferrer">http://yann.lecun.com/exdb/mnist/</a> からダウンロードするのだが,ダウンロード先のサーバーがしばしばダウンしている. 世界中の機械学習ユーザーがアクセスするので,これはしばしば発生するようである. サーバーがダウンしているとビルドも失敗してしまう. エラーメッセージにそれらしい文言が含まれていたら,この可能性を疑おう.</p><p>手元でビルドするかわりに, Docker Hub から pull することも可能である. その場合は次のコマンドを実行する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pull</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tomomano/mymnist:latest</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pull</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tomomano/mymnist:latest</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>イメージの準備ができたら,次のコマンドでコンテナを起動し, MNIST の学習を実行する..</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run</span><span style="color:#839496;"> </span><span style="color:#2AA198;">mymnist</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--lr</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.1</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--momentum</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.5</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--epochs</span><span style="color:#839496;"> </span><span style="color:#D33682;">10</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">mymnist</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--lr</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.1</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--momentum</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.5</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--epochs</span><span style="color:#657B83;"> </span><span style="color:#D33682;">10</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>このコマンドを実行すると,指定したハイパーパラメータ (<code>--lr</code> で与えられる学習率と <code>--momentum</code> で与えられるモメンタム) を使ってニューラルネットの最適化が始まる. 学習を行う最大のエポック数は <code>--epochs</code> パラメータで指定する. <a href="#sec_jupyter_and_deep_learning">Hands-on #2: AWS でディープラーニングを実践</a> のハンズオンで見たような, Loss の低下がコマンドライン上に出力されるだろう (<a href="#fig_mnist_log_output">figure_title</a>)</p><p><img src="`+ys+'" alt="Docker を実行した際の出力"></p><p>上に示したコマンドを使うと,計算は CPU を使って実行される. もし,ローカルの計算機に GPU が備わっており, <a href="https://github.com/NVIDIA/nvidia-docker" target="_blank" rel="noreferrer">nvidia-docker</a> の設定が済んでいるならば, 次のコマンドにより GPU を使って計算を実行できる.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--gpus</span><span style="color:#839496;"> </span><span style="color:#2AA198;">all</span><span style="color:#839496;"> </span><span style="color:#2AA198;">mymnist</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--lr</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.1</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--momentum</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.5</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--epochs</span><span style="color:#839496;"> </span><span style="color:#D33682;">10</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--gpus</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">all</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">mymnist</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--lr</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.1</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--momentum</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.5</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--epochs</span><span style="color:#657B83;"> </span><span style="color:#D33682;">10</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>このコマンドでは,<code>--gpus all</code> というパラメータが加わった.</p><p>CPU/GPU どちらで実行した場合でも,エポックを重ねるにつれて訓練データ (Train データ) の Loss は単調に減少していくのが見て取れるだろう. 一方,<strong>検証データ (Validation データ) の Loss および Accuracy は,ある程度まで減少した後,それ以上性能が向上しない</strong>ことに気がつくだろう. これを実際にプロットしてみると <a href="#fig_loss_epoch_profile">figure_title</a> のようになるはずである.</p><p><img src="'+ds+'" alt="(左) Train/Validation データそれぞれの Loss のエポックごとの変化. (右) Validation データの Accuracy のエポックごとの変化"></p><p>これは<strong>オーバーフィッティング</strong>とよばれる現象で,ニューラルネットが訓練データに過度に最適化され,訓練データの外のデータに対しての精度 (汎化性能) が向上していないことを示している. このような場合の対処法として, <strong>Early stopping</strong> とよばれるテクニックが知られている. Early stopping とは,検証データの Loss を追跡し,それが減少から増加に転じるエポックで学習をうち止め,そのエポックでのウェイトパラメータを採用する,というものである. 本ハンズオンでも, Early stopping によって訓練の終了を判断し,モデルの性能評価を行っていく.</p><p>MNIST 手書き文字データセットでは,訓練データとして 60,000 枚,テストデータとして 10,000 枚の画像が与えられている. 本ハンズオンで使用するコードでは,訓練データのうち 80% の 48,000 枚を訓練データとして使用し,残り 20% の 12,000 枚を検証データとして用いている. 詳しくはソースコードを参照のこと.</p><h2 id="アプリケーションの説明-3" tabindex="-1">アプリケーションの説明 <a class="header-anchor" href="#アプリケーションの説明-3" aria-label="Permalink to &quot;アプリケーションの説明&quot;"></a></h2><p>このハンズオンで作成するアプリケーションの概要を <a href="#fig_batch_architecture">figure_title</a> に示す.</p><p><img src="'+us+`" alt="アプリケーションのアーキテクチャ"></p><p>簡単にまとめると,次のような設計である.</p><ul><li><p>クライアントは,あるハイパーパラメータの組を指定して Batch にジョブを提出する</p></li><li><p>Batch はジョブを受け取ると, EC2 からなるクラスターで計算を実行する</p></li><li><p>クラスター内では <code>g4dn.xlarge</code> インスタンスが起動する</p></li><li><p>Docker イメージは, AWS 内に用意された ECR (Elastic Container Registry) から取得される</p></li><li><p>複数のジョブが投下された場合は,その数だけのインスタンスが起動し並列に実行される</p></li><li><p>各ジョブによる計算の結果は S3 に保存される</p></li><li><p>最後にクライアントは S3 から結果をダウンロードし,最適なハイパーパラメータの組を決定する</p></li></ul><p>それでは,プログラムのソースコードを見てみよう (<a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/aws-batch/app.py" target="_blank" rel="noreferrer">handson/aws-batch/app.py</a>)</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#93A1A1;font-weight:bold;">class</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">SimpleBatch</span><span style="color:#839496;">(</span><span style="color:#6C71C4;">core</span><span style="color:#839496;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#839496;">):</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#839496;">, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs) -&gt; </span><span style="color:#B58900;">None</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">super</span><span style="color:#839496;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> bucket </span><span style="color:#859900;">=</span><span style="color:#839496;"> s3.Bucket(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;bucket&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#839496;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> auto_delete_objects</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> vpc </span><span style="color:#859900;">=</span><span style="color:#839496;"> ec2.Vpc(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;vpc&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># other parameters...</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> managed_env </span><span style="color:#859900;">=</span><span style="color:#839496;"> batch.ComputeEnvironment(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;managed-env&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> compute_resources</span><span style="color:#859900;">=</span><span style="color:#839496;">batch.ComputeResources(</span></span>
<span class="line"><span style="color:#839496;"> vpc</span><span style="color:#859900;">=</span><span style="color:#839496;">vpc,</span></span>
<span class="line"><span style="color:#839496;"> allocation_strategy</span><span style="color:#859900;">=</span><span style="color:#839496;">batch.AllocationStrategy.</span><span style="color:#CB4B16;">BEST_FIT</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> desiredv_cpus</span><span style="color:#859900;">=</span><span style="color:#D33682;">0</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> maxv_cpus</span><span style="color:#859900;">=</span><span style="color:#D33682;">64</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> minv_cpus</span><span style="color:#859900;">=</span><span style="color:#D33682;">0</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> instance_types</span><span style="color:#859900;">=</span><span style="color:#839496;">[</span></span>
<span class="line"><span style="color:#839496;"> ec2.InstanceType(</span><span style="color:#2AA198;">&quot;g4dn.xlarge&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> ],</span></span>
<span class="line"><span style="color:#839496;"> ),</span></span>
<span class="line"><span style="color:#839496;"> managed</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> compute_environment_name</span><span style="color:#859900;">=</span><span style="color:#268BD2;">self</span><span style="color:#839496;">.stack_name </span><span style="color:#859900;">+</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;compute-env&quot;</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> job_queue </span><span style="color:#859900;">=</span><span style="color:#839496;"> batch.JobQueue(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;job-queue&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> compute_environments</span><span style="color:#859900;">=</span><span style="color:#839496;">[</span></span>
<span class="line"><span style="color:#839496;"> batch.JobQueueComputeEnvironment(</span></span>
<span class="line"><span style="color:#839496;"> compute_environment</span><span style="color:#859900;">=</span><span style="color:#839496;">managed_env,</span></span>
<span class="line"><span style="color:#839496;"> order</span><span style="color:#859900;">=</span><span style="color:#D33682;">100</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> ],</span></span>
<span class="line"><span style="color:#839496;"> job_queue_name</span><span style="color:#859900;">=</span><span style="color:#268BD2;">self</span><span style="color:#839496;">.stack_name </span><span style="color:#859900;">+</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;job-queue&quot;</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> job_role </span><span style="color:#859900;">=</span><span style="color:#839496;"> iam.Role(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;job-role&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> assumed_by</span><span style="color:#859900;">=</span><span style="color:#839496;">iam.CompositePrincipal(</span></span>
<span class="line"><span style="color:#839496;"> iam.ServicePrincipal(</span><span style="color:#2AA198;">&quot;ecs-tasks.amazonaws.com&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># allow read and write access to S3 bucket</span></span>
<span class="line"><span style="color:#839496;"> bucket.grant_read_write(job_role)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> repo </span><span style="color:#859900;">=</span><span style="color:#839496;"> ecr.Repository(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;repository&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#839496;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> job_def </span><span style="color:#859900;">=</span><span style="color:#839496;"> batch.JobDefinition(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;job-definition&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> container</span><span style="color:#859900;">=</span><span style="color:#839496;">batch.JobDefinitionContainer(</span></span>
<span class="line"><span style="color:#839496;"> image</span><span style="color:#859900;">=</span><span style="color:#839496;">ecs.ContainerImage.from_ecr_repository(repo),</span></span>
<span class="line"><span style="color:#839496;"> command</span><span style="color:#859900;">=</span><span style="color:#839496;">[</span><span style="color:#2AA198;">&quot;python3&quot;</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;main.py&quot;</span><span style="color:#839496;">],</span></span>
<span class="line"><span style="color:#839496;"> vcpus</span><span style="color:#859900;">=</span><span style="color:#D33682;">4</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> gpu_count</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> memory_limit_mib</span><span style="color:#859900;">=</span><span style="color:#D33682;">12000</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> job_role</span><span style="color:#859900;">=</span><span style="color:#839496;">job_role,</span></span>
<span class="line"><span style="color:#839496;"> environment</span><span style="color:#859900;">=</span><span style="color:#839496;">{</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;BUCKET_NAME&quot;</span><span style="color:#839496;">: bucket.bucket_name</span></span>
<span class="line"><span style="color:#839496;"> }</span></span>
<span class="line"><span style="color:#839496;"> ),</span></span>
<span class="line"><span style="color:#839496;"> job_definition_name</span><span style="color:#859900;">=</span><span style="color:#268BD2;">self</span><span style="color:#839496;">.stack_name </span><span style="color:#859900;">+</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;job-definition&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> timeout</span><span style="color:#859900;">=</span><span style="color:#839496;">core.Duration.hours(</span><span style="color:#D33682;">2</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> )</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#586E75;font-weight:bold;">class</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">SimpleBatch</span><span style="color:#657B83;">(</span><span style="color:#6C71C4;">core</span><span style="color:#657B83;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#657B83;">):</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#657B83;">, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs) -&gt; </span><span style="color:#B58900;">None</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">super</span><span style="color:#657B83;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> bucket </span><span style="color:#859900;">=</span><span style="color:#657B83;"> s3.Bucket(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;bucket&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#657B83;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> auto_delete_objects</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> vpc </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ec2.Vpc(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;vpc&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># other parameters...</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> managed_env </span><span style="color:#859900;">=</span><span style="color:#657B83;"> batch.ComputeEnvironment(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;managed-env&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> compute_resources</span><span style="color:#859900;">=</span><span style="color:#657B83;">batch.ComputeResources(</span></span>
<span class="line"><span style="color:#657B83;"> vpc</span><span style="color:#859900;">=</span><span style="color:#657B83;">vpc,</span></span>
<span class="line"><span style="color:#657B83;"> allocation_strategy</span><span style="color:#859900;">=</span><span style="color:#657B83;">batch.AllocationStrategy.</span><span style="color:#CB4B16;">BEST_FIT</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> desiredv_cpus</span><span style="color:#859900;">=</span><span style="color:#D33682;">0</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> maxv_cpus</span><span style="color:#859900;">=</span><span style="color:#D33682;">64</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> minv_cpus</span><span style="color:#859900;">=</span><span style="color:#D33682;">0</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> instance_types</span><span style="color:#859900;">=</span><span style="color:#657B83;">[</span></span>
<span class="line"><span style="color:#657B83;"> ec2.InstanceType(</span><span style="color:#2AA198;">&quot;g4dn.xlarge&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> ],</span></span>
<span class="line"><span style="color:#657B83;"> ),</span></span>
<span class="line"><span style="color:#657B83;"> managed</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> compute_environment_name</span><span style="color:#859900;">=</span><span style="color:#268BD2;">self</span><span style="color:#657B83;">.stack_name </span><span style="color:#859900;">+</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;compute-env&quot;</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> job_queue </span><span style="color:#859900;">=</span><span style="color:#657B83;"> batch.JobQueue(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;job-queue&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> compute_environments</span><span style="color:#859900;">=</span><span style="color:#657B83;">[</span></span>
<span class="line"><span style="color:#657B83;"> batch.JobQueueComputeEnvironment(</span></span>
<span class="line"><span style="color:#657B83;"> compute_environment</span><span style="color:#859900;">=</span><span style="color:#657B83;">managed_env,</span></span>
<span class="line"><span style="color:#657B83;"> order</span><span style="color:#859900;">=</span><span style="color:#D33682;">100</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> ],</span></span>
<span class="line"><span style="color:#657B83;"> job_queue_name</span><span style="color:#859900;">=</span><span style="color:#268BD2;">self</span><span style="color:#657B83;">.stack_name </span><span style="color:#859900;">+</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;job-queue&quot;</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> job_role </span><span style="color:#859900;">=</span><span style="color:#657B83;"> iam.Role(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;job-role&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> assumed_by</span><span style="color:#859900;">=</span><span style="color:#657B83;">iam.CompositePrincipal(</span></span>
<span class="line"><span style="color:#657B83;"> iam.ServicePrincipal(</span><span style="color:#2AA198;">&quot;ecs-tasks.amazonaws.com&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># allow read and write access to S3 bucket</span></span>
<span class="line"><span style="color:#657B83;"> bucket.grant_read_write(job_role)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> repo </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ecr.Repository(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;repository&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#657B83;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> job_def </span><span style="color:#859900;">=</span><span style="color:#657B83;"> batch.JobDefinition(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;job-definition&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> container</span><span style="color:#859900;">=</span><span style="color:#657B83;">batch.JobDefinitionContainer(</span></span>
<span class="line"><span style="color:#657B83;"> image</span><span style="color:#859900;">=</span><span style="color:#657B83;">ecs.ContainerImage.from_ecr_repository(repo),</span></span>
<span class="line"><span style="color:#657B83;"> command</span><span style="color:#859900;">=</span><span style="color:#657B83;">[</span><span style="color:#2AA198;">&quot;python3&quot;</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;main.py&quot;</span><span style="color:#657B83;">],</span></span>
<span class="line"><span style="color:#657B83;"> vcpus</span><span style="color:#859900;">=</span><span style="color:#D33682;">4</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> gpu_count</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> memory_limit_mib</span><span style="color:#859900;">=</span><span style="color:#D33682;">12000</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> job_role</span><span style="color:#859900;">=</span><span style="color:#657B83;">job_role,</span></span>
<span class="line"><span style="color:#657B83;"> environment</span><span style="color:#859900;">=</span><span style="color:#657B83;">{</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;BUCKET_NAME&quot;</span><span style="color:#657B83;">: bucket.bucket_name</span></span>
<span class="line"><span style="color:#657B83;"> }</span></span>
<span class="line"><span style="color:#657B83;"> ),</span></span>
<span class="line"><span style="color:#657B83;"> job_definition_name</span><span style="color:#859900;">=</span><span style="color:#268BD2;">self</span><span style="color:#657B83;">.stack_name </span><span style="color:#859900;">+</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;job-definition&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> timeout</span><span style="color:#859900;">=</span><span style="color:#657B83;">core.Duration.hours(</span><span style="color:#D33682;">2</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br></div></div><ul><li><p> S3 </p></li><li><p> Compute environment <code>g4dn.xlarge</code> 使 vCPU 使 64 vCPU 0 0 </p></li><li><p> &lt;2&gt; Compute environment Job queue </p></li><li><p> S3 IAM (IAM <a href="#sec:bashoutter_iam">AWS (IAM)</a> )</p></li><li><p> Docker image ECR </p></li><li><p> Job definition 4 vCPU 12000 MB (=12GB) RAM 使 (<code>BUCKET_NAME</code>) &lt;4&gt; IAM </p></li></ul><p><code>g4dn.xlarge</code> 1 4 vCPU Compute environment maximum vCPUs 64 16 maxium vCPUs 64 AWS 64 </p><p> AWS EC2 AWS EC2 <code>Limits</code> (<a href="#fig_ec2_limits">figure_title</a>) <code>g4dn.xlarge</code> (EC2 G ) <code>Running On-Demand All G instances</code> AWS <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-resource-limits.html" target="_blank" rel="noreferrer"> &quot;Amazon EC2 service quotas&quot;</a> </p><p><img src="`+bs+`" alt="EC2"></p><h2 id="-2" tabindex="-1"> <a class="header-anchor" href="#-2" aria-label="Permalink to &quot;&quot;"></a></h2><p></p><p> (# ) (<a href="#aws_cli_install">AWS CLI </a>)</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># </span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cd</span><span style="color:#839496;"> </span><span style="color:#2AA198;">handson/aws-batch</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># venv を作成し依存ライブラリのインストールを行う</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python3</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#839496;"> </span><span style="color:#2AA198;">venv</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">source</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pip</span><span style="color:#839496;"> </span><span style="color:#2AA198;">install</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#839496;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># デプロイを実行</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">deploy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># </span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cd</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">handson/aws-batch</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># venv を作成し依存ライブラリのインストールを行う</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python3</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">venv</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">source</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pip</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">install</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># デプロイを実行</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">deploy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>AWS <code>batch</code> AWS Batch (<a href="#fig_batch_console">figure_title</a>)</p><p><img src="`+As+'" alt="AWS Batch ()"></p><p> Compute environment overview <code>SimpleBatchcompute-env</code> Compute environment () <code>g4dn.xlarge</code> 使 <code>Minimum vCPUs</code> 0<code>Maximum vCPUs</code> 64 <code>Desired vCPUs</code> 0 Compute environment </p><p>Job queue overview <code>SimpleBatch-queue</code> <code>PENDING</code>, <code>RUNNING</code>, <code>SUCCEEDED</code>, <code>FAILED</code> </p><p> Job definition  <code>Job definitions</code> <code>SimpleBatchjob-definition</code> Job definition (<a href="#fig:batch_job_definition">figure_title</a>)  <code>vCPUs</code>, <code>Memory</code>, <code>GPU</code> Docker vCPU GPU <code>Image</code> 使 Docker ECR ECR ECR </p><p><img src="'+ms+`" alt="AWS Batch Job definition "></p><h2 id="docker-image--ecr-" tabindex="-1">Docker image ECR <a class="header-anchor" href="#docker-image--ecr-" aria-label="Permalink to &quot;Docker image ECR &quot;"></a></h2><p> Batch Docker (pull) (<a href="#sec_fargate_qabot">Hands-on #3: AWS </a>) Docker Hub pull AWS <strong>ECR (Elastic Container Registry)</strong> image ECR Batch ECR pull (<a href="#fig_batch_architecture">figure_title</a>)</p><p> ECR </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;">repo </span><span style="color:#859900;">=</span><span style="color:#839496;"> ecr.Repository(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;repository&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#839496;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;">job_def </span><span style="color:#859900;">=</span><span style="color:#839496;"> batch.JobDefinition(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;job-definition&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> container</span><span style="color:#859900;">=</span><span style="color:#839496;">batch.JobDefinitionContainer(</span></span>
<span class="line"><span style="color:#839496;"> image</span><span style="color:#859900;">=</span><span style="color:#839496;">ecs.ContainerImage.from_ecr_repository(repo), </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#CB4B16;">...</span></span>
<span class="line"><span style="color:#839496;"> ),</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#CB4B16;">...</span></span>
<span class="line"><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;">repo </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ecr.Repository(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;repository&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#657B83;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;">job_def </span><span style="color:#859900;">=</span><span style="color:#657B83;"> batch.JobDefinition(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;job-definition&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> container</span><span style="color:#859900;">=</span><span style="color:#657B83;">batch.JobDefinitionContainer(</span></span>
<span class="line"><span style="color:#657B83;"> image</span><span style="color:#859900;">=</span><span style="color:#657B83;">ecs.ContainerImage.from_ecr_repository(repo), </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#CB4B16;">...</span></span>
<span class="line"><span style="color:#657B83;"> ),</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#CB4B16;">...</span></span>
<span class="line"><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><ul><li><p> ECR </p></li><li><p> Job definition &lt;1&gt; ECR Job definition ECR IAM </p></li></ul><p> ECR 使 Docker push </p><p> AWS ECR ( <code>Elastic Container Registry</code> ) <code>Private</code> <code>simplebatch-repositoryXXXXXX</code> (<a href="#fig_ecr_console1">figure_title</a>)</p><p><img src="`+hs+'" alt="ECR "></p><p> <code>View push commands</code> <a href="#fig_ecr_push_command">figure_title</a> </p><p><img src="'+Bs+'" alt="ECR push "></p><p> Docker ECR push <strong>push AWS </strong> <strong><code>docker/</code> </strong> </p><p> 2 <code>docker build -t XXXXX .</code> <code>.</code> <em> Dockerfile 使</em> <code>Dockerfile</code> </p><p> GB ECR ECR ECR (<a href="#fig_ecr_console2">figure_title</a>) AWS Batch 使</p><p><img src="'+gs+`" alt="ECR image "></p><h2 id="" tabindex="-1"> <a class="header-anchor" href="#" aria-label="Permalink to &quot;&quot;"></a></h2><p> AWS Batch </p><p> <code>notebook/</code> <a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/aws-batch/notebook/run_single.ipynb" target="_blank" rel="noreferrer">run_single.ipynb</a> (<code>.ipynb</code> Jupyter notebook ) Jupyter notebook </p><p> <code>venv</code> Jupyter notebook Jupyter notebook </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># .env </span></span>
<span class="line"><span style="color:#839496;">(</span><span style="color:#268BD2;">.env</span><span style="color:#839496;">) $ cd notebook</span></span>
<span class="line"><span style="color:#839496;">(</span><span style="color:#268BD2;">.env</span><span style="color:#839496;">) $ jupyter notebook</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># .env </span></span>
<span class="line"><span style="color:#657B83;">(</span><span style="color:#268BD2;">.env</span><span style="color:#657B83;">) $ cd notebook</span></span>
<span class="line"><span style="color:#657B83;">(</span><span style="color:#268BD2;">.env</span><span style="color:#657B83;">) $ jupyter notebook</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>Jupyter notebook <code>run_single.ipynb</code> </p><p> [1], [2], [3] (<code>submit_job()</code>) </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># [1]</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> boto3</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> argparse</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># [2]</span></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># AWS 認証ヘルパー ...省略...</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># [3]</span></span>
<span class="line"><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">submit_job</span><span style="color:#839496;">(lr:</span><span style="color:#859900;">float</span><span style="color:#839496;">, momentum:</span><span style="color:#859900;">float</span><span style="color:#839496;">, epochs:</span><span style="color:#859900;">int</span><span style="color:#839496;">, profile_name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;default&quot;</span><span style="color:#839496;">):</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">if</span><span style="color:#839496;"> profile_name </span><span style="color:#859900;">is</span><span style="color:#839496;"> </span><span style="color:#B58900;">None</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> session </span><span style="color:#859900;">=</span><span style="color:#839496;"> boto3.Session()</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">else</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> session </span><span style="color:#859900;">=</span><span style="color:#839496;"> boto3.Session(profile_name</span><span style="color:#859900;">=</span><span style="color:#839496;">profile_name)</span></span>
<span class="line"><span style="color:#839496;"> client </span><span style="color:#859900;">=</span><span style="color:#839496;"> session.client(</span><span style="color:#2AA198;">&quot;batch&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> title </span><span style="color:#859900;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;lr&quot;</span><span style="color:#839496;"> </span><span style="color:#859900;">+</span><span style="color:#839496;"> </span><span style="color:#859900;">str</span><span style="color:#839496;">(lr).replace(</span><span style="color:#2AA198;">&quot;.&quot;</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#839496;">) </span><span style="color:#859900;">+</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;_m&quot;</span><span style="color:#839496;"> </span><span style="color:#859900;">+</span><span style="color:#839496;"> </span><span style="color:#859900;">str</span><span style="color:#839496;">(momentum).replace(</span><span style="color:#2AA198;">&quot;.&quot;</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> resp </span><span style="color:#859900;">=</span><span style="color:#839496;"> client.submit_job(</span></span>
<span class="line"><span style="color:#839496;"> jobName</span><span style="color:#859900;">=</span><span style="color:#839496;">title,</span></span>
<span class="line"><span style="color:#839496;"> jobQueue</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;SimpleBatchjob-queue&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> jobDefinition</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;SimpleBatchjob-definition&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> containerOverrides</span><span style="color:#859900;">=</span><span style="color:#839496;">{</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;command&quot;</span><span style="color:#839496;">: [</span><span style="color:#2AA198;">&quot;--lr&quot;</span><span style="color:#839496;">, </span><span style="color:#859900;">str</span><span style="color:#839496;">(lr),</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;--momentum&quot;</span><span style="color:#839496;">, </span><span style="color:#859900;">str</span><span style="color:#839496;">(momentum),</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;--epochs&quot;</span><span style="color:#839496;">, </span><span style="color:#859900;">str</span><span style="color:#839496;">(epochs),</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;--uploadS3&quot;</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;true&quot;</span><span style="color:#839496;">]</span></span>
<span class="line"><span style="color:#839496;"> }</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">print</span><span style="color:#839496;">(</span><span style="color:#2AA198;">&quot;Job submitted!&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">print</span><span style="color:#839496;">(</span><span style="color:#2AA198;">&quot;job name&quot;</span><span style="color:#839496;">, resp[</span><span style="color:#2AA198;">&quot;jobName&quot;</span><span style="color:#839496;">], </span><span style="color:#2AA198;">&quot;job ID&quot;</span><span style="color:#839496;">, resp[</span><span style="color:#2AA198;">&quot;jobId&quot;</span><span style="color:#839496;">])</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># [1]</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> boto3</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> argparse</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># [2]</span></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># AWS 認証ヘルパー ...省略...</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># [3]</span></span>
<span class="line"><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">submit_job</span><span style="color:#657B83;">(lr:</span><span style="color:#859900;">float</span><span style="color:#657B83;">, momentum:</span><span style="color:#859900;">float</span><span style="color:#657B83;">, epochs:</span><span style="color:#859900;">int</span><span style="color:#657B83;">, profile_name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;default&quot;</span><span style="color:#657B83;">):</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">if</span><span style="color:#657B83;"> profile_name </span><span style="color:#859900;">is</span><span style="color:#657B83;"> </span><span style="color:#B58900;">None</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> session </span><span style="color:#859900;">=</span><span style="color:#657B83;"> boto3.Session()</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">else</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> session </span><span style="color:#859900;">=</span><span style="color:#657B83;"> boto3.Session(profile_name</span><span style="color:#859900;">=</span><span style="color:#657B83;">profile_name)</span></span>
<span class="line"><span style="color:#657B83;"> client </span><span style="color:#859900;">=</span><span style="color:#657B83;"> session.client(</span><span style="color:#2AA198;">&quot;batch&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> title </span><span style="color:#859900;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;lr&quot;</span><span style="color:#657B83;"> </span><span style="color:#859900;">+</span><span style="color:#657B83;"> </span><span style="color:#859900;">str</span><span style="color:#657B83;">(lr).replace(</span><span style="color:#2AA198;">&quot;.&quot;</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#657B83;">) </span><span style="color:#859900;">+</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;_m&quot;</span><span style="color:#657B83;"> </span><span style="color:#859900;">+</span><span style="color:#657B83;"> </span><span style="color:#859900;">str</span><span style="color:#657B83;">(momentum).replace(</span><span style="color:#2AA198;">&quot;.&quot;</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> resp </span><span style="color:#859900;">=</span><span style="color:#657B83;"> client.submit_job(</span></span>
<span class="line"><span style="color:#657B83;"> jobName</span><span style="color:#859900;">=</span><span style="color:#657B83;">title,</span></span>
<span class="line"><span style="color:#657B83;"> jobQueue</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;SimpleBatchjob-queue&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> jobDefinition</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;SimpleBatchjob-definition&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> containerOverrides</span><span style="color:#859900;">=</span><span style="color:#657B83;">{</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;command&quot;</span><span style="color:#657B83;">: [</span><span style="color:#2AA198;">&quot;--lr&quot;</span><span style="color:#657B83;">, </span><span style="color:#859900;">str</span><span style="color:#657B83;">(lr),</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;--momentum&quot;</span><span style="color:#657B83;">, </span><span style="color:#859900;">str</span><span style="color:#657B83;">(momentum),</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;--epochs&quot;</span><span style="color:#657B83;">, </span><span style="color:#859900;">str</span><span style="color:#657B83;">(epochs),</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;--uploadS3&quot;</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;true&quot;</span><span style="color:#657B83;">]</span></span>
<span class="line"><span style="color:#657B83;"> }</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">print</span><span style="color:#657B83;">(</span><span style="color:#2AA198;">&quot;Job submitted!&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">print</span><span style="color:#657B83;">(</span><span style="color:#2AA198;">&quot;job name&quot;</span><span style="color:#657B83;">, resp[</span><span style="color:#2AA198;">&quot;jobName&quot;</span><span style="color:#657B83;">], </span><span style="color:#2AA198;">&quot;job ID&quot;</span><span style="color:#657B83;">, resp[</span><span style="color:#2AA198;">&quot;jobId&quot;</span><span style="color:#657B83;">])</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br></div></div><p><code>submit_job()</code> <a href="#sec_run_mnist_docker_local">MNIST ()</a> MNIST Docker 使</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-it</span><span style="color:#839496;"> </span><span style="color:#2AA198;">mymnist</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--lr</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.1</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--momentum</span><span style="color:#839496;"> </span><span style="color:#D33682;">0.5</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--epochs</span><span style="color:#839496;"> </span><span style="color:#D33682;">10</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-it</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">mymnist</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--lr</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.1</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--momentum</span><span style="color:#657B83;"> </span><span style="color:#D33682;">0.5</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--epochs</span><span style="color:#657B83;"> </span><span style="color:#D33682;">10</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> <code>--lr 0.1 --momentum 0.5 --epochs 10</code> </p><p>AWS Batch <code>ContainerOverrides</code> <code>command</code> 使 </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">containerOverrides</span><span style="color:#859900;">=</span><span style="color:#839496;">{</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;command&quot;</span><span style="color:#839496;">: [</span><span style="color:#2AA198;">&quot;--lr&quot;</span><span style="color:#839496;">, </span><span style="color:#859900;">str</span><span style="color:#839496;">(lr),</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;--momentum&quot;</span><span style="color:#839496;">, </span><span style="color:#859900;">str</span><span style="color:#839496;">(momentum),</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;--epochs&quot;</span><span style="color:#839496;">, </span><span style="color:#859900;">str</span><span style="color:#839496;">(epochs),</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;--uploadS3&quot;</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;true&quot;</span><span style="color:#839496;">]</span></span>
<span class="line"><span style="color:#839496;">}</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">containerOverrides</span><span style="color:#859900;">=</span><span style="color:#657B83;">{</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;command&quot;</span><span style="color:#657B83;">: [</span><span style="color:#2AA198;">&quot;--lr&quot;</span><span style="color:#657B83;">, </span><span style="color:#859900;">str</span><span style="color:#657B83;">(lr),</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;--momentum&quot;</span><span style="color:#657B83;">, </span><span style="color:#859900;">str</span><span style="color:#657B83;">(momentum),</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;--epochs&quot;</span><span style="color:#657B83;">, </span><span style="color:#859900;">str</span><span style="color:#657B83;">(epochs),</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;--uploadS3&quot;</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;true&quot;</span><span style="color:#657B83;">]</span></span>
<span class="line"><span style="color:#657B83;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p> [4] <code>submit_job()</code> = 0.01, =0.1, =100 </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># [4]</span></span>
<span class="line"><span style="color:#839496;">submit_job(</span><span style="color:#D33682;">0.01</span><span style="color:#839496;">, </span><span style="color:#D33682;">0.1</span><span style="color:#839496;">, </span><span style="color:#D33682;">100</span><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># [4]</span></span>
<span class="line"><span style="color:#657B83;">submit_job(</span><span style="color:#D33682;">0.01</span><span style="color:#657B83;">, </span><span style="color:#D33682;">0.1</span><span style="color:#657B83;">, </span><span style="color:#D33682;">100</span><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>AWS Jupyter Notebook Notebook [2] () 使 AWS aws secret key (Jupyter ) AWS </p><p> <code>submit_job()</code> <code>profile_name</code> <code>~/.aws/credentials</code> ( <a href="#aws_cli_install">AWS CLI </a>) <code>profile_name</code> 使 便</p><p>[4] AWS AWS Batch <a href="#fig_batch_running_job">figure_title</a> </p><p><img src="`+_s+'" alt="AWS Batch "></p><p><a href="#fig_batch_running_job">figure_title</a> <code>SUBMITTED</code> <code>RUNNABLE</code> <code>RUNNABLE</code> Compute environment <code>STARTING</code> <code>RUNNING</code> </p><p> <code>RUNNING</code> Compute environment <code>Desired vCPU</code> (<a href="#fig_batch_running_job">figure_title</a> ) 4 <code>g4dn.xlarge</code> vCPU EC2 ( EC2 )</p><p> <code>RUNNING</code> <code>SUCCEEDED</code> ( <code>FAILED</code>) 使 MNIST 10 <code>SUCCEEDED</code> </p><p> ( Loss Accuracy CSV ) S3 AWS </p><p>S3 <code>simplebatch-bucketXXXX</code> (XXXX ) <code>metrics_lr0.0100_m0.1000.csv</code> CSV (<a href="#fig_s3_saved_file">figure_title</a>) = 0.01, = 0.1 </p><p><img src="'+fs+`" alt=" S3 "></p><p> <code>run_single.ipynb</code> [5] [7] CSV </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># [5]</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> pandas </span><span style="color:#859900;">as</span><span style="color:#839496;"> pd</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> io</span></span>
<span class="line"><span style="color:#859900;">from</span><span style="color:#839496;"> matplotlib </span><span style="color:#859900;">import</span><span style="color:#839496;"> pyplot </span><span style="color:#859900;">as</span><span style="color:#839496;"> plt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># [6]</span></span>
<span class="line"><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">read_table_from_s3</span><span style="color:#839496;">(bucket_name, key, profile_name</span><span style="color:#859900;">=</span><span style="color:#B58900;">None</span><span style="color:#839496;">):</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">if</span><span style="color:#839496;"> profile_name </span><span style="color:#859900;">is</span><span style="color:#839496;"> </span><span style="color:#B58900;">None</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> session </span><span style="color:#859900;">=</span><span style="color:#839496;"> boto3.Session()</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">else</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> session </span><span style="color:#859900;">=</span><span style="color:#839496;"> boto3.Session(profile_name</span><span style="color:#859900;">=</span><span style="color:#839496;">profile_name)</span></span>
<span class="line"><span style="color:#839496;"> s3 </span><span style="color:#859900;">=</span><span style="color:#839496;"> session.resource(</span><span style="color:#2AA198;">&quot;s3&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> bucket </span><span style="color:#859900;">=</span><span style="color:#839496;"> s3.Bucket(bucket_name)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> obj </span><span style="color:#859900;">=</span><span style="color:#839496;"> bucket.Object(key).get().get(</span><span style="color:#2AA198;">&quot;Body&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> df </span><span style="color:#859900;">=</span><span style="color:#839496;"> pd.read_csv(obj)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">return</span><span style="color:#839496;"> df</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># [7]</span></span>
<span class="line"><span style="color:#839496;">bucket_name </span><span style="color:#859900;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;simplebatch-bucket43879c71-mbqaltx441fu&quot;</span></span>
<span class="line"><span style="color:#839496;">df </span><span style="color:#859900;">=</span><span style="color:#839496;"> read_table_from_s3(</span></span>
<span class="line"><span style="color:#839496;"> bucket_name,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;metrics_lr0.0100_m0.1000.csv&quot;</span></span>
<span class="line"><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># [5]</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> pandas </span><span style="color:#859900;">as</span><span style="color:#657B83;"> pd</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> io</span></span>
<span class="line"><span style="color:#859900;">from</span><span style="color:#657B83;"> matplotlib </span><span style="color:#859900;">import</span><span style="color:#657B83;"> pyplot </span><span style="color:#859900;">as</span><span style="color:#657B83;"> plt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># [6]</span></span>
<span class="line"><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">read_table_from_s3</span><span style="color:#657B83;">(bucket_name, key, profile_name</span><span style="color:#859900;">=</span><span style="color:#B58900;">None</span><span style="color:#657B83;">):</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">if</span><span style="color:#657B83;"> profile_name </span><span style="color:#859900;">is</span><span style="color:#657B83;"> </span><span style="color:#B58900;">None</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> session </span><span style="color:#859900;">=</span><span style="color:#657B83;"> boto3.Session()</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">else</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> session </span><span style="color:#859900;">=</span><span style="color:#657B83;"> boto3.Session(profile_name</span><span style="color:#859900;">=</span><span style="color:#657B83;">profile_name)</span></span>
<span class="line"><span style="color:#657B83;"> s3 </span><span style="color:#859900;">=</span><span style="color:#657B83;"> session.resource(</span><span style="color:#2AA198;">&quot;s3&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> bucket </span><span style="color:#859900;">=</span><span style="color:#657B83;"> s3.Bucket(bucket_name)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> obj </span><span style="color:#859900;">=</span><span style="color:#657B83;"> bucket.Object(key).get().get(</span><span style="color:#2AA198;">&quot;Body&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> df </span><span style="color:#859900;">=</span><span style="color:#657B83;"> pd.read_csv(obj)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">return</span><span style="color:#657B83;"> df</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># [7]</span></span>
<span class="line"><span style="color:#657B83;">bucket_name </span><span style="color:#859900;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;simplebatch-bucket43879c71-mbqaltx441fu&quot;</span></span>
<span class="line"><span style="color:#657B83;">df </span><span style="color:#859900;">=</span><span style="color:#657B83;"> read_table_from_s3(</span></span>
<span class="line"><span style="color:#657B83;"> bucket_name,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;metrics_lr0.0100_m0.1000.csv&quot;</span></span>
<span class="line"><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br></div></div><p>[6] S3 CSV pandas <code>DataFrame</code> [7] <code>bucket_name</code> <strong></strong> ( S3 <code>simplebatch-bucketXXXX</code> )</p><p> [9] CSV (<a href="#fig_loss_epoch_profile2">figure_title</a>) AWS Batch MNIST </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># [9]</span></span>
<span class="line"><span style="color:#839496;">fig, (ax1, ax2) </span><span style="color:#859900;">=</span><span style="color:#839496;"> plt.subplots(</span><span style="color:#D33682;">1</span><span style="color:#839496;">,</span><span style="color:#D33682;">2</span><span style="color:#839496;">, figsize</span><span style="color:#859900;">=</span><span style="color:#839496;">(</span><span style="color:#D33682;">9</span><span style="color:#839496;">,</span><span style="color:#D33682;">4</span><span style="color:#839496;">))</span></span>
<span class="line"><span style="color:#839496;">x </span><span style="color:#859900;">=</span><span style="color:#839496;"> [i </span><span style="color:#859900;">for</span><span style="color:#839496;"> i </span><span style="color:#859900;">in</span><span style="color:#839496;"> </span><span style="color:#268BD2;">range</span><span style="color:#839496;">(df.shape[</span><span style="color:#D33682;">0</span><span style="color:#839496;">])]</span></span>
<span class="line"><span style="color:#839496;">ax1.plot(x, df[</span><span style="color:#2AA198;">&quot;train_loss&quot;</span><span style="color:#839496;">], label</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;Train&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">ax1.plot(x, df[</span><span style="color:#2AA198;">&quot;val_loss&quot;</span><span style="color:#839496;">], label</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;Val&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">ax2.plot(x, df[</span><span style="color:#2AA198;">&quot;val_accuracy&quot;</span><span style="color:#839496;">])</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;">ax1.set_xlabel(</span><span style="color:#2AA198;">&quot;Epochs&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">ax1.set_ylabel(</span><span style="color:#2AA198;">&quot;Loss&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">ax1.legend()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;">ax2.set_xlabel(</span><span style="color:#2AA198;">&quot;Epochs&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">ax2.set_ylabel(</span><span style="color:#2AA198;">&quot;Accuracy&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#839496;">(</span><span style="color:#2AA198;">&quot;Best loss:&quot;</span><span style="color:#839496;">, df[</span><span style="color:#2AA198;">&quot;val_loss&quot;</span><span style="color:#839496;">].min())</span></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#839496;">(</span><span style="color:#2AA198;">&quot;Best loss epoch:&quot;</span><span style="color:#839496;">, df[</span><span style="color:#2AA198;">&quot;val_loss&quot;</span><span style="color:#839496;">].argmin())</span></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#839496;">(</span><span style="color:#2AA198;">&quot;Best accuracy:&quot;</span><span style="color:#839496;">, df[</span><span style="color:#2AA198;">&quot;val_accuracy&quot;</span><span style="color:#839496;">].max())</span></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#839496;">(</span><span style="color:#2AA198;">&quot;Best accuracy epoch:&quot;</span><span style="color:#839496;">, df[</span><span style="color:#2AA198;">&quot;val_accuracy&quot;</span><span style="color:#839496;">].argmax())</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># [9]</span></span>
<span class="line"><span style="color:#657B83;">fig, (ax1, ax2) </span><span style="color:#859900;">=</span><span style="color:#657B83;"> plt.subplots(</span><span style="color:#D33682;">1</span><span style="color:#657B83;">,</span><span style="color:#D33682;">2</span><span style="color:#657B83;">, figsize</span><span style="color:#859900;">=</span><span style="color:#657B83;">(</span><span style="color:#D33682;">9</span><span style="color:#657B83;">,</span><span style="color:#D33682;">4</span><span style="color:#657B83;">))</span></span>
<span class="line"><span style="color:#657B83;">x </span><span style="color:#859900;">=</span><span style="color:#657B83;"> [i </span><span style="color:#859900;">for</span><span style="color:#657B83;"> i </span><span style="color:#859900;">in</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">range</span><span style="color:#657B83;">(df.shape[</span><span style="color:#D33682;">0</span><span style="color:#657B83;">])]</span></span>
<span class="line"><span style="color:#657B83;">ax1.plot(x, df[</span><span style="color:#2AA198;">&quot;train_loss&quot;</span><span style="color:#657B83;">], label</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;Train&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">ax1.plot(x, df[</span><span style="color:#2AA198;">&quot;val_loss&quot;</span><span style="color:#657B83;">], label</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;Val&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">ax2.plot(x, df[</span><span style="color:#2AA198;">&quot;val_accuracy&quot;</span><span style="color:#657B83;">])</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;">ax1.set_xlabel(</span><span style="color:#2AA198;">&quot;Epochs&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">ax1.set_ylabel(</span><span style="color:#2AA198;">&quot;Loss&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">ax1.legend()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;">ax2.set_xlabel(</span><span style="color:#2AA198;">&quot;Epochs&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">ax2.set_ylabel(</span><span style="color:#2AA198;">&quot;Accuracy&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#657B83;">(</span><span style="color:#2AA198;">&quot;Best loss:&quot;</span><span style="color:#657B83;">, df[</span><span style="color:#2AA198;">&quot;val_loss&quot;</span><span style="color:#657B83;">].min())</span></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#657B83;">(</span><span style="color:#2AA198;">&quot;Best loss epoch:&quot;</span><span style="color:#657B83;">, df[</span><span style="color:#2AA198;">&quot;val_loss&quot;</span><span style="color:#657B83;">].argmin())</span></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#657B83;">(</span><span style="color:#2AA198;">&quot;Best accuracy:&quot;</span><span style="color:#657B83;">, df[</span><span style="color:#2AA198;">&quot;val_accuracy&quot;</span><span style="color:#657B83;">].max())</span></span>
<span class="line"><span style="color:#268BD2;">print</span><span style="color:#657B83;">(</span><span style="color:#2AA198;">&quot;Best accuracy epoch:&quot;</span><span style="color:#657B83;">, df[</span><span style="color:#2AA198;">&quot;val_accuracy&quot;</span><span style="color:#657B83;">].argmax())</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><p><img src="`+ks+`" alt="AWS Batch MNIST "></p><h2 id="-job-" tabindex="-1"> Job <a class="header-anchor" href="#-job-" aria-label="Permalink to &quot; Job &quot;"></a></h2><p> AWS Batch 使</p><p> <code>run_single.ipynb</code> <code>run_sweep.ipynb</code> </p><p> [1], [2], [3] <code>run_single.ipynb</code> </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># [1]</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> boto3</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> argparse</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># [2]</span></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># AWS 認証ヘルパー ...省略...</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># [3]</span></span>
<span class="line"><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">submit_job</span><span style="color:#839496;">(lr:</span><span style="color:#859900;">float</span><span style="color:#839496;">, momentum:</span><span style="color:#859900;">float</span><span style="color:#839496;">, epochs:</span><span style="color:#859900;">int</span><span style="color:#839496;">, profile_name</span><span style="color:#859900;">=</span><span style="color:#B58900;">None</span><span style="color:#839496;">):</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># ......</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># [1]</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> boto3</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> argparse</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># [2]</span></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># AWS 認証ヘルパー ...省略...</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># [3]</span></span>
<span class="line"><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">submit_job</span><span style="color:#657B83;">(lr:</span><span style="color:#859900;">float</span><span style="color:#657B83;">, momentum:</span><span style="color:#859900;">float</span><span style="color:#657B83;">, epochs:</span><span style="color:#859900;">int</span><span style="color:#657B83;">, profile_name</span><span style="color:#859900;">=</span><span style="color:#B58900;">None</span><span style="color:#657B83;">):</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># ......</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p> [4] for 使 batch 3x3=9 </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># [4]</span></span>
<span class="line"><span style="color:#859900;">for</span><span style="color:#839496;"> lr </span><span style="color:#859900;">in</span><span style="color:#839496;"> [</span><span style="color:#D33682;">0.1</span><span style="color:#839496;">, </span><span style="color:#D33682;">0.01</span><span style="color:#839496;">, </span><span style="color:#D33682;">0.001</span><span style="color:#839496;">]:</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">for</span><span style="color:#839496;"> m </span><span style="color:#859900;">in</span><span style="color:#839496;"> [</span><span style="color:#D33682;">0.5</span><span style="color:#839496;">, </span><span style="color:#D33682;">0.1</span><span style="color:#839496;">, </span><span style="color:#D33682;">0.05</span><span style="color:#839496;">]:</span></span>
<span class="line"><span style="color:#839496;"> submit_job(lr, m, </span><span style="color:#D33682;">100</span><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># [4]</span></span>
<span class="line"><span style="color:#859900;">for</span><span style="color:#657B83;"> lr </span><span style="color:#859900;">in</span><span style="color:#657B83;"> [</span><span style="color:#D33682;">0.1</span><span style="color:#657B83;">, </span><span style="color:#D33682;">0.01</span><span style="color:#657B83;">, </span><span style="color:#D33682;">0.001</span><span style="color:#657B83;">]:</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">for</span><span style="color:#657B83;"> m </span><span style="color:#859900;">in</span><span style="color:#657B83;"> [</span><span style="color:#D33682;">0.5</span><span style="color:#657B83;">, </span><span style="color:#D33682;">0.1</span><span style="color:#657B83;">, </span><span style="color:#D33682;">0.05</span><span style="color:#657B83;">]:</span></span>
<span class="line"><span style="color:#657B83;"> submit_job(lr, m, </span><span style="color:#D33682;">100</span><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p> [4] Batch <code>SUBMITTED</code> &gt; <code>RUNNABLE</code> &gt; <code>STARTING</code> &gt; <code>RUNNING</code> 9 <code>RUNNING</code> (<a href="#fig_batch_many_parallel_jobs">figure_title</a>) Compute environment <code>Desired vCPUs</code> 4x9=36 (<a href="#fig_batch_many_parallel_jobs">figure_title</a>)</p><p><img src="`+vs+'" alt=" Batch "></p><p>Batch <code>Jobs</code> (<a href="#fig_batch_parallel_job_list">figure_title</a>) 9 <code>RUNNING</code> </p><p><img src="'+qs+'" alt=" Job "></p><p> EC2 <code>Instances</code> <a href="#fig_ec2_instances_list">figure_title</a> <code>g4dn.xlarge</code> 9 Batch </p><p><img src="'+Ds+`" alt=" EC2 "></p><p> Job ( 10-15 ) <code>SUCCEEDED</code> 9 Compute environment <code>Desired vCPUs</code> 0 EC2 g4dn </p><p> AWS Batch 使<strong> EC2 </strong> 10 9 90 AWS Batch 使 (=10 ) </p><p> <code>run_sweep.ipynb</code> [5] </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># [5]</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> pandas </span><span style="color:#859900;">as</span><span style="color:#839496;"> pd</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> numpy </span><span style="color:#859900;">as</span><span style="color:#839496;"> np</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> io</span></span>
<span class="line"><span style="color:#859900;">from</span><span style="color:#839496;"> matplotlib </span><span style="color:#859900;">import</span><span style="color:#839496;"> pyplot </span><span style="color:#859900;">as</span><span style="color:#839496;"> plt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># [6]</span></span>
<span class="line"><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">read_table_from_s3</span><span style="color:#839496;">(bucket_name, key, profile_name</span><span style="color:#859900;">=</span><span style="color:#B58900;">None</span><span style="color:#839496;">):</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">if</span><span style="color:#839496;"> profile_name </span><span style="color:#859900;">is</span><span style="color:#839496;"> </span><span style="color:#B58900;">None</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> session </span><span style="color:#859900;">=</span><span style="color:#839496;"> boto3.Session()</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">else</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> session </span><span style="color:#859900;">=</span><span style="color:#839496;"> boto3.Session(profile_name</span><span style="color:#859900;">=</span><span style="color:#839496;">profile_name)</span></span>
<span class="line"><span style="color:#839496;"> s3 </span><span style="color:#859900;">=</span><span style="color:#839496;"> session.resource(</span><span style="color:#2AA198;">&quot;s3&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> bucket </span><span style="color:#859900;">=</span><span style="color:#839496;"> s3.Bucket(bucket_name)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> obj </span><span style="color:#859900;">=</span><span style="color:#839496;"> bucket.Object(key).get().get(</span><span style="color:#2AA198;">&quot;Body&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> df </span><span style="color:#859900;">=</span><span style="color:#839496;"> pd.read_csv(obj)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">return</span><span style="color:#839496;"> df</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># [7]</span></span>
<span class="line"><span style="color:#839496;">grid </span><span style="color:#859900;">=</span><span style="color:#839496;"> np.zeros((</span><span style="color:#D33682;">3</span><span style="color:#839496;">,</span><span style="color:#D33682;">3</span><span style="color:#839496;">))</span></span>
<span class="line"><span style="color:#859900;">for</span><span style="color:#839496;"> (i, lr) </span><span style="color:#859900;">in</span><span style="color:#839496;"> </span><span style="color:#268BD2;">enumerate</span><span style="color:#839496;">([</span><span style="color:#D33682;">0.1</span><span style="color:#839496;">, </span><span style="color:#D33682;">0.01</span><span style="color:#839496;">, </span><span style="color:#D33682;">0.001</span><span style="color:#839496;">]):</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">for</span><span style="color:#839496;"> (j, m) </span><span style="color:#859900;">in</span><span style="color:#839496;"> </span><span style="color:#268BD2;">enumerate</span><span style="color:#839496;">([</span><span style="color:#D33682;">0.5</span><span style="color:#839496;">, </span><span style="color:#D33682;">0.1</span><span style="color:#839496;">, </span><span style="color:#D33682;">0.05</span><span style="color:#839496;">]):</span></span>
<span class="line"><span style="color:#839496;"> key </span><span style="color:#859900;">=</span><span style="color:#839496;"> </span><span style="color:#93A1A1;font-weight:bold;">f</span><span style="color:#2AA198;">&quot;metrics_lr</span><span style="color:#CB4B16;">{</span><span style="color:#839496;">lr</span><span style="color:#93A1A1;font-weight:bold;">:0.4f</span><span style="color:#CB4B16;">}</span><span style="color:#2AA198;">_m</span><span style="color:#CB4B16;">{</span><span style="color:#839496;">m</span><span style="color:#93A1A1;font-weight:bold;">:0.4f</span><span style="color:#CB4B16;">}</span><span style="color:#2AA198;">.csv&quot;</span></span>
<span class="line"><span style="color:#839496;"> df </span><span style="color:#859900;">=</span><span style="color:#839496;"> read_table_from_s3(</span><span style="color:#2AA198;">&quot;simplebatch-bucket43879c71-mbqaltx441fu&quot;</span><span style="color:#839496;">, key)</span></span>
<span class="line"><span style="color:#839496;"> grid[i,j] </span><span style="color:#859900;">=</span><span style="color:#839496;"> df[</span><span style="color:#2AA198;">&quot;val_accuracy&quot;</span><span style="color:#839496;">].max()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># [8]</span></span>
<span class="line"><span style="color:#839496;">fig, ax </span><span style="color:#859900;">=</span><span style="color:#839496;"> plt.subplots(figsize</span><span style="color:#859900;">=</span><span style="color:#839496;">(</span><span style="color:#D33682;">6</span><span style="color:#839496;">,</span><span style="color:#D33682;">6</span><span style="color:#839496;">))</span></span>
<span class="line"><span style="color:#839496;">ax.set_aspect(</span><span style="color:#2AA198;">&#39;equal&#39;</span><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;">c </span><span style="color:#859900;">=</span><span style="color:#839496;"> ax.pcolor(grid, edgecolors</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&#39;w&#39;</span><span style="color:#839496;">, linewidths</span><span style="color:#859900;">=</span><span style="color:#D33682;">2</span><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#859900;">for</span><span style="color:#839496;"> i </span><span style="color:#859900;">in</span><span style="color:#839496;"> </span><span style="color:#268BD2;">range</span><span style="color:#839496;">(</span><span style="color:#D33682;">3</span><span style="color:#839496;">):</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">for</span><span style="color:#839496;"> j </span><span style="color:#859900;">in</span><span style="color:#839496;"> </span><span style="color:#268BD2;">range</span><span style="color:#839496;">(</span><span style="color:#D33682;">3</span><span style="color:#839496;">):</span></span>
<span class="line"><span style="color:#839496;"> text </span><span style="color:#859900;">=</span><span style="color:#839496;"> ax.text(j</span><span style="color:#859900;">+</span><span style="color:#D33682;">0.5</span><span style="color:#839496;">, i</span><span style="color:#859900;">+</span><span style="color:#D33682;">0.5</span><span style="color:#839496;">, </span><span style="color:#93A1A1;font-weight:bold;">f</span><span style="color:#2AA198;">&quot;</span><span style="color:#CB4B16;">{</span><span style="color:#839496;">grid[i, j]</span><span style="color:#93A1A1;font-weight:bold;">:0.1f</span><span style="color:#CB4B16;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> ha</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;center&quot;</span><span style="color:#839496;">, va</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;center&quot;</span><span style="color:#839496;">, color</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;w&quot;</span><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># [5]</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> pandas </span><span style="color:#859900;">as</span><span style="color:#657B83;"> pd</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> numpy </span><span style="color:#859900;">as</span><span style="color:#657B83;"> np</span></span>
<span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> io</span></span>
<span class="line"><span style="color:#859900;">from</span><span style="color:#657B83;"> matplotlib </span><span style="color:#859900;">import</span><span style="color:#657B83;"> pyplot </span><span style="color:#859900;">as</span><span style="color:#657B83;"> plt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># [6]</span></span>
<span class="line"><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">read_table_from_s3</span><span style="color:#657B83;">(bucket_name, key, profile_name</span><span style="color:#859900;">=</span><span style="color:#B58900;">None</span><span style="color:#657B83;">):</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">if</span><span style="color:#657B83;"> profile_name </span><span style="color:#859900;">is</span><span style="color:#657B83;"> </span><span style="color:#B58900;">None</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> session </span><span style="color:#859900;">=</span><span style="color:#657B83;"> boto3.Session()</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">else</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> session </span><span style="color:#859900;">=</span><span style="color:#657B83;"> boto3.Session(profile_name</span><span style="color:#859900;">=</span><span style="color:#657B83;">profile_name)</span></span>
<span class="line"><span style="color:#657B83;"> s3 </span><span style="color:#859900;">=</span><span style="color:#657B83;"> session.resource(</span><span style="color:#2AA198;">&quot;s3&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> bucket </span><span style="color:#859900;">=</span><span style="color:#657B83;"> s3.Bucket(bucket_name)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> obj </span><span style="color:#859900;">=</span><span style="color:#657B83;"> bucket.Object(key).get().get(</span><span style="color:#2AA198;">&quot;Body&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> df </span><span style="color:#859900;">=</span><span style="color:#657B83;"> pd.read_csv(obj)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">return</span><span style="color:#657B83;"> df</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># [7]</span></span>
<span class="line"><span style="color:#657B83;">grid </span><span style="color:#859900;">=</span><span style="color:#657B83;"> np.zeros((</span><span style="color:#D33682;">3</span><span style="color:#657B83;">,</span><span style="color:#D33682;">3</span><span style="color:#657B83;">))</span></span>
<span class="line"><span style="color:#859900;">for</span><span style="color:#657B83;"> (i, lr) </span><span style="color:#859900;">in</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">enumerate</span><span style="color:#657B83;">([</span><span style="color:#D33682;">0.1</span><span style="color:#657B83;">, </span><span style="color:#D33682;">0.01</span><span style="color:#657B83;">, </span><span style="color:#D33682;">0.001</span><span style="color:#657B83;">]):</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">for</span><span style="color:#657B83;"> (j, m) </span><span style="color:#859900;">in</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">enumerate</span><span style="color:#657B83;">([</span><span style="color:#D33682;">0.5</span><span style="color:#657B83;">, </span><span style="color:#D33682;">0.1</span><span style="color:#657B83;">, </span><span style="color:#D33682;">0.05</span><span style="color:#657B83;">]):</span></span>
<span class="line"><span style="color:#657B83;"> key </span><span style="color:#859900;">=</span><span style="color:#657B83;"> </span><span style="color:#586E75;font-weight:bold;">f</span><span style="color:#2AA198;">&quot;metrics_lr</span><span style="color:#CB4B16;">{</span><span style="color:#657B83;">lr</span><span style="color:#586E75;font-weight:bold;">:0.4f</span><span style="color:#CB4B16;">}</span><span style="color:#2AA198;">_m</span><span style="color:#CB4B16;">{</span><span style="color:#657B83;">m</span><span style="color:#586E75;font-weight:bold;">:0.4f</span><span style="color:#CB4B16;">}</span><span style="color:#2AA198;">.csv&quot;</span></span>
<span class="line"><span style="color:#657B83;"> df </span><span style="color:#859900;">=</span><span style="color:#657B83;"> read_table_from_s3(</span><span style="color:#2AA198;">&quot;simplebatch-bucket43879c71-mbqaltx441fu&quot;</span><span style="color:#657B83;">, key)</span></span>
<span class="line"><span style="color:#657B83;"> grid[i,j] </span><span style="color:#859900;">=</span><span style="color:#657B83;"> df[</span><span style="color:#2AA198;">&quot;val_accuracy&quot;</span><span style="color:#657B83;">].max()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># [8]</span></span>
<span class="line"><span style="color:#657B83;">fig, ax </span><span style="color:#859900;">=</span><span style="color:#657B83;"> plt.subplots(figsize</span><span style="color:#859900;">=</span><span style="color:#657B83;">(</span><span style="color:#D33682;">6</span><span style="color:#657B83;">,</span><span style="color:#D33682;">6</span><span style="color:#657B83;">))</span></span>
<span class="line"><span style="color:#657B83;">ax.set_aspect(</span><span style="color:#2AA198;">&#39;equal&#39;</span><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;">c </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ax.pcolor(grid, edgecolors</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&#39;w&#39;</span><span style="color:#657B83;">, linewidths</span><span style="color:#859900;">=</span><span style="color:#D33682;">2</span><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#859900;">for</span><span style="color:#657B83;"> i </span><span style="color:#859900;">in</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">range</span><span style="color:#657B83;">(</span><span style="color:#D33682;">3</span><span style="color:#657B83;">):</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">for</span><span style="color:#657B83;"> j </span><span style="color:#859900;">in</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">range</span><span style="color:#657B83;">(</span><span style="color:#D33682;">3</span><span style="color:#657B83;">):</span></span>
<span class="line"><span style="color:#657B83;"> text </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ax.text(j</span><span style="color:#859900;">+</span><span style="color:#D33682;">0.5</span><span style="color:#657B83;">, i</span><span style="color:#859900;">+</span><span style="color:#D33682;">0.5</span><span style="color:#657B83;">, </span><span style="color:#586E75;font-weight:bold;">f</span><span style="color:#2AA198;">&quot;</span><span style="color:#CB4B16;">{</span><span style="color:#657B83;">grid[i, j]</span><span style="color:#586E75;font-weight:bold;">:0.1f</span><span style="color:#CB4B16;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> ha</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;center&quot;</span><span style="color:#657B83;">, va</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;center&quot;</span><span style="color:#657B83;">, color</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;w&quot;</span><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br></div></div><p> <a href="#fig_grid_search_result">figure_title</a> </p><p><img src="`+Cs+'" alt=""></p><p> 0.1 0.1 </p><p></p><p> 0.1 100 </p><p> MNIST 60,000 48,000 12,000 k (<strong>k-fold cross-validation</strong>) </p><p> CNN MNIST AWS Batch EC2 EC2 使</p><h2 id="-2" tabindex="-1"> <a class="header-anchor" href="#-2" aria-label="Permalink to &quot;&quot;"></a></h2><p> ECR Docker ( <code>cdk destroy</code> CloudFormation )</p><p>ECR Docker image ECR <code>DELETE</code> (<a href="#fig_delete_ecr">figure_title</a>)</p><p><img src="'+Ss+'" alt="ECR Docker image "></p><p> AWS CLI (<code>XXXX</code> ECR )</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ecr</span><span style="color:#839496;"> </span><span style="color:#2AA198;">batch-delete-image</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--repository-name</span><span style="color:#839496;"> </span><span style="color:#2AA198;">XXXX</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--image-ids</span><span style="color:#839496;"> </span><span style="color:#2AA198;">imageTag=latest</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ecr</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">batch-delete-image</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--repository-name</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">XXXX</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--image-ids</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">imageTag=latest</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>image </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p><a href="#sec:batch_development_and_debug">???</a> === </p><p> AWS Batch 使 </p><p> GPU <a href="#fig:cloud_development">figure_title</a> <a href="#sec_jupyter_and_deep_learning">Hands-on #2: AWS </a> GPU EC2 Jupyter Notebook Jupyter Docker EC2 <code>docker run</code> <a href="#sec_aws_batch">Hands-on #4: AWS Batch 使</a> AWS Batch <a href="#sec_fargate_qabot">Hands-on #3: AWS </a> </p><p>沿 MNIST Jupyter Notebook 使 Docker AWS Batch </p><p><img src="'+ws+'" alt=""></p><h2 id="-1" tabindex="-1"> <a class="header-anchor" href="#-1" aria-label="Permalink to &quot;&quot;"></a></h2><p> </p><p> GPU EC2 使 MNIST (<a href="#sec_jupyter_and_deep_learning">Hands-on #2: AWS </a>)</p><p> Docker ECS (<a href="#sec_docker_introduction">Docker </a>) (<a href="#sec_fargate_qabot">Hands-on #3: AWS </a>) </p><p> <a href="#sec_aws_batch">Hands-on #4: AWS Batch 使</a> AWS Batch </p><p> SNS </p><h1 id="web-" tabindex="-1">Web <a class="header-anchor" href="#web-" aria-label="Permalink to &quot;Web &quot;"></a></h1><p> EC2, ECS, Fargate, Batch <strong>使</strong> <strong>使</strong></p><p>使 </p><p> </p><h2 id="--twitter-" tabindex="-1"> Twitter <a class="header-anchor" href="#--twitter-" aria-label="Permalink to &quot; Twitter &quot;"></a></h2><p> Twitter, Facebook, YouTube </p><p>HTTP <a href="https://twitter.com" target="_blank" rel="noreferrer">Twitter</a> <a href="#fig:web_server">figure_title</a> </p><p><img src="'+Ps+'" alt=" Web "></p><p> <strong>HTTP (Hypertext Transfer Protocol)</strong> 使 HTTP <strong>HTTPS (HTTPS (Hypertext Transfer Protocol Secure))</strong> HTTP(S) <strong>HTML (Hyptertext Markup Language)</strong> <strong>CSS (Cascading Style Sheets)</strong> <strong>JavaScript (JS)</strong> Twitter (: ) <strong>API (Application Programming Interface)</strong> JavaScript API <strong>JSON (JavaScript Object Notation)</strong> API HTML 稿 API </p><h2 id="rest-api" tabindex="-1">REST API <a class="header-anchor" href="#rest-api" aria-label="Permalink to &quot;REST API&quot;"></a></h2><p>API (Application Programming Interface) API API 使</p><p> <strong>REST (Representational State Transfer)</strong> API 使 REST API <strong>REST API</strong> <strong>RESTful API</strong> </p><p>REST API <a href="#rest_api">figure_title</a> <strong>Method</strong> <strong>URI (Universal Resource Identifier)</strong> </p><p><img src="'+Es+'" alt="REST API"></p><p>Method () <strong>&quot;&quot;</strong> HTTP 9 (verb) 使 <code>GET</code>, <code>POST</code>, <code>PUT</code>, <code>PATCH</code>, <code>DELETE</code> 5 使 (<a href="#tab:rest_api_methods">table_title</a>) 5 <strong>CRUD</strong> (create, read, update, and delete) </p><table><caption>REST API Methods</caption><colgroup><col style="width:25%;"><col style="width:75%;"></colgroup><thead><tr class="header"><th></th><th></th></tr></thead><tbody><tr class="odd"><td><p>GET</p></td><td><p></p></td></tr><tr class="even"><td><p>POST</p></td><td><p></p></td></tr><tr class="odd"><td><p>PUT</p></td><td><p></p></td></tr><tr class="even"><td><p>PATCH</p></td><td><p></p></td></tr><tr class="odd"><td><p>DELETE</p></td><td><p></p></td></tr></tbody></table><p> URI <strong>&quot;&quot;</strong> <strong></strong> URI http https / () <a href="#rest_api">figure_title</a> <code>https://api.twitter.com</code> <code>/1.1/status/home_timeline</code> (GET) ( <code>1.1</code> API ) API </p><p>REST API <a href="#tab:rest_api_methods">table_title</a> HTTP (OPTIONS, TRACE ) </p><p> URI 使 <code>DELETE</code> 使 Twitter API API <code>POST statuses/destroy/:id</code> API API 調</p><p>REST 2000 API API <a href="https://graphql.org/" target="_blank" rel="noreferrer">GraphQL</a> API GraphQL Facebook GraghQL Foundation GraphQL 使 REST </p><h2 id="twitter-api" tabindex="-1">Twitter API <a class="header-anchor" href="#twitter-api" aria-label="Permalink to &quot;Twitter API&quot;"></a></h2><p> API Twitter API Twitter API <a href="https://developer.twitter.com/en/docs/api-reference-index" target="_blank" rel="noreferrer">Twitter Developer Documentation</a> API <a href="#tab_twitter_api">table_title</a> </p><table><caption>Twitter API</caption><colgroup><col style="width:50%;"><col style="width:50%;"></colgroup><thead><tr class="header"><th></th><th></th></tr></thead><tbody><tr class="odd"><td><p><code>GET statuses/home_timeline</code></p></td><td><p></p></td></tr><tr class="even"><td><p><code>GET statuses/show/:id</code></p></td><td><p><code>:id</code> </p></td></tr><tr class="odd"><td><p><code>GET search</code></p></td><td><p></p></td></tr><tr class="even"><td><p><code>POST statuses/update</code></p></td><td><p>稿</p></td></tr><tr class="odd"><td><p><code>POST media/upload</code></p></td><td><p></p></td></tr><tr class="even"><td><p><code>POST statuses/destroy/:id</code></p></td><td><p><code>:id</code> </p></td></tr><tr class="odd"><td><p><code>POST statuses/retweet/:id</code></p></td><td><p><code>:id</code> </p></td></tr><tr class="even"><td><p><code>POST statuses/unretweet/:id</code></p></td><td><p><code>:id</code> </p></td></tr><tr class="odd"><td><p><code>POST favorites/create</code></p></td><td><p>&quot;&quot;</p></td></tr><tr class="even"><td><p><code>POST favorites/destroy</code></p></td><td><p>&quot;&quot;</p></td></tr></tbody></table><p> API Twitter </p><p> Twitter <code>GET statuses/home_timeline</code> API JSON <code>id</code>, <code>text</code>, <code>user</code>, <code>coordinates</code>, <code>entities</code> <code>id</code> ID <code>text</code> <code>user</code> 稿 URL JSON <code>coordinates</code> <code>entities</code> () <code>GET statuses/home_timeline</code> () ID <code>GET statuses/show/:id</code> <code>:id</code> </p><p> <code>GET search</code> API 使 API API <code>GET statuses/home_timeline</code> JSON </p><p>稿 <code>POST statuses/update</code> <code>POST statuses/update</code> ID <code>POST media/upload</code> 使 <code>POST statuses/destroy/:id</code> </p><p> <code>POST statuses/retweet/:id</code> <code>POST statuses/unretweet/:id</code> <code>:id</code> API <code>POST favorites/create</code><code>POST favorites/destroy</code> 使&quot;&quot;</p><p> Twitter API </p><p> API </p><h1 id="serverless-architecture" tabindex="-1">Serverless architecture <a class="header-anchor" href="#serverless-architecture" aria-label="Permalink to &quot;Serverless architecture&quot;"></a></h1><p> (Serverless architecture) (Serverless computing) AWS 2014 <a href="https://aws.amazon.com/lambda/" target="_blank" rel="noreferrer">Lamba</a> Google Microsoft </p><p>Serverless &quot;serverful&quot; </p><h2 id="serverful--" tabindex="-1">Serverful () <a class="header-anchor" href="#serverful--" aria-label="Permalink to &quot;Serverful ()&quot;"></a></h2><p> <a href="#serverful">figure_title</a> API API API API AWS EC2 </p><p> <strong>Load balancing</strong> <strong>Load balancer</strong> </p><p> <strong></strong> <strong>scale-out</strong> <strong>scale-in</strong> API <strong>調</strong> </p><p>API A 3000 512MB B 1000 128MB (使 = )</p><p><img src="'+Is+'" alt="Serverful "></p><h2 id="serverless-" tabindex="-1">Serverless <a class="header-anchor" href="#serverless-" aria-label="Permalink to &quot;Serverless &quot;"></a></h2><p><a href="#chap_serverful_cloud">Serverful ()</a> </p><p> <strong></strong><strong></strong> </p><p> serverful <strong></strong> EC2 使<strong> (CPU RAM) </strong> <strong> 0% 100%使</strong></p><p> <strong></strong> <strong></strong> <a href="#serverless">figure_title</a> </p><p><img src="'+zs+'" alt=" Serverless "></p><p> <strong>使 () </strong> </p><p> </p><p>()<strong></strong> </p><p><strong></strong> 使 </p><h2 id="" tabindex="-1"> <a class="header-anchor" href="#" aria-label="Permalink to &quot;&quot;"></a></h2><p> AWS <strong>Lambda</strong>, <strong>S3</strong>, <strong>DynamoDB</strong> (<a href="#fig:serverless_logos">figure_title</a>) LambdaS3DynamoDB <a href="#sec_intro_serverless">Hands-on #5: </a> </p><p><img src="'+xs+'" alt="Lambda, S3, DynamoDB "></p><h3 id="lambda" tabindex="-1">Lambda <a class="header-anchor" href="#lambda" aria-label="Permalink to &quot;Lambda&quot;"></a></h3><p>AWS <a href="https://aws.amazon.com/lambda/" target="_blank" rel="noreferrer">Lambda</a> Lambda 使 <a href="#lambda_workflow">figure_title</a> Lambda Python, Node.js, Ruby Lambda (Function) invoke Lambda Lambda invoke () </p><p><img src="'+Ts+'" alt="AWS Lambda"></p><p>Lambda invoke AWS AWS <strong> Lambda </strong> <strong>FaaS (Function as a Service)</strong> </p><p>Lambda 128MB 10240MB 使 () CPU CPU ( RAM CPU AWS ) 100 <a href="#lambda_pricing">table_title</a> Lambda ( <code>ap-north-east1</code> )</p><table><caption>Lambda </caption><colgroup><col style="width:50%;"><col style="width:50%;"></colgroup><thead><tr class="header"><th>Memory (MB)</th><th>Price per 100ms</th></tr></thead><tbody><tr class="odd"><td><p>128</p></td><td><p>$0.0000002083</p></td></tr><tr class="even"><td><p>512</p></td><td><p>$0.0000008333</p></td></tr><tr class="odd"><td><p>1024</p></td><td><p>$0.0000016667</p></td></tr><tr class="even"><td><p>3008</p></td><td><p>$0.0000048958</p></td></tr></tbody></table><p> $0.2 128MB 使 200 100 0.0000002083 * 2 * 10^6 + 0.2 = $0.6 200 100 $0.6 0 </p><p>Lambda Lambda </p><p> Lambda DynamoDB </p><h3 id="-s3" tabindex="-1">: S3 <a class="header-anchor" href="#-s3" aria-label="Permalink to &quot;: S3&quot;"></a></h3><p></p><p> () OS CPU (ZFS 使) (<a href="#fig:s3_vs_filesystem">figure_title</a>)</p><p><a href="https://aws.amazon.com/s3/" target="_blank" rel="noreferrer">Simple Storage Service (S3)</a> (<a href="#fig:s3_vs_filesystem">figure_title</a>) S3 OS &quot; API OS CPU API S3 () </p><p><img src="'+Ws+'" alt="S3 "></p><p>S3 <a href="#tab:s3_pricing">table_title</a> (<code>us-east-1</code> <a href="https://aws.amazon.com/s3/pricing/?nc=sn&amp;loc=4" target="_blank" rel="noreferrer"> &quot;Amazon S3 pricing&quot;</a> )</p><table><caption>S3 </caption><colgroup><col style="width:50%;"><col style="width:50%;"></colgroup><thead><tr class="header"><th></th><th></th></tr></thead><tbody><tr class="odd"><td><p>Data storage (First 50TB)</p></td><td><p>$0.023 per GB per month</p></td></tr><tr class="even"><td><p>PUT, COPY, POST, LIST requests (per 1,000 requests)</p></td><td><p>$0.005</p></td></tr><tr class="odd"><td><p>GET, SELECT, and all other requests (per 1,000 requests)</p></td><td><p>$0.0004</p></td></tr><tr class="even"><td><p>Data Transfer IN To Amazon S3 From Internet</p></td><td><p>$0</p></td></tr><tr class="odd"><td><p>Data Transfer OUT From Amazon S3 To Internet</p></td><td><p>$0.09 per GB</p></td></tr></tbody></table><p> $0.025 per GB 1000GB S3 $25 <code>PUT</code>, <code>COPY</code>, <code>POST</code> (=) 1000 $0.005 <code>GET</code>, <code>SELECT</code> (=) 1000 $0.0004 S3 S3 (data-out) $0.09 per GB S3 (data-in) AWS Region (Lambda EC2 ) AWS </p><h3 id="-dynamodb" tabindex="-1">: DynamoDB <a class="header-anchor" href="#-dynamodb" aria-label="Permalink to &quot;: DynamoDB&quot;"></a></h3><p></p><p> Web <a href="https://www.mysql.com/" target="_blank" rel="noreferrer">MySQL</a>, <a href="https://www.postgresql.org/" target="_blank" rel="noreferrer">PostgreSQL</a>, <a href="https://www.mongodb.com/" target="_blank" rel="noreferrer">MongoDB</a> </p><p> CPU CPU <a href="#chap_serverful_cloud">Serverful ()</a> </p><p><a href="https://aws.amazon.com/dynamodb/" target="_blank" rel="noreferrer">DynamoDB</a> AWS API S3 DynamoDB </p><p>DynamoDB &quot;On-demand Capacity&quot; 使 <a href="#tab:dynamodb_pricing">table_title</a> (<code>us-east-1</code> <a href="https://aws.amazon.com/dynamodb/pricing/on-demand/" target="_blank" rel="noreferrer"> &quot;Pricing for On-Demand Capacity&quot;</a> )</p><table><caption>DynamoDB </caption><colgroup><col style="width:50%;"><col style="width:50%;"></colgroup><thead><tr class="header"><th></th><th></th></tr></thead><tbody><tr class="odd"><td><p>Write request units</p></td><td><p>$1.25 per million write request units</p></td></tr><tr class="even"><td><p>Read request units</p></td><td><p>$0.25 per million read request units</p></td></tr><tr class="odd"><td><p>Data storage</p></td><td><p>$0.25 per GB-month</p></td></tr></tbody></table><p>DynamoDB write request unit read request unit 1kB 1 write request unit 4kB 1 read request unit ( <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html" target="_blank" rel="noreferrer"> &quot;Read/Write Capacity Mode&quot;</a> ) write request units 100 $1.25, read request units 100 $0.25 $0.25 per GB DynamoDB GB S3 10 DynamoDB data-indata-out $0 </p><h3 id="" tabindex="-1"> <a class="header-anchor" href="#" aria-label="Permalink to &quot;&quot;"></a></h3><p> Lambda, S3, DynamoDB 使 </p><ul><li><p><a href="https://aws.amazon.com/api-gateway/" target="_blank" rel="noreferrer">API Gateway</a>: API <a href="#sec_bashoutter">Hands-on #6: Bashoutter</a> </p></li><li><p><a href="https://aws.amazon.com/fargate/" target="_blank" rel="noreferrer">Fargate</a>: <a href="#sec_fargate_qabot">Hands-on #3: AWS </a> Fargate Lambda Lambda CPU </p></li><li><p><a href="https://aws.amazon.com/sns/" target="_blank" rel="noreferrer">Simple Notification Service (SNS)</a>: </p></li><li><p><a href="https://aws.amazon.com/step-functions/" target="_blank" rel="noreferrer">Step Functions</a>: </p></li></ul><p><strong></strong></p><p> NO </p><p>調</p><p> AWS Google serverful </p><p> </p><ul><li><a href="https://arxiv.org/abs/1812.03651" target="_blank" rel="noreferrer">Hellerstein et al., &quot;Serverless Computing: One Step Forward, Two Steps Back&quot; arXiv (2018)</a></li></ul><h1 id="hands-on-5-" tabindex="-1">Hands-on #5: <a class="header-anchor" href="#hands-on-5-" aria-label="Permalink to &quot;Hands-on \\#5: &quot;"></a></h1><p> 使 Lambda, S3, DynamoDB </p><h2 id="lambda-" tabindex="-1">Lambda <a class="header-anchor" href="#lambda-" aria-label="Permalink to &quot;Lambda &quot;"></a></h2><p> Lambda GitHub <a href="https://github.com/andatoshiki/toshiki-notebooktree/main/handson/serverless/lambda" target="_blank" rel="noreferrer">handson/serverless/lambda</a> </p><p>使 <a href="#fig:lambda_deploy">figure_title</a> STEP 1 AWS CDK 使 Python Lambda STEP 2 Invoke API 使 Lambda Lambda </p><p><img src="'+$s+`" alt="Lambda "></p><p> <a href="https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&amp;all-free-tier.sort-order=asc" target="_blank" rel="noreferrer">AWS Lambda </a> </p><p><a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/serverless/lambda/app.py" target="_blank" rel="noreferrer">app.py</a> </p><div class="language-py vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">py</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#CB4B16;">FUNC</span><span style="color:#839496;"> </span><span style="color:#859900;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;&quot;&quot;</span></span>
<span class="line"><span style="color:#2AA198;">import time</span></span>
<span class="line"><span style="color:#2AA198;">from random import choice, randint</span></span>
<span class="line"><span style="color:#2AA198;">def handler(event, context):</span></span>
<span class="line"><span style="color:#2AA198;"> time.sleep(randint(2,5))</span></span>
<span class="line"><span style="color:#2AA198;"> sushi = [&quot;salmon&quot;, &quot;tuna&quot;, &quot;squid&quot;]</span></span>
<span class="line"><span style="color:#2AA198;"> message = &quot;Welcome to Cloud Sushi. Your order is &quot; + choice(sushi)</span></span>
<span class="line"><span style="color:#2AA198;"> print(message)</span></span>
<span class="line"><span style="color:#2AA198;"> return message</span></span>
<span class="line"><span style="color:#2AA198;">&quot;&quot;&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-weight:bold;">class</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">SimpleLambda</span><span style="color:#839496;">(</span><span style="color:#6C71C4;">core</span><span style="color:#839496;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#839496;">):</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#839496;">, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs) -&gt; </span><span style="color:#B58900;">None</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">super</span><span style="color:#839496;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> handler </span><span style="color:#859900;">=</span><span style="color:#839496;"> _lambda.Function(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&#39;LambdaHandler&#39;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> runtime</span><span style="color:#859900;">=</span><span style="color:#839496;">_lambda.Runtime.</span><span style="color:#CB4B16;">PYTHON_3_7</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> code</span><span style="color:#859900;">=</span><span style="color:#839496;">_lambda.Code.from_inline(</span><span style="color:#CB4B16;">FUNC</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> handler</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;index.handler&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> memory_size</span><span style="color:#859900;">=</span><span style="color:#D33682;">128</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> timeout</span><span style="color:#859900;">=</span><span style="color:#839496;">core.Duration.seconds(</span><span style="color:#D33682;">10</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> dead_letter_queue_enabled</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#CB4B16;">FUNC</span><span style="color:#657B83;"> </span><span style="color:#859900;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;&quot;&quot;</span></span>
<span class="line"><span style="color:#2AA198;">import time</span></span>
<span class="line"><span style="color:#2AA198;">from random import choice, randint</span></span>
<span class="line"><span style="color:#2AA198;">def handler(event, context):</span></span>
<span class="line"><span style="color:#2AA198;"> time.sleep(randint(2,5))</span></span>
<span class="line"><span style="color:#2AA198;"> sushi = [&quot;salmon&quot;, &quot;tuna&quot;, &quot;squid&quot;]</span></span>
<span class="line"><span style="color:#2AA198;"> message = &quot;Welcome to Cloud Sushi. Your order is &quot; + choice(sushi)</span></span>
<span class="line"><span style="color:#2AA198;"> print(message)</span></span>
<span class="line"><span style="color:#2AA198;"> return message</span></span>
<span class="line"><span style="color:#2AA198;">&quot;&quot;&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-weight:bold;">class</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">SimpleLambda</span><span style="color:#657B83;">(</span><span style="color:#6C71C4;">core</span><span style="color:#657B83;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#657B83;">):</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#657B83;">, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs) -&gt; </span><span style="color:#B58900;">None</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">super</span><span style="color:#657B83;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> handler </span><span style="color:#859900;">=</span><span style="color:#657B83;"> _lambda.Function(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&#39;LambdaHandler&#39;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> runtime</span><span style="color:#859900;">=</span><span style="color:#657B83;">_lambda.Runtime.</span><span style="color:#CB4B16;">PYTHON_3_7</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> code</span><span style="color:#859900;">=</span><span style="color:#657B83;">_lambda.Code.from_inline(</span><span style="color:#CB4B16;">FUNC</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> handler</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;index.handler&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> memory_size</span><span style="color:#859900;">=</span><span style="color:#D33682;">128</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> timeout</span><span style="color:#859900;">=</span><span style="color:#657B83;">core.Duration.seconds(</span><span style="color:#D33682;">10</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> dead_letter_queue_enabled</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br></div></div><ul><li><p> Lambda 2-5 [&quot;salmon&quot;, &quot;tuna&quot;, &quot;squid&quot;] &quot;Welcome to Cloud Sushi. Your order is XXXX&quot; (XXXX 寿) </p></li><li><p> Lambda &lt;1&gt; </p><ul><li><p><code>runtime=_lambda.Runtime.PYTHON_3_7</code>: Python3.7 使 Python3.7 Node.js, Java, Ruby, Go </p></li><li><p><code>code=_lambda.Code.from_inline(FUNC)</code>: <code>FUNC=...</code> </p></li><li><p><code>handler=&quot;index.handler&quot;</code>: <code>handler</code> </p></li><li><p><code>memory_size=128</code>: 128MB 使</p></li><li><p><code>timeout=core.Duration.seconds(10)</code> 10 10 </p></li><li><p><code>dead_letter_queue_enabled=True</code>: </p></li></ul></li></ul><p> Lambda </p><h3 id="" tabindex="-1"> <a class="header-anchor" href="#" aria-label="Permalink to &quot;&quot;"></a></h3><p> (<code>#</code> ) 1, 2 (<a href="#aws_cli_install">AWS CLI </a>)</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># </span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cd</span><span style="color:#839496;"> </span><span style="color:#2AA198;">handson/serverless/lambda</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># venv を作成し依存ライブラリのインストールを行う</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python3</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#839496;"> </span><span style="color:#2AA198;">venv</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">source</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pip</span><span style="color:#839496;"> </span><span style="color:#2AA198;">install</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#839496;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># デプロイを実行</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">deploy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># </span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cd</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">handson/serverless/lambda</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># venv を作成し依存ライブラリのインストールを行う</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python3</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">venv</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">source</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pip</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">install</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># デプロイを実行</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">deploy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p> <a href="#handson_04_lambda_cdk_output">figure_title</a> <code>SimpleLambda.FunctionName = XXXX</code> XXXX 使</p><p><img src="`+Ls+'" alt="CDK"></p><p>AWS Lambda <a href="#handson_04_lambda_console_func_list">figure_title</a> Lambda </p><p><img src="'+Gs+'" alt="Lambda - "></p><p> <code>SimpleLambda</code> <a href="#handson_04_lambda_console_func_detail">figure_title</a> Python </p><p><img src="'+Ns+`" alt="Lambda - "></p><p>Lambda Lambda (<a href="#handson_04_lambda_console_func_detail">figure_title</a>) CDK </p><h3 id="lambda-" tabindex="-1">Lambda <a class="header-anchor" href="#lambda-" aria-label="Permalink to &quot;Lambda &quot;"></a></h3><p> Lambda (invoke) AWS API 使 <a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/serverless/lambda/invoke_one.py" target="_blank" rel="noreferrer">handson/serverless/lambda/invoke_one.py</a> </p><p>Lambda <code>XXXX</code> <code>SimpleLambda.FunctionName = XXXX</code> XXXX </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">invoke_one.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">XXXX</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">invoke_one.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">XXXX</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> <code>&quot;Welcome to Cloud Sushi. Your order is salmon&quot;</code> 寿 寿</p><p> Lambda 100 <a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/serverless/lambda/invoke_many.py" target="_blank" rel="noreferrer">handson/serverless/lambda/invoke_many.py</a> 使</p><p> XXXX <code>100</code> 100 </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">invoke_many.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">XXXX</span><span style="color:#839496;"> </span><span style="color:#D33682;">100</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">invoke_many.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">XXXX</span><span style="color:#657B83;"> </span><span style="color:#D33682;">100</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p></p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">....................................................................................................</span></span>
<span class="line"><span style="color:#268BD2;">Submitted</span><span style="color:#839496;"> </span><span style="color:#D33682;">100</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tasks</span><span style="color:#839496;"> </span><span style="color:#2AA198;">to</span><span style="color:#839496;"> </span><span style="color:#2AA198;">Lambda!</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">....................................................................................................</span></span>
<span class="line"><span style="color:#268BD2;">Submitted</span><span style="color:#657B83;"> </span><span style="color:#D33682;">100</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tasks</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">to</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">Lambda!</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>100 <a href="#handson_04_lambda_console_func_detail">figure_title</a> &quot;Monitoring&quot; <a href="#handson_04_lambda_console_monitoring">figure_title</a> </p><p><img src="`+Us+'" alt="Lambda - "></p><p><a href="#handson_04_lambda_console_monitoring">figure_title</a> </p><p><a href="#handson_04_lambda_console_monitoring">figure_title</a> &quot;Invocations&quot; 100 &quot;Concurrent executions&quot; 96 96 ( 100 )</p><p> Lambda 使</p><p> serverful 調</p><p> 1000 Lambda Lambda </p><h3 id="-3" tabindex="-1"> <a class="header-anchor" href="#-3" aria-label="Permalink to &quot;&quot;"></a></h3><p> </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><h2 id="dynamodb-" tabindex="-1">DynamoDB <a class="header-anchor" href="#dynamodb-" aria-label="Permalink to &quot;DynamoDB &quot;"></a></h2><p> DynamoDB GitHub <a href="https://github.com/andatoshiki/toshiki-notebooktree/main/handson/serverless/dynamodb" target="_blank" rel="noreferrer">/handson/serverless/dynamodb</a> </p><p>使 <a href="#fig:dynamodb_deploy">figure_title</a> STEP 1 AWS CDK 使 DynamoDB STEP 2 API 使</p><p><img src="'+Rs+`" alt="DynamoDB "></p><p> <a href="https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&amp;all-free-tier.sort-order=asc" target="_blank" rel="noreferrer">AWS DynamoDB </a> </p><p><a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/serverless/dynamodb/app.py" target="_blank" rel="noreferrer">handson/serverless/dynamodb/app.py</a> </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#93A1A1;font-weight:bold;">class</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">SimpleDynamoDb</span><span style="color:#839496;">(</span><span style="color:#6C71C4;">core</span><span style="color:#839496;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#839496;">):</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#839496;">, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs) -&gt; </span><span style="color:#B58900;">None</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">super</span><span style="color:#839496;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> table </span><span style="color:#859900;">=</span><span style="color:#839496;"> ddb.Table(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;SimpleTable&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> partition_key</span><span style="color:#859900;">=</span><span style="color:#839496;">ddb.Attribute(</span></span>
<span class="line"><span style="color:#839496;"> name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;item_id&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> type</span><span style="color:#859900;">=</span><span style="color:#839496;">ddb.AttributeType.</span><span style="color:#CB4B16;">STRING</span></span>
<span class="line"><span style="color:#839496;"> ),</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> billing_mode</span><span style="color:#859900;">=</span><span style="color:#839496;">ddb.BillingMode.</span><span style="color:#CB4B16;">PAY_PER_REQUEST</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#839496;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span></span>
<span class="line"><span style="color:#839496;"> )</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#586E75;font-weight:bold;">class</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">SimpleDynamoDb</span><span style="color:#657B83;">(</span><span style="color:#6C71C4;">core</span><span style="color:#657B83;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#657B83;">):</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#657B83;">, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs) -&gt; </span><span style="color:#B58900;">None</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">super</span><span style="color:#657B83;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> table </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ddb.Table(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;SimpleTable&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> partition_key</span><span style="color:#859900;">=</span><span style="color:#657B83;">ddb.Attribute(</span></span>
<span class="line"><span style="color:#657B83;"> name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;item_id&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> type</span><span style="color:#859900;">=</span><span style="color:#657B83;">ddb.AttributeType.</span><span style="color:#CB4B16;">STRING</span></span>
<span class="line"><span style="color:#657B83;"> ),</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> billing_mode</span><span style="color:#859900;">=</span><span style="color:#657B83;">ddb.BillingMode.</span><span style="color:#CB4B16;">PAY_PER_REQUEST</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#657B83;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p> DynamoDB </p><ul><li><p><code>partition_key</code>: DynamoDB Partition key Partition key () ID Partition key (: Sort Key 使 <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html" target="_blank" rel="noreferrer"> &quot;Core Components of Amazon DynamoDB&quot;</a> ) Partition key Partition key <code>item_id</code> </p></li><li><p><code>billing_mode</code>: <code>ddb.BillingMode.PAY_PER_REQUEST</code> <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.OnDemand" target="_blank" rel="noreferrer">On-demand Capacity Mode</a> DynamoDB <code>PROVISIONED</code> 使</p></li><li><p><code>removal_policy</code>: CloudFormation DynamoDB <code>DESTROY</code> DynamoDB </p></li></ul><h3 id="-1" tabindex="-1"> <a class="header-anchor" href="#-1" aria-label="Permalink to &quot;&quot;"></a></h3><p> (<code>#</code> ) (<a href="#aws_cli_install">AWS CLI </a>)</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># </span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cd</span><span style="color:#839496;"> </span><span style="color:#2AA198;">handson/serverless/dynamodb</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># venv を作成し依存ライブラリのインストールを行う</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python3</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#839496;"> </span><span style="color:#2AA198;">venv</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">source</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pip</span><span style="color:#839496;"> </span><span style="color:#2AA198;">install</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#839496;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># デプロイを実行</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">deploy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># </span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cd</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">handson/serverless/dynamodb</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># venv を作成し依存ライブラリのインストールを行う</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python3</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">venv</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">source</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pip</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">install</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># デプロイを実行</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">deploy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p> <a href="#handson_04_dynamodb_cdk_output">figure_title</a> <code>SimpleDynamoDb.TableName = XXXX</code> XXXX 使</p><p><img src="`+Xs+'" alt="CDK"></p><p>AWS DynamoDB &quot;Tables&quot; <a href="#handson_04_dynamodb_table_list">figure_title</a> </p><p><img src="'+Ms+'" alt="DynamoDB ()"></p><p> <code>SimpleDynamoDb</code> <a href="#handson_04_dynamodb_table_detail">figure_title</a> &quot;Items&quot; </p><p><img src="'+Hs+`" alt="DynamoDB ()"></p><h3 id="" tabindex="-1"> <a class="header-anchor" href="#" aria-label="Permalink to &quot;&quot;"></a></h3><p> <a href="#sec:serverless_dynamodb_deploy"></a> 使 Python <a href="https://boto3.amazonaws.com/v1/documentation/api/latest/index.html" target="_blank" rel="noreferrer">boto3</a> </p><p> <a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/serverless/dynamodb/simple_write.py" target="_blank" rel="noreferrer">simple_write.py</a> </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> boto3</span></span>
<span class="line"><span style="color:#859900;">from</span><span style="color:#839496;"> uuid </span><span style="color:#859900;">import</span><span style="color:#839496;"> uuid4</span></span>
<span class="line"><span style="color:#839496;">ddb </span><span style="color:#859900;">=</span><span style="color:#839496;"> boto3.resource(</span><span style="color:#2AA198;">&#39;dynamodb&#39;</span><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">write_item</span><span style="color:#839496;">(table_name):</span></span>
<span class="line"><span style="color:#839496;"> table </span><span style="color:#859900;">=</span><span style="color:#839496;"> ddb.Table(table_name)</span></span>
<span class="line"><span style="color:#839496;"> table.put_item(</span></span>
<span class="line"><span style="color:#839496;"> Item</span><span style="color:#859900;">=</span><span style="color:#839496;">{</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&#39;item_id&#39;</span><span style="color:#839496;">: </span><span style="color:#859900;">str</span><span style="color:#839496;">(uuid4()),</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&#39;first_name&#39;</span><span style="color:#839496;">: </span><span style="color:#2AA198;">&#39;John&#39;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&#39;last_name&#39;</span><span style="color:#839496;">: </span><span style="color:#2AA198;">&#39;Doe&#39;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&#39;age&#39;</span><span style="color:#839496;">: </span><span style="color:#D33682;">25</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> }</span></span>
<span class="line"><span style="color:#839496;"> )</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> boto3</span></span>
<span class="line"><span style="color:#859900;">from</span><span style="color:#657B83;"> uuid </span><span style="color:#859900;">import</span><span style="color:#657B83;"> uuid4</span></span>
<span class="line"><span style="color:#657B83;">ddb </span><span style="color:#859900;">=</span><span style="color:#657B83;"> boto3.resource(</span><span style="color:#2AA198;">&#39;dynamodb&#39;</span><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">write_item</span><span style="color:#657B83;">(table_name):</span></span>
<span class="line"><span style="color:#657B83;"> table </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ddb.Table(table_name)</span></span>
<span class="line"><span style="color:#657B83;"> table.put_item(</span></span>
<span class="line"><span style="color:#657B83;"> Item</span><span style="color:#859900;">=</span><span style="color:#657B83;">{</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&#39;item_id&#39;</span><span style="color:#657B83;">: </span><span style="color:#859900;">str</span><span style="color:#657B83;">(uuid4()),</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&#39;first_name&#39;</span><span style="color:#657B83;">: </span><span style="color:#2AA198;">&#39;John&#39;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&#39;last_name&#39;</span><span style="color:#657B83;">: </span><span style="color:#2AA198;">&#39;Doe&#39;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&#39;age&#39;</span><span style="color:#657B83;">: </span><span style="color:#D33682;">25</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> }</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p> boto3 <code>dynamodb</code> <code>write_item()</code> DynamoDB ( SimpleDynamoDb-XXXX) <code>put_item()</code> DB <code>item_id</code>, <code>first_name</code>, <code>last_name</code>, <code>age</code> 4 <code>item_id</code> Partition key <a href="https://en.wikipedia.org/wiki/Universally_unique_identifier" target="_blank" rel="noreferrer">UUID4</a> </p><p> <code>simple_write.py</code> &quot;XXXX&quot; (<code>SimpleDynamoDb</code> ) </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">simple_write.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">XXXX</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">simple_write.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">XXXX</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> AWS <a href="#handson_04_dynamodb_table_detail">figure_title</a> <a href="#fig:dynamodb_table_new_item">figure_title</a> </p><p><img src="`+Fs+`" alt="DynamoDB "></p><p>boto3 使 <a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/serverless/dynamodb/simple_read.py" target="_blank" rel="noreferrer">simple_read.py</a> </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#859900;">import</span><span style="color:#839496;"> boto3</span></span>
<span class="line"><span style="color:#839496;">ddb </span><span style="color:#859900;">=</span><span style="color:#839496;"> boto3.resource(</span><span style="color:#2AA198;">&#39;dynamodb&#39;</span><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">scan_table</span><span style="color:#839496;">(table_name):</span></span>
<span class="line"><span style="color:#839496;"> table </span><span style="color:#859900;">=</span><span style="color:#839496;"> ddb.Table(table_name)</span></span>
<span class="line"><span style="color:#839496;"> items </span><span style="color:#859900;">=</span><span style="color:#839496;"> table.scan().get(</span><span style="color:#2AA198;">&quot;Items&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">print</span><span style="color:#839496;">(items)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#859900;">import</span><span style="color:#657B83;"> boto3</span></span>
<span class="line"><span style="color:#657B83;">ddb </span><span style="color:#859900;">=</span><span style="color:#657B83;"> boto3.resource(</span><span style="color:#2AA198;">&#39;dynamodb&#39;</span><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">scan_table</span><span style="color:#657B83;">(table_name):</span></span>
<span class="line"><span style="color:#657B83;"> table </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ddb.Table(table_name)</span></span>
<span class="line"><span style="color:#657B83;"> items </span><span style="color:#859900;">=</span><span style="color:#657B83;"> table.scan().get(</span><span style="color:#2AA198;">&quot;Items&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">print</span><span style="color:#657B83;">(items)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p><code>table.scan().get(&quot;Items&quot;)</code> </p><p> (&quot;XXXX&quot; </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">simple_read.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">XXXX</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">simple_read.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">XXXX</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p></p><h3 id="" tabindex="-1"> <a class="header-anchor" href="#" aria-label="Permalink to &quot;&quot;"></a></h3><p>DynamoDB </p><p> <a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/serverless/dynamodb/batch_rw.py" target="_blank" rel="noreferrer">batch_rw.py</a> </p><p> (XXXX )</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">batch_rw.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">XXXX</span><span style="color:#839496;"> </span><span style="color:#2AA198;">write</span><span style="color:#839496;"> </span><span style="color:#D33682;">1000</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">batch_rw.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">XXXX</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">write</span><span style="color:#657B83;"> </span><span style="color:#D33682;">1000</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> 1000 </p><p> <code>age</code> 1 50 <code>age</code> 2 </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">batch_rw.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">XXXX</span><span style="color:#839496;"> </span><span style="color:#2AA198;">search_under_age</span><span style="color:#839496;"> </span><span style="color:#D33682;">2</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">batch_rw.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">XXXX</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">search_under_age</span><span style="color:#657B83;"> </span><span style="color:#D33682;">2</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> 2 </p><h3 id="-4" tabindex="-1"> <a class="header-anchor" href="#-4" aria-label="Permalink to &quot;&quot;"></a></h3><p>DynamoDB </p><p></p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><h2 id="s3-" tabindex="-1">S3 <a class="header-anchor" href="#s3-" aria-label="Permalink to &quot;S3 &quot;"></a></h2><p> S3 GitHub <a href="https://github.com/andatoshiki/toshiki-notebooktree/main/handson/serverless/s3" target="_blank" rel="noreferrer">handson/serverless/s3</a> </p><p><a href="#fig:s3_deploy">figure_title</a> S3 STEP 1 AWS CDK S3 (Bucket) STEP 2 </p><p><img src="`+Os+`" alt="S3 "></p><p> <a href="https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&amp;all-free-tier.sort-order=asc" target="_blank" rel="noreferrer">S3 </a> </p><p><a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/serverless/s3/app.py" target="_blank" rel="noreferrer">app.py</a> </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#93A1A1;font-weight:bold;">class</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">SimpleS3</span><span style="color:#839496;">(</span><span style="color:#6C71C4;">core</span><span style="color:#839496;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#839496;">):</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#839496;">, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs) -&gt; </span><span style="color:#B58900;">None</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">super</span><span style="color:#839496;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># S3 bucket to store data</span></span>
<span class="line"><span style="color:#839496;"> bucket </span><span style="color:#859900;">=</span><span style="color:#839496;"> s3.Bucket(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;bucket&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#839496;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> auto_delete_objects</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#586E75;font-weight:bold;">class</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">SimpleS3</span><span style="color:#657B83;">(</span><span style="color:#6C71C4;">core</span><span style="color:#657B83;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#657B83;">):</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#657B83;">, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs) -&gt; </span><span style="color:#B58900;">None</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">super</span><span style="color:#657B83;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># S3 bucket to store data</span></span>
<span class="line"><span style="color:#657B83;"> bucket </span><span style="color:#859900;">=</span><span style="color:#657B83;"> s3.Bucket(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;bucket&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#657B83;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> auto_delete_objects</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p><code>s3.Bucket()</code> <code>bucket_name</code> (i.e. AWS ) </p><p> CloudFormation S3 <code>cdk destroy</code> <code>removal_policy=core.RemovalPolicy.DESTROY, auto_delete_objects=True</code> </p><h3 id="-2" tabindex="-1"> <a class="header-anchor" href="#-2" aria-label="Permalink to &quot;&quot;"></a></h3><p> (<code>#</code> ) (<a href="#aws_cli_install">AWS CLI </a>)</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># </span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cd</span><span style="color:#839496;"> </span><span style="color:#2AA198;">handson/serverless/s3</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># venv を作成し依存ライブラリのインストールを行う</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python3</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#839496;"> </span><span style="color:#2AA198;">venv</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">source</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pip</span><span style="color:#839496;"> </span><span style="color:#2AA198;">install</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#839496;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># デプロイを実行</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">deploy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># </span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cd</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">handson/serverless/s3</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># venv を作成し依存ライブラリのインストールを行う</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python3</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">venv</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">source</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pip</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">install</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># デプロイを実行</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">deploy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p> <a href="#fig:s3_deploy_output">figure_title</a> <code>SimpleS3.BucketName = XXXX</code> (使 使</p><p><img src="`+js+`" alt=""></p><h3 id="-1" tabindex="-1"> <a class="header-anchor" href="#-1" aria-label="Permalink to &quot;&quot;"></a></h3><p></p><p> <code>tmp.txt</code> </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">echo</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;Hello world!&quot;</span><span style="color:#839496;"> </span><span style="color:#859900;">&gt;&gt;</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tmp.txt</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">echo</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;Hello world!&quot;</span><span style="color:#657B83;"> </span><span style="color:#859900;">&gt;&gt;</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tmp.txt</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> <a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/serverless/s3/simple_s3.py" target="_blank" rel="noreferrer">simple_s3.py</a> <a href="https://boto3.amazonaws.com/v1/documentation/api/latest/index.html" target="_blank" rel="noreferrer">boto3</a> 使 S3 <code>simple_s3.py</code> 使 <code>tmp.txt</code> <code>XXXX</code> </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">simple_s3.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">XXXX</span><span style="color:#839496;"> </span><span style="color:#2AA198;">upload</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tmp.txt</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">simple_s3.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">XXXX</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">upload</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tmp.txt</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p><code>simple_s3.py</code> </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">upload_file</span><span style="color:#839496;">(bucket_name, filename, key</span><span style="color:#859900;">=</span><span style="color:#B58900;">None</span><span style="color:#839496;">):</span></span>
<span class="line"><span style="color:#839496;"> bucket </span><span style="color:#859900;">=</span><span style="color:#839496;"> s3.Bucket(bucket_name)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">if</span><span style="color:#839496;"> key </span><span style="color:#859900;">is</span><span style="color:#839496;"> </span><span style="color:#B58900;">None</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> key </span><span style="color:#859900;">=</span><span style="color:#839496;"> os.path.basename(filename)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> bucket.upload_file(filename, key)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">upload_file</span><span style="color:#657B83;">(bucket_name, filename, key</span><span style="color:#859900;">=</span><span style="color:#B58900;">None</span><span style="color:#657B83;">):</span></span>
<span class="line"><span style="color:#657B83;"> bucket </span><span style="color:#859900;">=</span><span style="color:#657B83;"> s3.Bucket(bucket_name)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">if</span><span style="color:#657B83;"> key </span><span style="color:#859900;">is</span><span style="color:#657B83;"> </span><span style="color:#B58900;">None</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> key </span><span style="color:#859900;">=</span><span style="color:#657B83;"> os.path.basename(filename)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> bucket.upload_file(filename, key)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p><code>bucket = s3.Bucket(bucket_name)</code> <code>Bucket()</code> <code>upload_file()</code> </p><p>S3 使 <strong>Key</strong> (Path) Key Key S3 <a href="https://en.wikipedia.org/wiki/Object_storage" target="_blank" rel="noreferrer">Object storage</a> <code>--key</code> <code>simple_s3.py</code> Key </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">simple_s3.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">XXXX</span><span style="color:#839496;"> </span><span style="color:#2AA198;">upload</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tmp.txt</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--key</span><span style="color:#839496;"> </span><span style="color:#2AA198;">a/b/tmp.txt</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">simple_s3.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">XXXX</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">upload</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tmp.txt</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--key</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">a/b/tmp.txt</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> <code>a/b/tmp.txt</code> Key </p><p> AWS S3 S3 <code>simples3-bucket</code> (<a href="#fig:s3_bucket_filelist">figure_title</a>)</p><p><img src="`+Vs+`" alt="S3 "></p><p> 2 <code>tmp.txt</code> <code>a/b/tmp.txt</code> S3 Key <strong>&quot;/&quot; ()</strong> <strong></strong></p><p> &quot;/&quot; </p><p> <code>simple_s3.py</code> 使 <code>XXXX</code> </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">simple_s3.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">XXXX</span><span style="color:#839496;"> </span><span style="color:#2AA198;">download</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tmp.txt</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">simple_s3.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">XXXX</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">download</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tmp.txt</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p><code>simple_s3.py</code> </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">download_file</span><span style="color:#839496;">(bucket_name, key, filename</span><span style="color:#859900;">=</span><span style="color:#B58900;">None</span><span style="color:#839496;">):</span></span>
<span class="line"><span style="color:#839496;"> bucket </span><span style="color:#859900;">=</span><span style="color:#839496;"> s3.Bucket(bucket_name)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">if</span><span style="color:#839496;"> filename </span><span style="color:#859900;">is</span><span style="color:#839496;"> </span><span style="color:#B58900;">None</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> filename </span><span style="color:#859900;">=</span><span style="color:#839496;"> os.path.basename(key)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> bucket.download_file(key, filename)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">download_file</span><span style="color:#657B83;">(bucket_name, key, filename</span><span style="color:#859900;">=</span><span style="color:#B58900;">None</span><span style="color:#657B83;">):</span></span>
<span class="line"><span style="color:#657B83;"> bucket </span><span style="color:#859900;">=</span><span style="color:#657B83;"> s3.Bucket(bucket_name)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">if</span><span style="color:#657B83;"> filename </span><span style="color:#859900;">is</span><span style="color:#657B83;"> </span><span style="color:#B58900;">None</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> filename </span><span style="color:#859900;">=</span><span style="color:#657B83;"> os.path.basename(key)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> bucket.download_file(key, filename)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>S3 <code>download_file()</code> 使 Key 2 </p><h3 id="-5" tabindex="-1"> <a class="header-anchor" href="#-5" aria-label="Permalink to &quot;&quot;"></a></h3><p> S3 使 </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><h1 id="hands-on-6-bashoutter" tabindex="-1">Hands-on #6: Bashoutter <a class="header-anchor" href="#hands-on-6-bashoutter" aria-label="Permalink to &quot;Hands-on \\#6: Bashoutter&quot;"></a></h1><p>使 稿 SNS (<strong>Bashoutter</strong> ) Lambda, DynamoDB, S3 SNS <a href="#handson_05_bashoutter">figure_title</a> SNS </p><p><img src="`+Ks+'" alt="#6 SNS &quot;Bashoutter&quot;"></p><h2 id="-4" tabindex="-1"> <a class="header-anchor" href="#-4" aria-label="Permalink to &quot;&quot;"></a></h2><p> GitHub <a href="https://github.com/andatoshiki/toshiki-notebooktree/main/handson/bashoutter" target="_blank" rel="noreferrer">handson/bashoutter</a> </p><p> (<a href="#handson_01_prep"></a>) </p><p> <a href="https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&amp;all-free-tier.sort-order=asc" target="_blank" rel="noreferrer">AWS </a> </p><h2 id="-4" tabindex="-1"> <a class="header-anchor" href="#-4" aria-label="Permalink to &quot;&quot;"></a></h2><h3 id="api" tabindex="-1">API <a class="header-anchor" href="#api" aria-label="Permalink to &quot;API&quot;"></a></h3><p>稿稿 <a href="#tab_handson_05_api">table_title</a> REST API 稿 API <code>PATCH /haiku/{item_id}</code> <code>{item_id}</code> 使</p><table><caption>Bashoutter API</caption><colgroup><col style="width:50%;"><col style="width:50%;"></colgroup><tbody><tr class="odd"><td><p><code>GET /haiku</code></p></td><td><p></p></td></tr><tr class="even"><td><p><code>POST /haiku</code></p></td><td><p>稿</p></td></tr><tr class="odd"><td><p><code>PATCH /haiku/{item_id}</code></p></td><td><p><code>{item_id}</code> </p></td></tr><tr class="even"><td><p><code>DELETE /haiku/{item_id}</code></p></td><td><p><code>{item_id}</code> </p></td></tr></tbody></table><p> API <a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/bashoutter/specs/swagger.yml" target="_blank" rel="noreferrer">swagger.yml</a> </p><p><strong>Open API Specification</strong> (OAS; Swagger Specification ) REST API OAS API <a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/bashoutter/specs/swagger.yml" target="_blank" rel="noreferrer"> API </a> OAS <a href="https://swagger.io/docs/specification/about/" target="_blank" rel="noreferrer">Swagger </a> </p><h3 id="" tabindex="-1"> <a class="header-anchor" href="#" aria-label="Permalink to &quot;&quot;"></a></h3><p> <a href="#handson_05_architecture">figure_title</a> </p><p><img src="'+Ys+`" alt="#5"></p><p></p><ul><li><p> API <strong>API Gateway</strong> () API URI Lambda </p></li><li><p> API () Lambda </p></li><li><p> (稿) (DynamoDB) </p></li><li><p> Lambda DynamoDB </p></li><li><p> S3 S3 HTML/CSS/JS </p></li></ul><p> (<a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/bashoutter/app.py" target="_blank" rel="noreferrer">handson/bashoutter/app.py</a>)</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#93A1A1;font-weight:bold;">class</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">Bashoutter</span><span style="color:#839496;">(</span><span style="color:#6C71C4;">core</span><span style="color:#839496;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#839496;">):</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#839496;">, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs) -&gt; </span><span style="color:#B58900;">None</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">super</span><span style="color:#839496;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># dynamoDB table to store haiku</span></span>
<span class="line"><span style="color:#839496;"> table </span><span style="color:#859900;">=</span><span style="color:#839496;"> ddb.Table(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;Bashoutter-Table&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> partition_key</span><span style="color:#859900;">=</span><span style="color:#839496;">ddb.Attribute(</span></span>
<span class="line"><span style="color:#839496;"> name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;item_id&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> type</span><span style="color:#859900;">=</span><span style="color:#839496;">ddb.AttributeType.</span><span style="color:#CB4B16;">STRING</span></span>
<span class="line"><span style="color:#839496;"> ),</span></span>
<span class="line"><span style="color:#839496;"> billing_mode</span><span style="color:#859900;">=</span><span style="color:#839496;">ddb.BillingMode.</span><span style="color:#CB4B16;">PAY_PER_REQUEST</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#839496;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> bucket </span><span style="color:#859900;">=</span><span style="color:#839496;"> s3.Bucket(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;Bashoutter-Bucket&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> website_index_document</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;index.html&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> public_read_access</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#839496;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> common_params </span><span style="color:#859900;">=</span><span style="color:#839496;"> {</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;runtime&quot;</span><span style="color:#839496;">: _lambda.Runtime.</span><span style="color:#CB4B16;">PYTHON_3_7</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;environment&quot;</span><span style="color:#839496;">: {</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;TABLE_NAME&quot;</span><span style="color:#839496;">: table.table_name</span></span>
<span class="line"><span style="color:#839496;"> }</span></span>
<span class="line"><span style="color:#839496;"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># define Lambda functions</span></span>
<span class="line"><span style="color:#839496;"> get_haiku_lambda </span><span style="color:#859900;">=</span><span style="color:#839496;"> _lambda.Function(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;GetHaiku&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> code</span><span style="color:#859900;">=</span><span style="color:#839496;">_lambda.Code.from_asset(</span><span style="color:#2AA198;">&quot;api&quot;</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> handler</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;api.get_haiku&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> memory_size</span><span style="color:#859900;">=</span><span style="color:#D33682;">512</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">**</span><span style="color:#839496;">common_params,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> post_haiku_lambda </span><span style="color:#859900;">=</span><span style="color:#839496;"> _lambda.Function(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;PostHaiku&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> code</span><span style="color:#859900;">=</span><span style="color:#839496;">_lambda.Code.from_asset(</span><span style="color:#2AA198;">&quot;api&quot;</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> handler</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;api.post_haiku&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">**</span><span style="color:#839496;">common_params,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> patch_haiku_lambda </span><span style="color:#859900;">=</span><span style="color:#839496;"> _lambda.Function(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;PatchHaiku&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> code</span><span style="color:#859900;">=</span><span style="color:#839496;">_lambda.Code.from_asset(</span><span style="color:#2AA198;">&quot;api&quot;</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> handler</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;api.patch_haiku&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">**</span><span style="color:#839496;">common_params,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> delete_haiku_lambda </span><span style="color:#859900;">=</span><span style="color:#839496;"> _lambda.Function(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;DeleteHaiku&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> code</span><span style="color:#859900;">=</span><span style="color:#839496;">_lambda.Code.from_asset(</span><span style="color:#2AA198;">&quot;api&quot;</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> handler</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;api.delete_haiku&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">**</span><span style="color:#839496;">common_params,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># grant permissions</span></span>
<span class="line"><span style="color:#839496;"> table.grant_read_data(get_haiku_lambda)</span></span>
<span class="line"><span style="color:#839496;"> table.grant_read_write_data(post_haiku_lambda)</span></span>
<span class="line"><span style="color:#839496;"> table.grant_read_write_data(patch_haiku_lambda)</span></span>
<span class="line"><span style="color:#839496;"> table.grant_read_write_data(delete_haiku_lambda)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># define API Gateway</span></span>
<span class="line"><span style="color:#839496;"> api </span><span style="color:#859900;">=</span><span style="color:#839496;"> apigw.RestApi(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;BashoutterApi&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> default_cors_preflight_options</span><span style="color:#859900;">=</span><span style="color:#839496;">apigw.CorsOptions(</span></span>
<span class="line"><span style="color:#839496;"> allow_origins</span><span style="color:#859900;">=</span><span style="color:#839496;">apigw.Cors.</span><span style="color:#CB4B16;">ALL_ORIGINS</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> allow_methods</span><span style="color:#859900;">=</span><span style="color:#839496;">apigw.Cors.</span><span style="color:#CB4B16;">ALL_METHODS</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> haiku </span><span style="color:#859900;">=</span><span style="color:#839496;"> api.root.add_resource(</span><span style="color:#2AA198;">&quot;haiku&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> haiku.add_method(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;GET&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> apigw.LambdaIntegration(get_haiku_lambda)</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> haiku.add_method(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;POST&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> apigw.LambdaIntegration(post_haiku_lambda)</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> haiku_item_id </span><span style="color:#859900;">=</span><span style="color:#839496;"> haiku.add_resource(</span><span style="color:#2AA198;">&quot;</span><span style="color:#CB4B16;">{item_id}</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> haiku_item_id.add_method(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;PATCH&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> apigw.LambdaIntegration(patch_haiku_lambda)</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;"> haiku_item_id.add_method(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;DELETE&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> apigw.LambdaIntegration(delete_haiku_lambda)</span></span>
<span class="line"><span style="color:#839496;"> )</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#586E75;font-weight:bold;">class</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">Bashoutter</span><span style="color:#657B83;">(</span><span style="color:#6C71C4;">core</span><span style="color:#657B83;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#657B83;">):</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#657B83;">, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs) -&gt; </span><span style="color:#B58900;">None</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">super</span><span style="color:#657B83;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># dynamoDB table to store haiku</span></span>
<span class="line"><span style="color:#657B83;"> table </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ddb.Table(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;Bashoutter-Table&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> partition_key</span><span style="color:#859900;">=</span><span style="color:#657B83;">ddb.Attribute(</span></span>
<span class="line"><span style="color:#657B83;"> name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;item_id&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> type</span><span style="color:#859900;">=</span><span style="color:#657B83;">ddb.AttributeType.</span><span style="color:#CB4B16;">STRING</span></span>
<span class="line"><span style="color:#657B83;"> ),</span></span>
<span class="line"><span style="color:#657B83;"> billing_mode</span><span style="color:#859900;">=</span><span style="color:#657B83;">ddb.BillingMode.</span><span style="color:#CB4B16;">PAY_PER_REQUEST</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#657B83;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> bucket </span><span style="color:#859900;">=</span><span style="color:#657B83;"> s3.Bucket(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;Bashoutter-Bucket&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> website_index_document</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;index.html&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> public_read_access</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#657B83;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> common_params </span><span style="color:#859900;">=</span><span style="color:#657B83;"> {</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;runtime&quot;</span><span style="color:#657B83;">: _lambda.Runtime.</span><span style="color:#CB4B16;">PYTHON_3_7</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;environment&quot;</span><span style="color:#657B83;">: {</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;TABLE_NAME&quot;</span><span style="color:#657B83;">: table.table_name</span></span>
<span class="line"><span style="color:#657B83;"> }</span></span>
<span class="line"><span style="color:#657B83;"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># define Lambda functions</span></span>
<span class="line"><span style="color:#657B83;"> get_haiku_lambda </span><span style="color:#859900;">=</span><span style="color:#657B83;"> _lambda.Function(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;GetHaiku&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> code</span><span style="color:#859900;">=</span><span style="color:#657B83;">_lambda.Code.from_asset(</span><span style="color:#2AA198;">&quot;api&quot;</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> handler</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;api.get_haiku&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> memory_size</span><span style="color:#859900;">=</span><span style="color:#D33682;">512</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">**</span><span style="color:#657B83;">common_params,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> post_haiku_lambda </span><span style="color:#859900;">=</span><span style="color:#657B83;"> _lambda.Function(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;PostHaiku&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> code</span><span style="color:#859900;">=</span><span style="color:#657B83;">_lambda.Code.from_asset(</span><span style="color:#2AA198;">&quot;api&quot;</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> handler</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;api.post_haiku&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">**</span><span style="color:#657B83;">common_params,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> patch_haiku_lambda </span><span style="color:#859900;">=</span><span style="color:#657B83;"> _lambda.Function(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;PatchHaiku&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> code</span><span style="color:#859900;">=</span><span style="color:#657B83;">_lambda.Code.from_asset(</span><span style="color:#2AA198;">&quot;api&quot;</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> handler</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;api.patch_haiku&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">**</span><span style="color:#657B83;">common_params,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> delete_haiku_lambda </span><span style="color:#859900;">=</span><span style="color:#657B83;"> _lambda.Function(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;DeleteHaiku&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> code</span><span style="color:#859900;">=</span><span style="color:#657B83;">_lambda.Code.from_asset(</span><span style="color:#2AA198;">&quot;api&quot;</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> handler</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;api.delete_haiku&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">**</span><span style="color:#657B83;">common_params,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># grant permissions</span></span>
<span class="line"><span style="color:#657B83;"> table.grant_read_data(get_haiku_lambda)</span></span>
<span class="line"><span style="color:#657B83;"> table.grant_read_write_data(post_haiku_lambda)</span></span>
<span class="line"><span style="color:#657B83;"> table.grant_read_write_data(patch_haiku_lambda)</span></span>
<span class="line"><span style="color:#657B83;"> table.grant_read_write_data(delete_haiku_lambda)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># define API Gateway</span></span>
<span class="line"><span style="color:#657B83;"> api </span><span style="color:#859900;">=</span><span style="color:#657B83;"> apigw.RestApi(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;BashoutterApi&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> default_cors_preflight_options</span><span style="color:#859900;">=</span><span style="color:#657B83;">apigw.CorsOptions(</span></span>
<span class="line"><span style="color:#657B83;"> allow_origins</span><span style="color:#859900;">=</span><span style="color:#657B83;">apigw.Cors.</span><span style="color:#CB4B16;">ALL_ORIGINS</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> allow_methods</span><span style="color:#859900;">=</span><span style="color:#657B83;">apigw.Cors.</span><span style="color:#CB4B16;">ALL_METHODS</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> haiku </span><span style="color:#859900;">=</span><span style="color:#657B83;"> api.root.add_resource(</span><span style="color:#2AA198;">&quot;haiku&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> haiku.add_method(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;GET&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> apigw.LambdaIntegration(get_haiku_lambda)</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> haiku.add_method(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;POST&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> apigw.LambdaIntegration(post_haiku_lambda)</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> haiku_item_id </span><span style="color:#859900;">=</span><span style="color:#657B83;"> haiku.add_resource(</span><span style="color:#2AA198;">&quot;</span><span style="color:#CB4B16;">{item_id}</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> haiku_item_id.add_method(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;PATCH&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> apigw.LambdaIntegration(patch_haiku_lambda)</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;"> haiku_item_id.add_method(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;DELETE&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> apigw.LambdaIntegration(delete_haiku_lambda)</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br></div></div><ul><li><p> DynamoDB </p></li><li><p> S3 </p></li><li><p> API Lambda Python3.7 <a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/bashoutter/api/api.py" target="_blank" rel="noreferrer">handson/bashoutter/api/api.py</a> </p></li><li><p>&lt;3&gt; Lambda </p></li><li><p>API Gateway API Lambda </p></li></ul><p></p><h3 id="public-access-mode--s3-" tabindex="-1">Public access mode S3 <a class="header-anchor" href="#public-access-mode--s3-" aria-label="Permalink to &quot;Public access mode S3 &quot;"></a></h3><p>S3 </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">bucket </span><span style="color:#859900;">=</span><span style="color:#839496;"> s3.Bucket(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;Bashoutter-Bucket&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> website_index_document</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;index.html&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> public_read_access</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#839496;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span></span>
<span class="line"><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">bucket </span><span style="color:#859900;">=</span><span style="color:#657B83;"> s3.Bucket(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;Bashoutter-Bucket&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> website_index_document</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;index.html&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> public_read_access</span><span style="color:#859900;">=</span><span style="color:#B58900;">True</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#657B83;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span></span>
<span class="line"><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p> <code>public_read_access=True</code> S3 S3 <strong>Public access mode</strong> Public access mode (i.e. ) public access mode <code>http://XXXX.s3-website-ap-northeast-1.amazonaws.com/</code> URL URL <code>index.html</code> ( <code>website_index_document=&quot;index.html&quot;</code> )</p><p> HTML/CSS/JS </p><p> public access mode S3 <a href="https://aws.amazon.com/cloudfront/" target="_blank" rel="noreferrer">CloudFront</a> CloudFront  <strong>Content Delivery Nework (CDN)</strong> HTTPS CloudFront <a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html" target="_blank" rel="noreferrer"> &quot;What is Amazon CloudFront?&quot;</a> </p><p> CloudFront </p><ul><li><a href="https://github.com/aws-samples/aws-cdk-examples/tree/master/typescript/static-site" target="_blank" rel="noreferrer">https://github.com/aws-samples/aws-cdk-examples/tree/master/typescript/static-site</a></li></ul><p> S3 AWS URL <code>example.com</code> AWS URL DNS </p><h3 id="api-" tabindex="-1">API <a class="header-anchor" href="#api-" aria-label="Permalink to &quot;API &quot;"></a></h3><p>API (handler) <code>GET /haiku</code> API Lambda </p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">get_haiku_lambda </span><span style="color:#859900;">=</span><span style="color:#839496;"> _lambda.Function(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;GetHaiku&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> code</span><span style="color:#859900;">=</span><span style="color:#839496;">_lambda.Code.from_asset(</span><span style="color:#2AA198;">&quot;api&quot;</span><span style="color:#839496;">),</span></span>
<span class="line"><span style="color:#839496;"> handler</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;api.get_haiku&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> memory_size</span><span style="color:#859900;">=</span><span style="color:#D33682;">512</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">**</span><span style="color:#839496;">common_params</span></span>
<span class="line"><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">get_haiku_lambda </span><span style="color:#859900;">=</span><span style="color:#657B83;"> _lambda.Function(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;GetHaiku&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> code</span><span style="color:#859900;">=</span><span style="color:#657B83;">_lambda.Code.from_asset(</span><span style="color:#2AA198;">&quot;api&quot;</span><span style="color:#657B83;">),</span></span>
<span class="line"><span style="color:#657B83;"> handler</span><span style="color:#859900;">=</span><span style="color:#2AA198;">&quot;api.get_haiku&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> memory_size</span><span style="color:#859900;">=</span><span style="color:#D33682;">512</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">**</span><span style="color:#657B83;">common_params</span></span>
<span class="line"><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p> <code>memory_size=512</code> 使 512MB <code>code=_lambda.Code.from_asset(&quot;api&quot;)</code> (<code>api/</code>) <code>handler=&quot;api.get_haiku&quot;</code> <code>api.py</code> <code>get_haiku()</code> </p><p>使 <code>get_haiku()</code> (<a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/bashoutter/api/api.py" target="_blank" rel="noreferrer">handson/bashoutter/api/api.py</a>)</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">ddb </span><span style="color:#859900;">=</span><span style="color:#839496;"> boto3.resource(</span><span style="color:#2AA198;">&quot;dynamodb&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">table </span><span style="color:#859900;">=</span><span style="color:#839496;"> ddb.Table(os.environ[</span><span style="color:#2AA198;">&quot;TABLE_NAME&quot;</span><span style="color:#839496;">])</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">get_haiku</span><span style="color:#839496;">(event, context):</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;&quot;&quot;</span></span>
<span class="line"><span style="color:#2AA198;"> handler for GET /haiku</span></span>
<span class="line"><span style="color:#2AA198;"> &quot;&quot;&quot;</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">try</span><span style="color:#839496;">:</span></span>
<span class="line"><span style="color:#839496;"> response </span><span style="color:#859900;">=</span><span style="color:#839496;"> table.scan()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#839496;"> status_code </span><span style="color:#859900;">=</span><span style="color:#839496;"> </span><span style="color:#D33682;">200</span></span>
<span class="line"><span style="color:#839496;"> resp </span><span style="color:#859900;">=</span><span style="color:#839496;"> response.get(</span><span style="color:#2AA198;">&quot;Items&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">except</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">Exception</span><span style="color:#839496;"> </span><span style="color:#859900;">as</span><span style="color:#839496;"> e:</span></span>
<span class="line"><span style="color:#839496;"> status_code </span><span style="color:#859900;">=</span><span style="color:#839496;"> </span><span style="color:#D33682;">500</span></span>
<span class="line"><span style="color:#839496;"> resp </span><span style="color:#859900;">=</span><span style="color:#839496;"> {</span><span style="color:#2AA198;">&quot;description&quot;</span><span style="color:#839496;">: </span><span style="color:#93A1A1;font-weight:bold;">f</span><span style="color:#2AA198;">&quot;Internal server error. </span><span style="color:#CB4B16;">{</span><span style="color:#859900;">str</span><span style="color:#839496;">(e)</span><span style="color:#CB4B16;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;">}</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">return</span><span style="color:#839496;"> {</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;statusCode&quot;</span><span style="color:#839496;">: status_code,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;headers&quot;</span><span style="color:#839496;">: </span><span style="color:#CB4B16;">HEADERS</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;body&quot;</span><span style="color:#839496;">: json.dumps(resp, cls</span><span style="color:#859900;">=</span><span style="color:#839496;">DecimalEncoder)</span></span>
<span class="line"><span style="color:#839496;"> }</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">ddb </span><span style="color:#859900;">=</span><span style="color:#657B83;"> boto3.resource(</span><span style="color:#2AA198;">&quot;dynamodb&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">table </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ddb.Table(os.environ[</span><span style="color:#2AA198;">&quot;TABLE_NAME&quot;</span><span style="color:#657B83;">])</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">get_haiku</span><span style="color:#657B83;">(event, context):</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;&quot;&quot;</span></span>
<span class="line"><span style="color:#2AA198;"> handler for GET /haiku</span></span>
<span class="line"><span style="color:#2AA198;"> &quot;&quot;&quot;</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">try</span><span style="color:#657B83;">:</span></span>
<span class="line"><span style="color:#657B83;"> response </span><span style="color:#859900;">=</span><span style="color:#657B83;"> table.scan()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#657B83;"> status_code </span><span style="color:#859900;">=</span><span style="color:#657B83;"> </span><span style="color:#D33682;">200</span></span>
<span class="line"><span style="color:#657B83;"> resp </span><span style="color:#859900;">=</span><span style="color:#657B83;"> response.get(</span><span style="color:#2AA198;">&quot;Items&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">except</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">Exception</span><span style="color:#657B83;"> </span><span style="color:#859900;">as</span><span style="color:#657B83;"> e:</span></span>
<span class="line"><span style="color:#657B83;"> status_code </span><span style="color:#859900;">=</span><span style="color:#657B83;"> </span><span style="color:#D33682;">500</span></span>
<span class="line"><span style="color:#657B83;"> resp </span><span style="color:#859900;">=</span><span style="color:#657B83;"> {</span><span style="color:#2AA198;">&quot;description&quot;</span><span style="color:#657B83;">: </span><span style="color:#586E75;font-weight:bold;">f</span><span style="color:#2AA198;">&quot;Internal server error. </span><span style="color:#CB4B16;">{</span><span style="color:#859900;">str</span><span style="color:#657B83;">(e)</span><span style="color:#CB4B16;">}</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;">}</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">return</span><span style="color:#657B83;"> {</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;statusCode&quot;</span><span style="color:#657B83;">: status_code,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;headers&quot;</span><span style="color:#657B83;">: </span><span style="color:#CB4B16;">HEADERS</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;body&quot;</span><span style="color:#657B83;">: json.dumps(resp, cls</span><span style="color:#859900;">=</span><span style="color:#657B83;">DecimalEncoder)</span></span>
<span class="line"><span style="color:#657B83;"> }</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div><p><code>response = table.scan()</code> DynamoDB 200 500 </p><p> API API </p><p><code>GET /haiku</code> <code>response = table.scan()</code> DynamoDB <code>scan()</code> 1MB 1MB <code>scan()</code> <a href="https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Table.scan" target="_blank" rel="noreferrer">boto3 </a> </p><h3 id="aws--iam" tabindex="-1">AWS (IAM) <a class="header-anchor" href="#aws--iam" aria-label="Permalink to &quot;AWS (IAM)&quot;"></a></h3><p></p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">table.grant_read_data(get_haiku_lambda)</span></span>
<span class="line"><span style="color:#839496;">table.grant_read_write_data(post_haiku_lambda)</span></span>
<span class="line"><span style="color:#839496;">table.grant_read_write_data(patch_haiku_lambda)</span></span>
<span class="line"><span style="color:#839496;">table.grant_read_write_data(delete_haiku_lambda)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">table.grant_read_data(get_haiku_lambda)</span></span>
<span class="line"><span style="color:#657B83;">table.grant_read_write_data(post_haiku_lambda)</span></span>
<span class="line"><span style="color:#657B83;">table.grant_read_write_data(patch_haiku_lambda)</span></span>
<span class="line"><span style="color:#657B83;">table.grant_read_write_data(delete_haiku_lambda)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p> AWS <a href="https://aws.amazon.com/iam/" target="_blank" rel="noreferrer">IAM (Identity and Access Management)</a> IAM Lambda Lambda DynamoDB IAM Lambda </p><p>CDK <code>dynamodb.Table</code> <code>grant_read_write_data()</code> 便 Lambda IAM CDK <code>s3.Bucket</code> <code>grant_read_write()</code> <a href="#sec_aws_batch">Hands-on #4: AWS Batch 使</a> AWS Batch 使 </p><p> IAM <strong></strong> </p><p> <code>GET</code> <code>grant_read_data()</code> read </p><h3 id="api-gateway" tabindex="-1">API Gateway <a class="header-anchor" href="#api-gateway" aria-label="Permalink to &quot;API Gateway&quot;"></a></h3><p><a href="https://aws.amazon.com/api-gateway/" target="_blank" rel="noreferrer">API Gateway</a> API &quot;&quot;API Lambda EC2 (<a href="#fig:bashoutter_api_gateway">figure_title</a>) Lambda EC2 API Gateway API <strong></strong><strong></strong> API Gateway API API </p><p><img src="`+Js+`" alt="API Gateway"></p><p>API Gateway (1 ) API API Gateway <a href="#tab_handson_05_apigateway_price">table_title</a> 100 0 </p><table><caption>API Gateway (<a href="https://aws.amazon.com/api-gateway/pricing/"></a>)</caption><colgroup><col style="width:50%;"><col style="width:50%;"></colgroup><thead><tr class="header"><th>Number of Requests (per month)</th><th>Price (per million)</th></tr></thead><tbody><tr class="odd"><td><p>First 333 million</p></td><td><p>$4.25</p></td></tr><tr class="even"><td><p>Next 667 million</p></td><td><p>$3.53</p></td></tr><tr class="odd"><td><p>Next 19 billion</p></td><td><p>$3.00</p></td></tr><tr class="even"><td><p>Over 20 billion</p></td><td><p>$1.91</p></td></tr></tbody></table><p></p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;">api </span><span style="color:#859900;">=</span><span style="color:#839496;"> apigw.RestApi(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">&quot;BashoutterApi&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> default_cors_preflight_options</span><span style="color:#859900;">=</span><span style="color:#839496;">apigw.CorsOptions(</span></span>
<span class="line"><span style="color:#839496;"> allow_origins</span><span style="color:#859900;">=</span><span style="color:#839496;">apigw.Cors.</span><span style="color:#CB4B16;">ALL_ORIGINS</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> allow_methods</span><span style="color:#859900;">=</span><span style="color:#839496;">apigw.Cors.</span><span style="color:#CB4B16;">ALL_METHODS</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> )</span></span>
<span class="line"><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;">haiku </span><span style="color:#859900;">=</span><span style="color:#839496;"> api.root.add_resource(</span><span style="color:#2AA198;">&quot;haiku&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;">haiku.add_method(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;GET&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> apigw.LambdaIntegration(get_haiku_lambda)</span></span>
<span class="line"><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">haiku.add_method(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;POST&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> apigw.LambdaIntegration(post_haiku_lambda)</span></span>
<span class="line"><span style="color:#839496;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;">haiku_item_id </span><span style="color:#859900;">=</span><span style="color:#839496;"> haiku.add_resource(</span><span style="color:#2AA198;">&quot;</span><span style="color:#CB4B16;">{item_id}</span><span style="color:#2AA198;">&quot;</span><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#586E75;font-style:italic;">#</span></span>
<span class="line"><span style="color:#839496;">haiku_item_id.add_method(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;PATCH&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> apigw.LambdaIntegration(patch_haiku_lambda)</span></span>
<span class="line"><span style="color:#839496;">)</span></span>
<span class="line"><span style="color:#839496;">haiku_item_id.add_method(</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;DELETE&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> apigw.LambdaIntegration(delete_haiku_lambda)</span></span>
<span class="line"><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;">api </span><span style="color:#859900;">=</span><span style="color:#657B83;"> apigw.RestApi(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">&quot;BashoutterApi&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> default_cors_preflight_options</span><span style="color:#859900;">=</span><span style="color:#657B83;">apigw.CorsOptions(</span></span>
<span class="line"><span style="color:#657B83;"> allow_origins</span><span style="color:#859900;">=</span><span style="color:#657B83;">apigw.Cors.</span><span style="color:#CB4B16;">ALL_ORIGINS</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> allow_methods</span><span style="color:#859900;">=</span><span style="color:#657B83;">apigw.Cors.</span><span style="color:#CB4B16;">ALL_METHODS</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> )</span></span>
<span class="line"><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;">haiku </span><span style="color:#859900;">=</span><span style="color:#657B83;"> api.root.add_resource(</span><span style="color:#2AA198;">&quot;haiku&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;">haiku.add_method(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;GET&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> apigw.LambdaIntegration(get_haiku_lambda)</span></span>
<span class="line"><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">haiku.add_method(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;POST&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> apigw.LambdaIntegration(post_haiku_lambda)</span></span>
<span class="line"><span style="color:#657B83;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;">haiku_item_id </span><span style="color:#859900;">=</span><span style="color:#657B83;"> haiku.add_resource(</span><span style="color:#2AA198;">&quot;</span><span style="color:#CB4B16;">{item_id}</span><span style="color:#2AA198;">&quot;</span><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;">#</span></span>
<span class="line"><span style="color:#657B83;">haiku_item_id.add_method(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;PATCH&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> apigw.LambdaIntegration(patch_haiku_lambda)</span></span>
<span class="line"><span style="color:#657B83;">)</span></span>
<span class="line"><span style="color:#657B83;">haiku_item_id.add_method(</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;DELETE&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> apigw.LambdaIntegration(delete_haiku_lambda)</span></span>
<span class="line"><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br></div></div><ul><li><p> <code>api = apigw.RestApi()</code> API Gateway </p></li><li><p> <code>api.root.add_resource()</code> <code>/haiku</code> API </p></li><li><p> <code>add_method()</code> <code>GET</code>, <code>POST</code> <code>/haiku</code> </p></li><li><p> <code>haiku.add_resource(&quot;{item_id}&quot;)</code> <code>/haiku/{item_id}</code> API </p></li><li><p> <code>add_method()</code> <code>PATCH</code>, <code>DELETE</code> <code>/haiku/{item_id}</code> </p></li></ul><p> API Gateway 使 API Lambda </p><p> API URL API <code>api.example.com</code> AWS URL DNS </p><p>API Gateway API <code>default_cors_preflight_options=</code> <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" target="_blank" rel="noreferrer">Cross Origin Resource Sharing (CORS)</a> Web API </p><h2 id="" tabindex="-1"> <a class="header-anchor" href="#" aria-label="Permalink to &quot;&quot;"></a></h2><p> (<code>#</code> ) (<a href="#aws_cli_install">AWS CLI </a>)</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># </span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cd</span><span style="color:#839496;"> </span><span style="color:#2AA198;">intro-aws/handson/bashoutter</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># venv を作成し依存ライブラリのインストールを行う</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python3</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#839496;"> </span><span style="color:#2AA198;">venv</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">source</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pip</span><span style="color:#839496;"> </span><span style="color:#2AA198;">install</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#839496;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#586E75;font-style:italic;"># デプロイを実行</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">deploy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># </span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cd</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">intro-aws/handson/bashoutter</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># venv を作成し依存ライブラリのインストールを行う</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python3</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">venv</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">source</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pip</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">install</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color:#93A1A1;font-style:italic;"># デプロイを実行</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">deploy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p> <a href="#handson_05_cdk_output">figure_title</a> <code>Bashoutter.BashoutterApiEndpoint = XXXX</code>, <code>Bashoutter.BucketUrl = YYYY</code> 使</p><p><img src="`+Qs+'" alt="CDK"></p><p>AWS API Gateway <a href="#handson_05_apigw_console_list">figure_title</a> API </p><p><img src="'+Zs+'" alt="API Gateway (1)"></p><p> &quot;BashoutterApi&quot; API <a href="#handson_05_apigw_console_detail">figure_title</a> <code>GET /haiku</code>, <code>POST /haiku</code> </p><p> API Gateway 使 &quot;Method Request&quot; <a href="#handson_05_apigw_console_detail">figure_title</a> API Lambda Lambda </p><p><img src="'+sa+'" alt="API Gateway (2)"></p><p> S3 <code>bashouter-</code> (<a href="#handson_05_s3_console">figure_title</a>)</p><p><img src="'+aa+'" alt="S3 "></p><p> <code>index.html</code> <code>css/</code>, <code>js/</code> (<a href="#handson_05_s3_contents">figure_title</a>) &quot;&quot;</p><p><img src="'+na+`" alt="S3 "></p><h2 id="api-" tabindex="-1">API <a class="header-anchor" href="#api-" aria-label="Permalink to &quot;API &quot;"></a></h2><p> API API S3 GUI </p><p> HTTP API HTTP <a href="https://httpie.org/" target="_blank" rel="noreferrer">HTTPie</a> 使 HTTPie Python (venv) <code>http</code> OK </p><p> API URL (<code>Bashoutter.BashoutterApiEndpoint = XXXX</code> <code>XXXX</code> ) </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">export</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ENDPOINT_URL=XXXX</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">export</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ENDPOINT_URL=XXXX</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> <code>GET /haiku</code> API </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">http</span><span style="color:#839496;"> </span><span style="color:#2AA198;">GET</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">ENDPOINT_URL</span><span style="color:#859900;">}</span><span style="color:#2AA198;">/haiku&quot;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">http</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">GET</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">ENDPOINT_URL</span><span style="color:#859900;">}</span><span style="color:#2AA198;">/haiku&quot;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>稿 (<code>[]</code>) </p><p> <code>POST /haiku</code> 使稿</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">http</span><span style="color:#839496;"> </span><span style="color:#2AA198;">POST</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">ENDPOINT_URL</span><span style="color:#859900;">}</span><span style="color:#2AA198;">/haiku&quot;</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">\\</span></span>
<span class="line"><span style="color:#839496;">username=</span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">\\</span></span>
<span class="line"><span style="color:#839496;">first=</span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">\\</span></span>
<span class="line"><span style="color:#839496;">second=</span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">\\</span></span>
<span class="line"><span style="color:#839496;">third=</span><span style="color:#2AA198;">&quot;&quot;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">http</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">POST</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">ENDPOINT_URL</span><span style="color:#859900;">}</span><span style="color:#2AA198;">/haiku&quot;</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">\\</span></span>
<span class="line"><span style="color:#657B83;">username=</span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">\\</span></span>
<span class="line"><span style="color:#657B83;">first=</span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">\\</span></span>
<span class="line"><span style="color:#657B83;">second=</span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">\\</span></span>
<span class="line"><span style="color:#657B83;">third=</span><span style="color:#2AA198;">&quot;&quot;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p></p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">HTTP/1.1</span><span style="color:#839496;"> </span><span style="color:#D33682;">201</span><span style="color:#839496;"> </span><span style="color:#2AA198;">Created</span></span>
<span class="line"><span style="color:#268BD2;">Connection:</span><span style="color:#839496;"> </span><span style="color:#2AA198;">keep-alive</span></span>
<span class="line"><span style="color:#268BD2;">Content-Length:</span><span style="color:#839496;"> </span><span style="color:#D33682;">49</span></span>
<span class="line"><span style="color:#268BD2;">Content-Type:</span><span style="color:#839496;"> </span><span style="color:#2AA198;">application/json</span></span>
<span class="line"><span style="color:#268BD2;">....</span></span>
<span class="line"><span style="color:#839496;">{</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">&quot;description&quot;</span><span style="color:#268BD2;">:</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;Successfully added a new haiku&quot;</span></span>
<span class="line"><span style="color:#839496;">}</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">HTTP/1.1</span><span style="color:#657B83;"> </span><span style="color:#D33682;">201</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">Created</span></span>
<span class="line"><span style="color:#268BD2;">Connection:</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">keep-alive</span></span>
<span class="line"><span style="color:#268BD2;">Content-Length:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">49</span></span>
<span class="line"><span style="color:#268BD2;">Content-Type:</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">application/json</span></span>
<span class="line"><span style="color:#268BD2;">....</span></span>
<span class="line"><span style="color:#657B83;">{</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">&quot;description&quot;</span><span style="color:#268BD2;">:</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;Successfully added a new haiku&quot;</span></span>
<span class="line"><span style="color:#657B83;">}</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>稿 GET </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">http</span><span style="color:#839496;"> </span><span style="color:#2AA198;">GET</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">ENDPOINT_URL</span><span style="color:#859900;">}</span><span style="color:#2AA198;">/haiku&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">HTTP/1.1</span><span style="color:#839496;"> </span><span style="color:#D33682;">200</span><span style="color:#839496;"> </span><span style="color:#2AA198;">OK</span></span>
<span class="line"><span style="color:#268BD2;">Connection:</span><span style="color:#839496;"> </span><span style="color:#2AA198;">keep-alive</span></span>
<span class="line"><span style="color:#268BD2;">Content-Length:</span><span style="color:#839496;"> </span><span style="color:#D33682;">258</span></span>
<span class="line"><span style="color:#268BD2;">Content-Type:</span><span style="color:#839496;"> </span><span style="color:#2AA198;">application/json</span></span>
<span class="line"><span style="color:#268BD2;">...</span></span>
<span class="line"><span style="color:#839496;">[</span></span>
<span class="line"><span style="color:#839496;"> {</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;created_at&quot;</span><span style="color:#839496;">: </span><span style="color:#2AA198;">&quot;2020-07-06T02:46:04+00:00&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;first&quot;</span><span style="color:#839496;">: </span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;item_id&quot;</span><span style="color:#839496;">: </span><span style="color:#2AA198;">&quot;7e91c5e4d7ad47909e0ac14c8bbab05b&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;likes&quot;</span><span style="color:#839496;">: </span><span style="color:#D33682;">0.0</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;second&quot;</span><span style="color:#839496;">: </span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;third&quot;</span><span style="color:#839496;">: </span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;username&quot;</span><span style="color:#839496;">: </span><span style="color:#2AA198;">&quot;&quot;</span></span>
<span class="line"><span style="color:#839496;"> }</span></span>
<span class="line"><span style="color:#839496;">]</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">http</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">GET</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">ENDPOINT_URL</span><span style="color:#859900;">}</span><span style="color:#2AA198;">/haiku&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">HTTP/1.1</span><span style="color:#657B83;"> </span><span style="color:#D33682;">200</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">OK</span></span>
<span class="line"><span style="color:#268BD2;">Connection:</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">keep-alive</span></span>
<span class="line"><span style="color:#268BD2;">Content-Length:</span><span style="color:#657B83;"> </span><span style="color:#D33682;">258</span></span>
<span class="line"><span style="color:#268BD2;">Content-Type:</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">application/json</span></span>
<span class="line"><span style="color:#268BD2;">...</span></span>
<span class="line"><span style="color:#657B83;">[</span></span>
<span class="line"><span style="color:#657B83;"> {</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;created_at&quot;</span><span style="color:#657B83;">: </span><span style="color:#2AA198;">&quot;2020-07-06T02:46:04+00:00&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;first&quot;</span><span style="color:#657B83;">: </span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;item_id&quot;</span><span style="color:#657B83;">: </span><span style="color:#2AA198;">&quot;7e91c5e4d7ad47909e0ac14c8bbab05b&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;likes&quot;</span><span style="color:#657B83;">: </span><span style="color:#D33682;">0.0</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;second&quot;</span><span style="color:#657B83;">: </span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;third&quot;</span><span style="color:#657B83;">: </span><span style="color:#2AA198;">&quot;&quot;</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;username&quot;</span><span style="color:#657B83;">: </span><span style="color:#2AA198;">&quot;&quot;</span></span>
<span class="line"><span style="color:#657B83;"> }</span></span>
<span class="line"><span style="color:#657B83;">]</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><p></p><p> <code>PATCH /haiku/{item_id}</code> <code>item_id</code> <code>XXXX</code> </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">http</span><span style="color:#839496;"> </span><span style="color:#2AA198;">PATCH</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">ENDPOINT_URL</span><span style="color:#859900;">}</span><span style="color:#2AA198;">/haiku/XXXX&quot;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">http</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">PATCH</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">ENDPOINT_URL</span><span style="color:#859900;">}</span><span style="color:#2AA198;">/haiku/XXXX&quot;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p><code>{&quot;description&quot;: &quot;OK&quot;}</code> GET (<code>likes</code>) 1 </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">http</span><span style="color:#839496;"> </span><span style="color:#2AA198;">GET</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">ENDPOINT_URL</span><span style="color:#859900;">}</span><span style="color:#2AA198;">/haiku&quot;</span></span>
<span class="line"><span style="color:#268BD2;">...</span></span>
<span class="line"><span style="color:#839496;">[</span></span>
<span class="line"><span style="color:#839496;"> {</span></span>
<span class="line"><span style="color:#839496;"> ...</span></span>
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;likes&quot;</span><span style="color:#839496;">: </span><span style="color:#D33682;">1.0</span><span style="color:#839496;">,</span></span>
<span class="line"><span style="color:#839496;"> ...</span></span>
<span class="line"><span style="color:#839496;"> }</span></span>
<span class="line"><span style="color:#839496;">]</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">http</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">GET</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">ENDPOINT_URL</span><span style="color:#859900;">}</span><span style="color:#2AA198;">/haiku&quot;</span></span>
<span class="line"><span style="color:#268BD2;">...</span></span>
<span class="line"><span style="color:#657B83;">[</span></span>
<span class="line"><span style="color:#657B83;"> {</span></span>
<span class="line"><span style="color:#657B83;"> ...</span></span>
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;likes&quot;</span><span style="color:#657B83;">: </span><span style="color:#D33682;">1.0</span><span style="color:#657B83;">,</span></span>
<span class="line"><span style="color:#657B83;"> ...</span></span>
<span class="line"><span style="color:#657B83;"> }</span></span>
<span class="line"><span style="color:#657B83;">]</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><p> DELETE <code>XXXX</code> <code>item_id</code> </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">http</span><span style="color:#839496;"> </span><span style="color:#2AA198;">DELETE</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">ENDPOINT_URL</span><span style="color:#859900;">}</span><span style="color:#2AA198;">/haiku/XXXX&quot;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">http</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">DELETE</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;</span><span style="color:#859900;">\${</span><span style="color:#268BD2;">ENDPOINT_URL</span><span style="color:#859900;">}</span><span style="color:#2AA198;">/haiku/XXXX&quot;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> GET (<code>[]</code>) </p><p>稿 API </p><h2 id="-api-" tabindex="-1"> API <a class="header-anchor" href="#-api-" aria-label="Permalink to &quot; API &quot;"></a></h2><p>稿 SNS 1 稿 API </p><p><a href="https://github.com/andatoshiki/toshiki-notebookblob/main/handson/bashoutter/client.py" target="_blank" rel="noreferrer">handson/bashoutter/client.py</a> API 使 <code>POST /haiku</code> API </p><p> API 300 </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">client.py</span><span style="color:#839496;"> </span><span style="color:#268BD2;">$ENDPOINT_URL</span><span style="color:#839496;"> </span><span style="color:#2AA198;">post_many</span><span style="color:#839496;"> </span><span style="color:#D33682;">300</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">client.py</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">$ENDPOINT_URL</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">post_many</span><span style="color:#657B83;"> </span><span style="color:#D33682;">300</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> API 1 </p><p>稿 使</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">client.py</span><span style="color:#839496;"> </span><span style="color:#268BD2;">$ENDPOINT_URL</span><span style="color:#839496;"> </span><span style="color:#2AA198;">clear_database</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">client.py</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">$ENDPOINT_URL</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">clear_database</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><h2 id="bashoutter-gui-" tabindex="-1">Bashoutter GUI <a class="header-anchor" href="#bashoutter-gui-" aria-label="Permalink to &quot;Bashoutter GUI &quot;"></a></h2><p> API (<a href="#fig:web_server">figure_title</a> ) API GUI </p><p>CDK Public access mode S3 <code>gui/dist</code> (HTML/CSS/JavaScript) AWS CLI 使 S3 </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">s3</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cp</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--recursive</span><span style="color:#839496;"> </span><span style="color:#2AA198;">./gui/dist</span><span style="color:#839496;"> </span><span style="color:#2AA198;">s3://</span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">BUCKET_NAM</span><span style="color:#839496;">E</span><span style="color:#859900;">&gt;</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">s3</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cp</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--recursive</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">./gui/dist</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">s3://</span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">BUCKET_NAM</span><span style="color:#657B83;">E</span><span style="color:#859900;">&gt;</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> Bashoutter (<code>./gui/dist</code> ) <code>&lt;BUCKET_NAME&gt;</code> AWS </p><p> GUI Bashoutter <a href="https://vuejs.org/" target="_blank" rel="noreferrer">Vue.js</a> <a href="https://vuetifyjs.com/" target="_blank" rel="noreferrer">Vuetify</a> UI 使 Vue 使 Single page application (SPA) <a href="https://github.com/andatoshiki/toshiki-notebooktree/main/handson/bashoutter/gui" target="_blank" rel="noreferrer">handson/bashoutter/gui</a> </p><p> <code>Bashoutter.BucketUrl=</code> URL (<a href="#handson_05_cdk_output">figure_title</a>) Public access mode S3 URL </p><p> S3 URL <a href="#handson_05_bashoutter_2">figure_title</a> </p><p><img src="`+la+'" alt="&quot;Bashoutter&quot; GUI "></p><p> &quot;API Endpoint URL&quot; <strong>API Gateway URL </strong> (API Gateway URL GUI ) &quot;REFRESH&quot; &quot;like&quot; </p><p>稿稿 &quot;POST&quot; &quot;POST&quot; &quot;REFRESH&quot; </p><h2 id="" tabindex="-1"> <a class="header-anchor" href="#" aria-label="Permalink to &quot;&quot;"></a></h2><p> Bashoutter SNS <a href="#simulating_many_apis"> API </a> </p><p>Bashoutter </p><p>使</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>CDK S3 <code>cdk destroy</code> S3 </p><p> S3 &quot;Actions&quot; &quot;Delete&quot; </p><p> 使 &lt;BUCKET NAME&gt; (&quot;<code>BashoutterBucketXXXX</code>&quot; ) </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">s3</span><span style="color:#839496;"> </span><span style="color:#2AA198;">rm</span><span style="color:#839496;"> </span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">BUCKET</span><span style="color:#839496;"> </span><span style="color:#2AA198;">NAM</span><span style="color:#839496;">E</span><span style="color:#859900;">&gt;</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--recursive</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">s3</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">rm</span><span style="color:#657B83;"> </span><span style="color:#859900;">&lt;</span><span style="color:#2AA198;">BUCKET</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">NAM</span><span style="color:#657B83;">E</span><span style="color:#859900;">&gt;</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--recursive</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><h2 id="-2" tabindex="-1"> <a class="header-anchor" href="#-2" aria-label="Permalink to &quot;&quot;"></a></h2><p></p><p>使 <a href="#sec_intro_serverless">Hands-on #5: </a> AWS Lambda, S3, DynamoDB <a href="#sec_bashoutter">Hands-on #6: Bashoutter</a> &quot;Bashoutter&quot; </p><p> </p><h1 id="" tabindex="-1"> <a class="header-anchor" href="#" aria-label="Permalink to &quot;&quot;"></a></h1><h1 id="appendix-" tabindex="-1">Appendix: <a class="header-anchor" href="#appendix-" aria-label="Permalink to &quot;Appendix: &quot;"></a></h1><p> AWS </p><ul><li><p>AWS (<a href="#sec:create_aws_account">AWS </a>)</p></li><li><p>AWS (<a href="#aws_secrets">AWS </a>)</p></li><li><p>AWS CLI (<a href="#aws_cli_install">AWS CLI </a>)</p></li><li><p>AWS CDK (<a href="#aws_cdk_install">AWS CDK </a>)</p></li><li><p>WSL (<a href="#sec:install_wsl">WSL </a>)</p></li><li><p>Docker (<a href="#sec:install_docker">Docker </a>)</p></li><li><p>Python venv (<a href="#venv_quick_guide">Python </a>)</p></li><li><p> Docker image 使 (<a href="#sec_handson_docker"> Docker image 使</a>)</p></li></ul><p>使 OS Linux/Mac/Windows Windows Windows Subsytem for Linux (WSL) 使 (<a href="#sec:install_wsl">WSL </a>)</p><p> <a href="https://hub.docker.com/repository/docker/tomomano/labc" target="_blank" rel="noreferrer">Docker </a> AWS CLI/CDK Python Docker 使便</p><h2 id="aws-" tabindex="-1">AWS <a class="header-anchor" href="#aws-" aria-label="Permalink to &quot;AWS &quot;"></a></h2><p> AWS <a href="https://aws.amazon.com/jp/register-flow/" target="_blank" rel="noreferrer"></a> </p><p> <a href="https://aws.amazon.com/console/" target="_blank" rel="noreferrer">AWS </a> <code>Create an AWS Account</code> (<a href="#fig:aws-signup-1">figure_title</a> )</p><p><img src="'+pa+'" alt=" (1): AWS "></p><p> (<a href="#fig:aws-signup-3">figure_title</a>)</p><p><img src="'+oa+'" alt=" (2): "></p><p> (<a href="#fig:aws-signup-4">figure_title</a>)</p><p><img src="'+ea+'" alt=" (3): "></p><p> (<a href="#fig:aws-signup-5">figure_title</a>) AWS AWS 使</p><p><img src="'+ta+'" alt=" (4): "></p><p> SMS (<a href="#fig:aws-signup-6">figure_title</a>) </p><p><img src="'+ra+'" alt=" (5): "></p><p> (<a href="#fig:aws-signup-8">figure_title</a>) Basic support </p><p><img src="'+ca+'" alt=" (6): "></p><p> (<a href="#fig:aws-signup-9">figure_title</a>) AWS </p><p><img src="'+ia+'" alt=" (7): "></p><h2 id="aws-" tabindex="-1">AWS <a class="header-anchor" href="#aws-" aria-label="Permalink to &quot;AWS &quot;"></a></h2><p>AWS AWS CLI AWS CDK AWS API AWS CLI/CDK 使 AWS <a href="https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html" target="_blank" rel="noreferrer"> &quot;Understanding and getting your AWS credentials&quot;</a> </p><ol><li><p>AWS </p></li><li><p> &quot;My Security Credentials&quot; (<a href="#fig:aws_secret_key_1">figure_title</a>)</p></li><li><p>&quot;Access keys for CLI, SDK, &amp; API access&quot; &quot;Create accesss key&quot; (<a href="#fig:aws_secret_key_2">figure_title</a>)</p></li><li><p> Access key ID, Secret access key ()</p></li><li><p></p></li><li><p> <code>~/.aws/credentials</code> 使 ( <a href="#aws_cli_install">AWS CLI </a>)</p></li></ol><p><img src="'+ya+'" alt="AWS 1"></p><p><img src="'+da+'" alt="AWS 2"></p><p><strong>AWS Educate Starter Account</strong> </p><ul><li><p>AWS Educate <code>vocareum</code> (<a href="#fig:vocareum_console">figure_title</a>)</p></li><li><p><code>Account Details</code> <code>AWS CLI: Show</code> </p></li><li><p><code>aws_access_key_id</code>, <code>aws_secret_access_key</code>, <code>aws_session_token</code> (<a href="#fig:vocareum_secret">figure_title</a>) <code>~/.aws/credentials</code> (<a href="#aws_cli_install">AWS CLI </a> ) <code>aws_session_token</code> </p></li><li><p> <code>~/.aws/config</code> AWS Starter Account <code>us-east-1</code> </p><p>[default] region = us-east-1 output = json</p></li><li><p> <code>default</code> <code>default</code> 使 ( <a href="#aws_cli_install">AWS CLI </a>)</p></li></ul><p><img src="'+ua+'" alt="vocareum "></p><p><img src="'+ba+`" alt="vocareum AWS "></p><h2 id="aws-cli-" tabindex="-1">AWS CLI <a class="header-anchor" href="#aws-cli-" aria-label="Permalink to &quot;AWS CLI &quot;"></a></h2><p> (Linux ) <a href="https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html" target="_blank" rel="noreferrer"></a> </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">curl</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip&quot;</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-o</span><span style="color:#839496;"> </span><span style="color:#2AA198;">&quot;awscliv2.zip&quot;</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">unzip</span><span style="color:#839496;"> </span><span style="color:#2AA198;">awscliv2.zip</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">sudo</span><span style="color:#839496;"> </span><span style="color:#2AA198;">./aws/install</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">curl</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip&quot;</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-o</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">&quot;awscliv2.zip&quot;</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">unzip</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">awscliv2.zip</span></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">sudo</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">./aws/install</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p></p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--version</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--version</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> (<a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html" target="_blank" rel="noreferrer"></a>)</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">configure</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">configure</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> <code>AWS Access Key ID</code>, <code>AWS Secret Access Key</code> <a href="#aws_secrets">AWS </a> <code>Default region name</code> ( <code>ap-northeast-1</code> =) <code>Default output format</code> <code>json</code> </p><p> <code>~/.aws/credentials</code> <code>~/.aws/config</code>  <code>cat</code> 使</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cat</span><span style="color:#839496;"> </span><span style="color:#2AA198;">~/.aws/credentials</span></span>
<span class="line"><span style="color:#839496;">[default]</span></span>
<span class="line"><span style="color:#268BD2;">aws_access_key_id</span><span style="color:#839496;"> </span><span style="color:#2AA198;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">XXXXXXXXXXXXXXXXXX</span></span>
<span class="line"><span style="color:#268BD2;">aws_secret_access_key</span><span style="color:#839496;"> </span><span style="color:#2AA198;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">YYYYYYYYYYYYYYYYYYY</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cat</span><span style="color:#839496;"> </span><span style="color:#2AA198;">~/.aws/config</span></span>
<span class="line"><span style="color:#839496;">[profile default]</span></span>
<span class="line"><span style="color:#268BD2;">region</span><span style="color:#839496;"> </span><span style="color:#2AA198;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ap-northeast-1</span></span>
<span class="line"><span style="color:#268BD2;">output</span><span style="color:#839496;"> </span><span style="color:#2AA198;">=</span><span style="color:#839496;"> </span><span style="color:#2AA198;">json</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cat</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">~/.aws/credentials</span></span>
<span class="line"><span style="color:#657B83;">[default]</span></span>
<span class="line"><span style="color:#268BD2;">aws_access_key_id</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">XXXXXXXXXXXXXXXXXX</span></span>
<span class="line"><span style="color:#268BD2;">aws_secret_access_key</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">YYYYYYYYYYYYYYYYYYY</span></span>
<span class="line"></span>
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cat</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">~/.aws/config</span></span>
<span class="line"><span style="color:#657B83;">[profile default]</span></span>
<span class="line"><span style="color:#268BD2;">region</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ap-northeast-1</span></span>
<span class="line"><span style="color:#268BD2;">output</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">=</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">json</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><p><code>~/.aws/credentials</code> <code>~/.aws/config</code> AWS CLI </p><p> <code>[default]</code> 使 default <code>[myprofile]</code> </p><p>AWS CLI 使</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws</span><span style="color:#839496;"> </span><span style="color:#2AA198;">s3</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ls</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--profile</span><span style="color:#839496;"> </span><span style="color:#2AA198;">myprofile</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">s3</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ls</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--profile</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">myprofile</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> <code>--profile</code> </p><p> <code>--profile</code> <code>AWS_PROFILE</code> </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">export</span><span style="color:#839496;"> </span><span style="color:#2AA198;">AWS_PROFILE=myprofile</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">export</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">AWS_PROFILE=myprofile</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p></p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#93A1A1;font-weight:bold;">export</span><span style="color:#839496;"> </span><span style="color:#268BD2;">AWS_ACCESS_KEY_ID</span><span style="color:#859900;">=</span><span style="color:#2AA198;">XXXXXX</span></span>
<span class="line"><span style="color:#93A1A1;font-weight:bold;">export</span><span style="color:#839496;"> </span><span style="color:#268BD2;">AWS_SECRET_ACCESS_KEY</span><span style="color:#859900;">=</span><span style="color:#2AA198;">YYYYYY</span></span>
<span class="line"><span style="color:#93A1A1;font-weight:bold;">export</span><span style="color:#839496;"> </span><span style="color:#268BD2;">AWS_DEFAULT_REGION</span><span style="color:#859900;">=</span><span style="color:#2AA198;">ap-northeast-1</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#586E75;font-weight:bold;">export</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">AWS_ACCESS_KEY_ID</span><span style="color:#859900;">=</span><span style="color:#2AA198;">XXXXXX</span></span>
<span class="line"><span style="color:#586E75;font-weight:bold;">export</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">AWS_SECRET_ACCESS_KEY</span><span style="color:#859900;">=</span><span style="color:#2AA198;">YYYYYY</span></span>
<span class="line"><span style="color:#586E75;font-weight:bold;">export</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">AWS_DEFAULT_REGION</span><span style="color:#859900;">=</span><span style="color:#2AA198;">ap-northeast-1</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p> <code>~/.aws/credentials</code> 使 (<a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html" target="_blank" rel="noreferrer"></a>)</p><p><strong>AWS Educate Starter Account</strong> <code>us-east-1</code> () AWS Educate Starter Account 使 default region <code>us-east-1</code> </p><h2 id="aws-cdk-" tabindex="-1">AWS CDK <a class="header-anchor" href="#aws-cdk-" aria-label="Permalink to &quot;AWS CDK &quot;"></a></h2><p> (Linux ) <a href="https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html" target="_blank" rel="noreferrer"></a> </p><p>Node.js </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">sudo</span><span style="color:#839496;"> </span><span style="color:#2AA198;">npm</span><span style="color:#839496;"> </span><span style="color:#2AA198;">install</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-g</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws-cdk</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">sudo</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">npm</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">install</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-g</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws-cdk</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> AWS CDK version 1.100.0 CDK API API version 1.100.0 使</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">npm</span><span style="color:#839496;"> </span><span style="color:#2AA198;">install</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-g</span><span style="color:#839496;"> </span><span style="color:#2AA198;">aws-cdk@1.100</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">npm</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">install</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-g</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">aws-cdk@1.100</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p></p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--version</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--version</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> AWS OK</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">bootstrap</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">bootstrap</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p><code>cdk bootstrap</code> AWS <code>~/.aws/config</code> 使 <a href="#aws_cli_install">AWS CLI </a> 使</p><p>AWS CDK AWS CLI <a href="#aws_cli_install">AWS CLI </a> </p><h2 id="wsl-" tabindex="-1">WSL <a class="header-anchor" href="#wsl-" aria-label="Permalink to &quot;WSL &quot;"></a></h2><p> AWS CLI Python UNIX Linux Mac OS Windows <a href="https://docs.microsoft.com/en-us/windows/wsl/" target="_blank" rel="noreferrer">Windows Subsystem for Linux (WSL)</a> Linux <a href="https://www.cygwin.com/" target="_blank" rel="noreferrer">Cygwin</a> Linux WSL </p><p>WSL Windows OS Linux Microsoft Ubuntu Linux distribution Linux 使</p><p> <a href="https://docs.microsoft.com/en-us/windows/wsl/compare-versions#whats-new-in-wsl-2" target="_blank" rel="noreferrer">WSL 2</a> WSL 2 <a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10" target="_blank" rel="noreferrer"></a> </p><p>使 OS Windows 10 (Pro Home ) 使 Windows 10 WSL X64 Version 1903, Build 18362 Windows </p><p> Administrator PowerShell (<a href="#fig:powershell">figure_title</a>) Windows <code>powershell</code> PowerShell <code>Run as administrator</code> </p><p><img src="`+Aa+'" alt=" PowerShell "></p><p>PowerShell </p><div class="language-powershell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">powershell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">dism.exe</span><span style="color:#839496;"> </span><span style="color:#859900;">/</span><span style="color:#839496;">online </span><span style="color:#859900;">/</span><span style="color:#268BD2;">enable-feature</span><span style="color:#839496;"> </span><span style="color:#859900;">/</span><span style="color:#839496;">featurename:Microsoft</span><span style="color:#859900;">-</span><span style="color:#839496;">Windows</span><span style="color:#859900;">-</span><span style="color:#839496;">Subsystem</span><span style="color:#859900;">-</span><span style="color:#839496;">Linux </span><span style="color:#859900;">/</span><span style="color:#839496;">all </span><span style="color:#859900;">/</span><span style="color:#839496;">norestart</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">dism.exe</span><span style="color:#657B83;"> </span><span style="color:#859900;">/</span><span style="color:#657B83;">online </span><span style="color:#859900;">/</span><span style="color:#268BD2;">enable-feature</span><span style="color:#657B83;"> </span><span style="color:#859900;">/</span><span style="color:#657B83;">featurename:Microsoft</span><span style="color:#859900;">-</span><span style="color:#657B83;">Windows</span><span style="color:#859900;">-</span><span style="color:#657B83;">Subsystem</span><span style="color:#859900;">-</span><span style="color:#657B83;">Linux </span><span style="color:#859900;">/</span><span style="color:#657B83;">all </span><span style="color:#859900;">/</span><span style="color:#657B83;">norestart</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>The operation completed successfully. WSL enable </p><p> Administrator PowerShell </p><div class="language-powersh vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">powersh</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> The operation completed successfully. </p><p> Linux kernel update package <a href="https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi" target="_blank" rel="noreferrer">https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi</a></p><p> </p><p> PowerShell </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">wsl</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--set-default-version</span><span style="color:#839496;"> </span><span style="color:#D33682;">2</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">wsl</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--set-default-version</span><span style="color:#657B83;"> </span><span style="color:#D33682;">2</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> Linux distribution Ubuntu 20.04 </p><p>Microsoft store <code>Ubuntu</code> Ubuntu 20.04 LTS Get (<a href="#fig:microsoft_store">figure_title</a>) Ubuntu 20.04 </p><p><img src="'+ma+'" alt="Microsoft store Ubuntu 20.04 "></p><p>Ubuntu 20.04 </p><p> WSL2 WSL2 Windows <code>Ubuntu</code> Ubuntu 20.04 (<a href="#fig:ubuntu">figure_title</a>) </p><p><img src="'+ha+'" alt="Ubuntu 20.04 "></p><p> (<a href="#fig:wsl_window">figure_title</a>) <code>ls</code>, <code>top</code> WSL </p><p><img src="'+Ba+'" alt="WSL "></p><p> <a href="https://docs.microsoft.com/en-us/windows/terminal/get-started" target="_blank" rel="noreferrer">Windows Terminal</a> 使 WSL 使 </p><h2 id="docker-" tabindex="-1">Docker <a class="header-anchor" href="#docker-" aria-label="Permalink to &quot;Docker &quot;"></a></h2><p>Docker OS </p><p>Mac Docker Desktop <a href="https://docs.docker.com/docker-for-mac/install/" target="_blank" rel="noreferrer">Docker </a> Mac Docker Desktop <code>Applications</code> <a href="https://docs.docker.com/docker-for-mac/install/" target="_blank" rel="noreferrer"></a> </p><p>Windows Docker Desktop WSL 2 <a href="https://docs.docker.com/desktop/windows/install/" target="_blank" rel="noreferrer"></a> Docker Desktop WSL <code>docker</code> 使</p><p>Linux ( Ubuntu ) <a href="https://docs.docker.com/engine/install/ubuntu/" target="_blank" rel="noreferrer"></a> </p><p> Docker Docker </p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">curl</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-fsSL</span><span style="color:#839496;"> </span><span style="color:#2AA198;">https://get.docker.com</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-o</span><span style="color:#839496;"> </span><span style="color:#2AA198;">get-docker.sh</span></span>\n<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">sudo</span><span style="color:#839496;"> </span><span style="color:#2AA198;">sh</span><span style="color:#839496;"> </span><span style="color:#2AA198;">get-docker.sh</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">curl</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-fsSL</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">https://get.docker.com</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-o</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">get-docker.sh</span></span>\n<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">sudo</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">sh</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">get-docker.sh</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p> root <code>docker</code> 使 <code>sudo</code> 使 <code>docker</code> ( <a href="https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user" target="_blank" rel="noreferrer"> &quot;Post-installation steps for Linux&quot;</a> )</p><p> <code>docker</code> <code>docker</code> </p><div class="language-sh vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">sudo</span><span style="color:#839496;"> </span><span style="color:#2AA198;">groupadd</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">sudo</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">groupadd</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>使 <code>docker</code> </p><div class="language-sh vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">sudo</span><span style="color:#839496;"> </span><span style="color:#2AA198;">usermod</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-aG</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#268BD2;">$USER</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">sudo</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">usermod</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-aG</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">$USER</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> </p><p></p><div class="language-sh vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run</span><span style="color:#839496;"> </span><span style="color:#2AA198;">hello-world</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">hello-world</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p><code>sudo</code> </p><h2 id="python-venv-" tabindex="-1">Python <code>venv</code> <a class="header-anchor" href="#python-venv-" aria-label="Permalink to &quot;Python `venv` &quot;"></a></h2><p> numpy scipy Python </p><p> Python <a href="https://docs.python.org/3/tutorial/venv.html" target="_blank" rel="noreferrer">venv</a>, <a href="https://github.com/pyenv/pyenv" target="_blank" rel="noreferrer">pyenv</a>, <a href="https://docs.conda.io/en/latest/" target="_blank" rel="noreferrer">conda</a> 使</p><p> <code>venv</code> Python 便 <code>pyenv</code> <code>conda</code> </p><p><code>venv</code> 使</p><div class="language-sh vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#839496;"> </span><span style="color:#2AA198;">venv</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">venv</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> <code>.env/</code> </p><p></p><div class="language-sh vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">source</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">source</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p></p><p> <code>(.env)</code> (<a href="#fig_venv_prompt">figure_title</a>) &quot; venv &quot; </p><p><img src="'+ga+'" alt="venv "></p><p> <code>pip</code> <code>.env/</code> 使</p><p>Python <code>requirements.txt</code> <code>requirements.txt</code> </p><div class="language-sh vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pip</span><span style="color:#839496;"> </span><span style="color:#2AA198;">install</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#839496;"> </span><span style="color:#2AA198;">requirements.txt</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pip</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">install</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">requirements.txt</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> Python </p><p>venv <code>.env</code> </p><h2 id="-docker-image-使" tabindex="-1"> Docker image 使 <a class="header-anchor" href="#-docker-image-使" aria-label="Permalink to &quot; Docker image 使&quot;"></a></h2><p> Node.js, Python, AWS CDK Docker image 使</p><p> Docker = </p><p>Docker <a href="https://hub.docker.com/repository/docker/tomomano/labc" target="_blank" rel="noreferrer">Docker Hub</a> Docker GitHub <a href="https://github.com/tomomano/learn-aws-by-coding-source-code/blob/main/docker/Dockerfile" target="_blank" rel="noreferrer">docker/Dockerfile</a> </p><p></p><div class="language-sh vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-it</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tomomano/labc:latest</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-it</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tomomano/labc:latest</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> Docker Hub (pull) 使</p><p> ( <code>-it</code> )</p><div class="language-sh vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">root@aws-handson:~/programlisting</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">root@aws-handson:~/programlisting</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> <code>ls</code> <code>handson/</code> <code>cd</code> </p><div class="language-sh vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cd</span><span style="color:#839496;"> </span><span style="color:#2AA198;">handson</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cd</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">handson</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p></p><p> virtualenv (<a href="#sec_handson_ec2_run"></a> ) 使 virtualenv </p><p>AWS <a href="#aws_cli_install">AWS CLI </a> <code>AWS_ACCESS_KEY_ID</code> <strong></strong> <code>~/.aws/credentials</code> <strong></strong> </p><div class="language-sh vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-it</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-v</span><span style="color:#839496;"> </span><span style="color:#2AA198;">~/.aws:/root/.aws:ro</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tomomano/labc:latest</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-it</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-v</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">~/.aws:/root/.aws:ro</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tomomano/labc:latest</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p> <code>~/.aws</code> <code>/root/.aws</code> <code>:ro</code> read-only read-only </p><p><code>/root/</code> SSH 使</p><h1 id="" tabindex="-1"> <a class="header-anchor" href="#" aria-label="Permalink to &quot;&quot;"></a></h1><p> <a href="https://creativecommons.org/licenses/by-nc-nd/4.0/" target="_blank" rel="noreferrer">CC BY-NC-ND 4.0</a> </p><p>使 </p>',1319),Ca=[Da];function Sa(wa,Pa,Ea,Ia,za,xa){return ka(),fa("div",null,Ca)}const Ja=_a(qa,[["render",Sa]]);export{Ya as __pageData,Ja as default};