Pythonのseleniumを使ってWeb画面操作を自動化する~サンプルを使ってWebスクライピンングのチャレンジ~

概要~Pythonのseleniumを使って値取得/値入力/クリック/スクリーンショット等、画面操作を自動化する~

少しずつ毎日のWeb生活を快適にするために最近は Python selenium 使ったWeb画面自動化処理を行っています。
今回の投稿は、その自動化処理をする上で繰り返し使える基本コードのまとめから、ちょっとした便利ノウハウをまとめた内容になっています。
これを実行すれば誰でも簡単にWeb画面の自動化処理ができ、日々単調なルーチンワークから脱却できるので、ぜひ試してみてください。

対象読者

  • Pythonを触ったことがある人
  • ブラウザの自動化で楽したい人

出来るようになること

  • Web画面を自動操作する
    • 画面を開く
    • 特定のHTML要素から値を取得する
    • 特定のHTML要素に値を入力する
    • ボタンをクリックする
  • Web画面のスクリーンショットを取得する

事前準備

今回は selenium を使って自動化します。その為に2つの事前準備が必要なのでその準備をします。

事前準備1~ブラウザのドライバをダウンロード~

Web画面の自動化はブラウザの専用ドライバーを使って画面操作を行います。そのためにドライバーをダウンロードします。ドライバーはブラウザ別に用意されているのでお好みのブラウザのドライバーをダウンロードしましょう。(どのドライバーでも自動化のソースコードは同じです)

chromeドライバー

https://chromedriver.chromium.org/downloads

Edge ドライバー

https://developer.microsoft.com/ja-jp/microsoft-edge/tools/webdriver/

事前準備2~seleniumのインストール~

これはpipを使うだけで簡単です。以下のコマンド実行します。

pip install selenium

事前準備は以上です!では、さっそくWeb画面の自動化にチャレンジしていきましょう!!

補足~Google Colaboratoryでのselenium実行~

seleniumu は Google Colaboratory でも実行できるので、サクッと試してみたい時はこちらがおすすめです。
その場合、ドライバー、selenium のインストールは以下のコマンドを実行しておくことになります。

!apt-get update
!apt install chromium-chromedriver
!cp /usr/lib/chromium-browser/chromedriver /usr/bin
!pip install selenium
!pip freeze

Google Colaboratory では、日本語フォントがインストールされていないので文字化けが発生する場合は、以下のコマンドで日本語フォントをダウンロードします。

# 日本語フォントをダウンロードする。
!apt-get -y install fonts-ipafont-gothic

それでは、本編に戻ります!

ページを開く

最初は最も基本的な特定のページを開く操作です。
getメソッドに開きたいページのURLを指定します。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By

# ドライバーの設定
CHROME_DRIVER = "{ドライバーの格納フォルダ}\\chromedriver"

driver = webdriver.Chrome(CHROME_DRIVER,options=Options())

# 指定したURLの画面を開く
driver.get("http://www.google.com")

# ブラウザを閉じる
driver.quit()

【参考ドキュメント】
https://www.selenium.dev/ja/documentation/webdriver/drivers/options/#normal-default

サンプルソースの{ドライバー格納フォルダ}を自身でドライバーを保存したフォルダに変更して実行してみてください。(サンプルはChromeドライバーを使った例になります)

簡単にブラウザの特定のページが開けたと思います。すぐに閉じてしまっているので一瞬だったかもしれませんが、ここから自動化処理のスタートです!

要素を探す

seleniumで実現したいことはWeb画面の自動操作だと思います。
その中で最も基本的なことは操作したい要素を探す(指定する)ことであり、慣れるまでここが最も大変と思うのでこの部分を重点的に説明します。

要素の選択(指定)

要素の選択(指定)方法には以下の8種類があります。
(ロケータと呼びます)

ロケータ詳細コード例
idid属性が一致する要素を探すdriver.find_element(By.ID,"abc")
class nameclass名に値を含む要素を探す(複合クラス名は使えない)driver.find_elements(By.CLASS_NAME,"abc")
css selectorCSSセレクタが一致する要素を探すdriver.find_elements(By.CSS_SELECTOR,"abc")
xpathXPathと一致する要素を探すdriver.find_elements(By.XPATH,"abc")
link texta要素のテキストが一致する要素を探すdriver.find_elements(By.LINK_TEXT,"abc")
partial link texta要素のテキストが部分一致する要素を探すdriver.find_elements(By.PARTIAL_LINK_TEXT,"abc")
namename属性が一致する要素を探すdriver.find_elements(By.NAME,"abc")
tag nameタグ名が一致する要素を探すdriver.find_elements(By.TAG_NAME,"abc")

【参考ドキュメント】
https://www.selenium.dev/ja/documentation/webdriver/elements/locators/#%E8%A6%81%E7%B4%A0%E9%81%B8%E6%8A%9E%E3%81%AE%E6%96%B9%E6%B3%95

この表は私が良く使う順に記載しています。
次から具体的に説明していきますが、コード例のidだけはfind_element最後の(s)がないことに注意してください。
これはidだけはページ内で1つというHTMLのルールがあるため、1つの要素が返却されることを意味しています。
ちなみに他のロケータにもfind_elementがありますが、先頭の1つの要素が取れるという仕様になっており、限られたケースでしか使用しないため、私は基本的にはid以外はfind_elements最後の(s)ありのメソッドを使用しています。

使用優先度1:ID指定による要素選択

ここからは具体例とともにそれぞれの要素選択方法のサンプルを記載していきます。
まずはID指定です。取得したい要素にid指定の属性があった場合、迷わずこれを使えば良いと思います。

サンプルコード

login_form = driver.find_element(By.ID, 'loginForm')

サンプルHTML

<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
  </form>
 </body>
</html>

実行結果サンプル

login_form = driver.find_element(By.ID, 'loginForm')
print(login_form.tag_name)
# form が出力される

【参考ドキュメント】
https://selenium-python.readthedocs.io/locating-elements.html#locating-by-id

これで formタグの要素(element)が取得できます。id属性があれば最も簡単です。

使用優先度2:クラス名指定による要素選択

次はクラス名指定に要素選択方法です。
idがなくてもクラスが指定されているケースはよくあるので良く使用しています。
(普段使うのは find_elements メソッドですが、サンプルをわかりやすくするため find_element (sなし)メソッドを使っています。)

コードサンプル

content = driver.find_element(By.CLASS_NAME, 'content')

HTMLサンプル

<html>
 <body>
  <p class="content">Site content goes here.</p>
</body>
</html>

実行結果サンプル

content = driver.find_element(By.CLASS_NAME, 'content')
print(content.text)
# Site content goes here.

【参考ドキュメント】
https://selenium-python.readthedocs.io/locating-elements.html#locating-elements-by-class-name

クラス名に複数の指定がある場合

クラス名指定は結構便利ですが、1つ注意点があります。
クラス名はよく複数指定されるケースがあります。↓こんな場合、

<div class="content test">TEST</div>

こんな場合は、.(ドット)区切りで指定します。

content = driver.find_element(By.CLASS_NAME, 'content.test')

これで取得できるのですが、たまに取得出来ないケースがあるようです。
私の場合は、AWS Lambdaがこのケースで取得できず、結局次のCSSセレクタを使って取得しました。(ちなみにLambdaは、Python 3.7 Selenium 3.141でした)

使用優先度3:CSSセレクタ指定による要素選択

次にCSSセレクタです。
CSSに詳しい人なら迷わず使えますね。私もクラス名指定の所で書いたクラス名指定ができないケースがあるので、最近はこれを一番多用しています。

コードサンプル

content = driver.find_element(By.CSS_SELECTOR, 'p.content')

HTMLサンプル

<html>
 <body>
  <p class="content">Site content goes here.</p>
</body>
</html>

実行結果サンプル

content = driver.find_element(By.CSS_SELECTOR, 'p.content')
print(content.text)
# Site content goes here.

【参考ドキュメント】
https://selenium-python.readthedocs.io/locating-elements.html#locating-elements-by-css-selectors

クラス名にタブを.(ドット)区切りで指定というクラス名指定と同じようなシンプルな指定で使えるので簡単ですね。

クラス名の所で記載した複数のクラスが指定されていた場合の指定方法は以下になります。

# <div class="a b">text</div> の場合
find_element(By.CLASS_NAME, "a.b")# ←Lambda NG
find_element(By.CSS_SELECTOR, "div.a.b")# ←OK
find_element(By.XPATH, "//div[@class='a b']")# ←XPathのこれもOK

使用優先度4:XPath指定による要素選択

次はXPathによる指定です。
XPathは柔軟な指定ができるので、私はクラス名やCSSセレクタ指定で複数の要素が取得できてしまうケースで、敢えて1つのみの要素を指定したい場合とかに使用しています。

コードサンプル

login_form = driver.find_element(By.XPATH, "/html/body/form[1]")
login_form = driver.find_element(By.XPATH, "//form[1]")
login_form = driver.find_element(By.XPATH, "//form[@id='loginForm']")

HTMLサンプル

<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
   <input name="continue" type="button" value="Clear" />
  </form>
</body>
</html>

実行結果サンプル

login_form = driver.find_element(By.XPATH, "/html/body/form[1]")
login_form = driver.find_element(By.XPATH, "//form[1]")
login_form = driver.find_element(By.XPATH, "//form[@id='loginForm']")
print(login_form.tag_name)
# form が出力される(どの指定方法でも同じ結果です)

【参考ドキュメント】

https://selenium-python.readthedocs.io/locating-elements.html#locating-by-xpath

3種類の指定方法をサンプルにしていますが、取得結果はどれも同じです。

  1. htmlタグからの絶対パスで指定しています。直感的な指定が可能ですが、HTML構造が変わったら取得できなくなるので使用ケースは注意が必要です
  2. formタグの1つ目という指定です。// を使用すること絶対パス指定が不要になります。
  3. formタグ、かつ、id指定という指定の仕方です。2.のケースよりわかりやすく指定できますね。

使用優先度5:a要素テキスト指定による要素選択

次はa(アンカー)タグ内のテキスト指定する方法になります。
完全一致で指定する LINK_TEXT と 部分一致で指定する PARTIAL_LINK_TEXT があります。

コードサンプル

continue_link = driver.find_element(By.LINK_TEXT, 'Continue')
continue_link = driver.find_element(By.PARTIAL_LINK_TEXT, 'Can')

HTMLサンプル

<html>
 <body>
  <p>Are you sure you want to do this?</p>
  <a href="continue.html">Continue</a>
  <a href="cancel.html">Cancel</a>
</body>
</html>

実行結果サンプル

continue_link = driver.find_element(By.LINK_TEXT, 'Continue')
print(continue_link.text)
# Continue
continue_link = driver.find_element(By.PARTIAL_LINK_TEXT, 'Can')
print(continue_link.text)
# Cancel

【参考ドキュメント】
https://selenium-python.readthedocs.io/locating-elements.html#locating-hyperlinks-by-link-text

この指定方法は、Web画面に表示されている文字をそのまま使えるので結構便利だったりします。ただ、最近のWebでアンカータグがどれだけあるのか、画面表示の文字は頻繁に変わらないか、と考えると使用ケースは限られるため、個人的に使用ケースがあまりないかなと思っています。

使用優先度6:name属性指定による要素選択

次はname属性による指定です。
先に紹介したクラス名指定とよく勘違いするのですが、こちらはname属性になります。

コードサンプル

username = driver.find_element(By.NAME, 'username')
password = driver.find_element(By.NAME, 'password')

HTMLサンプル

<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
   <input name="continue" type="button" value="Clear" />
  </form>
</body>
</html>

実行結果サンプル

username = driver.find_element(By.NAME, 'username')
print(username.tag_name)
# input

【参考ドキュメント】
https://selenium-python.readthedocs.io/locating-elements.html#locating-by-name

この指定ケースも直感的でわかりやすいのですが、name属性が指定された要素がそんなにあるかな。。。という印象なので、どちらかというとクラス名指定を良く使っています。

使用優先度7:タグ名指定による要素選択

最後は、タグ名による指定です。
これはシンプルですね。タグ名をそのまま指定します。

コードサンプル

heading1 = driver.find_element(By.TAG_NAME, 'h1')

HTMLサンプル

<html>
 <body>
  <h1>Welcome</h1>
  <p>Site content goes here.</p>
</body>
</html>

実行結果サンプル

heading1 = driver.find_element(By.TAG_NAME, 'h1')
print(heading1.text)
# Welcome

【参考ドキュメント】
https://selenium-python.readthedocs.io/locating-elements.html#locating-by-name

使用方法はシンプルなのですが、タグの直接指定がそれほど使用ケースがない気がしているので最後の紹介になります。

補足~便利?コードサンプル~

ここからは私が個人的に良く使っているコードサンプルの紹介です。

要素取得判定

冒頭で記載した通り、私は find_elements(find_elementではなく)を多用しています。
そのため、要素が意図通り取得できたかを以下のように確認するメソッドを使って判定しています。

コードサンプル

# 要素取得判定関数
def element_check(element, target):
    if len(element) > 0:
        print(target + " 個数:" + str(len(element)))
        return True
    else:
        print(target + ":要素が見つかりません")
        return False

# 要素取得判定関数呼び出し例
elements = driver.find_elements(By.TAG_NAME, 'a')
if element_check(elements, 'a') :
    for element in elements:
        print(element.text)

要素に対する操作コードサンプル

要素を取得した後の操作は基本的には以下の操作と思っています。
これだけは覚えておけば基本的な操作はできるかなというものを記載しておきます。

  • テキスト取得
  • テキスト入力
  • テキストクリア
  • クリック

コードサンプル

element.text
element.send_keys("abc")
element.clear()
element.click()

ページのタイトルを取得する

各処理を始める前にまずタイトルを取得する場合、以下のコードで簡単に取得できます。

driver = webdriver.Chrome(CHROME_DRIVER,options=Options())
print(driver.title)

HTMLを表示する

意図した動作にならない場合など、実際のHTMLを確認したいケースがあると思います。その時は、以下のコードでHTMLを取得します。

driver = webdriver.Chrome(CHROME_DRIVER,options=Options())
print(driver.page_source.encode('UTF-8'))

スクリーンショットを保存する

Web画面の操作結果を保存する、意図した動作になっているか途中の画面遷移を保存する際に利用するのがスクリーンショットです。
seleniumu では簡単にスクリーンショットを取ることができます。

コードサンプル

# スクロールを含めて全画面のスクリーンショットを取得するためヘッドレスモードにする
options = Options()
options.add_argument('--headless')
driver = webdriver.Chrome(CHROME_DRIVER,options=options)

# 全画面のスクリーンショット取得
w = driver.execute_script('return document.body.scrollWidth')
h = driver.execute_script('return document.body.scrollHeight')
driver.set_window_size(w, h)
driver.save_screenshot("screenshot.png")

指定した要素部分のみの一部のスクリーンショットを保存する

上の例だと全画面表示になってしまうため、必要な要素部分だけ取得したい場合(例えば特定のframe内だけ取得したい場合)は事前に要素取得してから、スクリーンショットを保存します。

# スクロールを含めて全画面のスクリーンショットを取得するためヘッドレスモードにする
options = Options()
options.add_argument('--headless')
driver = webdriver.Chrome(CHROME_DRIVER,options=options)

# 一部要素の全画面スクリーンショット取得
w = driver.execute_script('return document.body.scrollWidth')
h = driver.execute_script('return document.body.scrollHeight')
driver.set_window_size(w, h)
# 取得したい要素を指定する(ID指定でなくても良い)
element = driver.find_element(By.ID, 'main-element')
png = element.screenshot_as_png
# 任意のファイル名を指定してpngファイルに保存
with open('ElementScreenshot.png', 'wb') as f:
    f.write(png)

ドライバーの自動更新

ドライバーのバージョンは自分が普段使用するブラウザのバージョンと一致しておく必要があるため、ブラウザのバージョンアップが定期的にあり、その度にドライバーのダウンロードが面倒という方は以下でドライバーのインストール含めて自動化できます。

# Webdriver ManagerでChromeDriverを取得
from webdriver_manager.chrome import ChromeDriverManager
# ChromeDriverManager().install()を指定して自動インストール
driver = webdriver.Chrome(ChromeDriverManager().install(),options=options)

ちなみにブラウザとドライバーのバージョンは不一致の場合、以下のエラーメッセージが出力され、処理が異常終了します。

selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 104
Current browser version is 106.0.5249.119 with binary path C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

逆引き参考ページ

以下はseleniumでやりたいことの目的別に逆引きができるサイトになります。

https://www.seleniumqref.com/api/webdriver_gyaku.html

属性ごとの取得方法まとめ

以下は属性ごとに指定方法がまとめられて非常に参考になるサイトになります。
XPathの使い方がうまい。

https://qiita.com/VA_nakatsu/items/0095755dc48ad7e86e2f

「Chrome の自動操作を一通り」

タイトルの通り、「Chrome の自動操作を一通り」まとめてくれているサイトになります。網羅的に書かれていて非常に参考になります。

https://qiita.com/memakura/items/20a02161fa7e18d8a693

まとめ

今回はPythonのSeleniumでWeb画面操作を自動化する基礎をまとめてみました。
自分なりによく使う辞書的な位置づけでまとめてみたので、同じような人の役に立てれば嬉しいです(^^)

gspreadライブラリを使ってPythonでGoogleスプレッドシートの操作(値追加・値取得・行追加・行削除)する

概要〜Pythonでgspreadライブラリを公式ページにならってやってみてAWS LambdaでGoogleスプレッドシートに定期的に記録する〜

皆さん日々記録を取りたい時どこに記録をしていますか?
私はGoogleスプレッドシートを多用しています。
なぜなら、、、

  • Googleアカウントをもっていれば誰でも無料で使える
  • Webブラウザがあれば携帯、PC問わずアクセスできる
  • ちょっと修正したいなと思った時の修正がExcelと同じ操作感なので容易

などの理由からです。
日々自動化して記録をしたいことがあるのですが、その都度DBを用意して記録するのはそれなりに手間がかかるので私はGoogleスプレッドシートを使って日々の自動化処理を実行しています。
今回はその時に役に立つ、PythonからGoogleスプレッドシートに簡単にアクセスできるgspreadライブラリを調べたのでその整理内容になります。

出来るようになること

  • Googleスプレッドシートを開く
  • Googleスプレッドシートのシートを指定する
  • Googleスプレッドシートの値を取得する
  • Googleスプレッドシートに値を書き込む
  • Googleスプレッドシートに行を追加する/行を削除する

最終的なコードは以下になります。
これだけのコードでGoogleスプレッドシートに対する最低限の操作が出来るのでかなり簡単だったと思います。

import gspread
import json

#認証処理
gc  = gspread.service_account_from_dict('認証情報のJSON')

# ファイル名指定で開く
sh = gc.open('ファイル名')

# シート名指定
worksheet = sh.worksheet("シート名")

# A1等のラベル指定して値取得
val = worksheet.acell('B1').value

# ラベル指定して値を更新
worksheet.update('B1', 'Bingo!')

# 最終行に引数のリストの内容を1行追加
worksheet.append_row(['A','B','C'])

公式ページ

gspreadの公式ページは以下になります。

https://docs.gspread.org/en/latest/

前提条件

前提条件としてGoogleスプレッドシートにアクセスするための認証情報(JSONファイル)をGCPで取得する必要があります。(GCPを利用するのでGCPアカウントが必要になります)
今回はgspreadライブラリの説明をメインとした記事なのでこの部分は割愛しますが、以下のようなコードで取得した認証情報を使って認証処理を実装します。
gspreadライブラリを使えばたった3行です。簡単ですね。

import gspread
import json

#認証処理
gc  = gspread.service_account_from_dict('認証情報のJSON')

認証処理の更新ページURLは以下になります。
実装方法は上のサンプル以外にもあるので必要なら別の方法を確認してみてください。

https://docs.gspread.org/en/latest/oauth2.html

ワークブックを開く

それでは実際のGoogleスプレッドシートの操作の説明に移ります。
まず最初はGoogleスプレッドシートの操作するスプレッドシートを指定して開きます。
指定方法にはファイル名を指定、キーを指定、URLの指定の3つの方法があるので、扱い易い方法で開けばいいと思います。個人的にはファイル名指定が一番直感的に扱えるかなと思っています。

# ファイル名指定で開く
sh = gc.open('ファイル名')

# スプレッドシートのキー指定で開く
sh = gc.open_by_key('スプレッドシートキー')

# URL指定で開く
sh = gc.open_by_url('URL')

# スプレッドシートを取得したらスプレッドシートの内容を表示してみる
print(sh.title) #スプレッドシートのタイトルを表示する
print(sh.id) # スプレッドシートキーを表示する

ファイルを開く部分の公式ページは以下になります。

https://docs.gspread.org/en/latest/user-guide.html#opening-a-spreadsheet

シート選択

スプレッドシートが開けたら次はシートを選択します。
この辺りの操作間はExcel操作と一緒ですね。
こちらも複数の方法がありますが、基本的にはインデックスを指定するか、シート名を指定する方法になります。個人的にはこちらもシート名を指定する方法が直感的かなと思います。

# シートのインデックスを指定(先頭は0になります)
worksheet = sh.get_worksheet(0)

# シート名指定
worksheet = sh.worksheet("シート名")

# 先頭のシート指定(先頭のシートだけです。sheet2にしたところで2番目のシートは指定できません)
worksheet = sh.sheet1

# すべてのシートをリストで取得する
worksheet_list = sh.worksheets()

# シートを取得したらシートの内容を表示してみる
print(worksheet.title)  # シート名表示
print(worksheet.id) # シートID表示

公式ページは以下になります。

https://docs.gspread.org/en/latest/user-guide.html#selecting-a-worksheet

値取得

シートまで取得できたので、それではここから値を取得していきます。
A1等のラベル表記と1,2といった行と列番号を指定して取得する方法があります。
こちらはどちらの取得方法でも良いと思うので好みですかね。。。

# A1等のラベル指定して値取得
val = worksheet.acell('B1').value

# 行と列番号を指定して値取得(左:行番号、右:列番号)
val = worksheet.cell(1, 2).value

# 行番号の指定して1行の値をリストとして取得
values_list = worksheet.row_values(1)

# 列番号の指定して1列の値をリストとして取得
values_list = worksheet.col_values(1)

# 値を取得したら値の内容を表示してみる
print(val) # 値表示
print(values_list) # 取得したリストの値を表示

公式ページは以下になります。

https://docs.gspread.org/en/latest/user-guide.html#getting-a-cell-value

他にもシート全て値を取得する方法や行ごとに取得する方法が公式ページには記載されているので参照してみてください。

https://docs.gspread.org/en/latest/user-guide.html#getting-all-values-from-a-worksheet-as-a-list-of-lists

https://docs.gspread.org/en/latest/user-guide.html#getting-all-values-from-a-worksheet-as-a-list-of-dictionaries

値を更新

続いて値を更新していきます。
方法は値取得と同一になり、A1等のラベル表記と1,2といった行と列番号を指定して取得する方法があります。

# ラベル指定して値を更新
worksheet.update('B1', 'Bingo!')

# 行と列番号を指定して値更新
worksheet.update_cell(1, 2, 'Bingo!')

# 範囲を指定して値をまとめて更新
worksheet.update('A1:B2', [[1, 2], [3, 4]])

# 更新したら値の内容を表示してみる
print(worksheet.acell('B2').value) # 値表示

公式ページは以下になります。

https://docs.gspread.org/en/latest/user-guide.html#updating-cells

行操作

最後に行ごとに操作する方法の紹介になります。
実際スプレッドシートの更新は行ごとに行うことが多いと思うので、その時の操作方法になります。
方法としては、最終行に追加、指定行に追加、指定行の削除になります。
行を指定しての更新方法が見つからず私は指定行を削除後、指定行を追加することで行の更新を行っています。

# 最終行に引数のリストの内容を1行追加
worksheet.append_row(['A','B','C'])

# 指定行に引数のリストの内容を1行追加
worksheet.insert_row(['A','B','C'], 1)

# 指定行を削除
worksheet.delete_rows(2)

# 行を更新したら値の内容を表示してみる
values_list = worksheet.row_values(1)
print(values_list)

公式ページは以下になります。

https://docs.gspread.org/en/latest/api/models/worksheet.html#gspread.worksheet.Worksheet.append_row

https://docs.gspread.org/en/latest/api/models/worksheet.html#gspread.worksheet.Worksheet.insert_row

https://docs.gspread.org/en/latest/api/models/worksheet.html#gspread.worksheet.Worksheet.delete_row

まとめ

いかがだったでしょうか。
私はgspreadライブラリを使うことでかなり簡単にGoogleスプレッドシートの操作ができたと感じています。
私はこれをAWS Lambdaに実装し日々の記録を自動化しています。
機会があればLambdaへの実装方法を記事にしようと思いますが、ソースコードだけ参考に載せておきます。
認証情報をパラメータストアから取得するところがAWS Lambda特有の部分ですが、他は同じようにGoogleスプレッドシートの操作が可能です。

import gspread
import json
import boto3
import os

# パラメータストアに保存している認証情報のキー名を環境変数から取得
# PARAM_KEY = os.environ.get('●●●パラメータストアを取得する環境変数名を指定●●●')
# 私は環境変数として「PARAM_KEY」として設定
PARAM_KEY = os.environ.get('PARAM_KEY')

def lambda_handler(event, context):

    # パラメータストアに保存している認証情報(JSONファイルを取得)
    ssm = boto3.client('ssm')
    response = ssm.get_parameters(
        Names=[
            PARAM_KEY,
        ],
        WithDecryption=True
    )
    service_account_info = json.loads(response['Parameters'][0]['Value'])

    #認証処理
    gc  = gspread.service_account_from_dict(service_account_info)

    # ファイル名指定で開く
    sh = gc.open('●●●Googleスプレッドシートファイル名を指定●●●')

    # シート名指定
    worksheet = sh.worksheet("●●●操作するシート名を指定●●●")

    # A1等のラベル指定して値取得
    val = worksheet.acell('B1').value

    # ラベル指定して値を更新
    worksheet.update('B1', 'Bingo!')

    # 最終行に引数のリストの内容を1行追加
    worksheet.append_row(['A','B','C'])

Lambdaの環境変数に以下を設定

SystemsManagerのパラメータストアに以下を設定

AWS Lambda関連の記事は以下などを投稿しているので興味がある方はぜひ読んでみてください(^^)

1.AWS Lambda 入門~おすすめ本5冊の紹介~

2.AWS Lambda で Python プログラミング~Boto3 サンプル集S3編~

3.AWS Lambda SAMとは?~Cloud9でSAM Sampleを使ってPythonのLambdaプログラムを簡単にデプロイする~

これで日々の単調な作業から脱却します!

AWS Lambda SAMとは?~Cloud9でSAM Sampleを使ってPythonのLambdaプログラムを簡単にデプロイする~

概要

前のLambda投稿に続き今回もAWS Lambdaネタになります。
今回はLambda構築・設定・イベントソースマッピングからソースコードを管理・編集しやすいようにAWS サーバーレスアプリケーションモデル (Serverless Application Model)、AWS SAMにチャレンジします。

https://aws.amazon.com/jp/serverless/sam/

サンプルコードなどの簡単なプログラミングであればAWSコンソールで設定、ソースコードの直接編集すれば良いのですが、ちょっと規模が大きくなるとLambdaの設定・ソースコードをしっかり管理したい、しっかりテストしたいという状況が出てきます。

その時にかなり便利なのがAWS サーバーレスアプリケーションモデル(AWS SAM)になります。

Lambdaを使って本格的にLambdaのサービスを運用したい人、興味がある方は読んでみて下さい。

資格試験の勉強法は記事は以下を参照。

AWS初心者がAWS 認定ソリューションアーキテクト – アソシエイト資格試験に合格した時の勉強法
AWS初心者がAWS 認定ソリューションアーキテクト – プロフェッショナル資格試験に合格した時の勉強法

想定読者

  • LambdaでSAMを使ってみたい人
  • Lambdaの知識をレベルアップしたい人
  • Lambdaを実運用で使っている人

参考書籍

AWS Lambda実践ガイド 第2版

【Kindle版】AWS Lambda実践ガイド 第2版

ほぼほぼこの本を参考にさせて頂きました。
Lambdaに特化した本はあまりないので現時点で唯一の専門書と思います。
2022年になって第2版となり内容が最新化されています。

目次

  • SAM環境(Cloud9環境)準備
  • SAM初期設定
  • SAMビルド/デプロイ

SAMを使って簡単なLambda関数を作っていきます。
作業時間、たったの 30分!

SAM環境(Cloud9環境)準備

SAMを使うためには SAM CLI がインストールされている必要があります。
ローカル環境でインストールしても良いのですが、AWS の Cloud9 を使うのが一番簡単なので今回はCloud9の環境準備から説明します。

Cloud9の作成は非常に簡単で、AWSコンソールのCloud9のサービスメニュに行き、

image.png

Create environmentをクリック
image.png

Nameに任意の名前を入力
Next stepをクリック

image.png

環境設定は、基本的には任意のものを選択していいのですが、ブラウザからそのままアクセスが出来て簡単なのが direct access 、料金が安く済むものが t2.micro になります。

image.png

料金節約のため無操作30分後に自動停止するよう After 30 minutes(default) のままにしておきます。
Network settingd(advanced) はデフォルトVPC以外に作りたい時(Cloud9へのアクセスをしっかりアクセス制御したい時)に選択します。
Next step をクリック

image.png

設定内容を最終確認して問題なければ、Create environment クリック

memo_2022-05-01-11-46-16.png

数分待つとこんな感じのCloud9のトップ画面が表示されます。
実際の操作は左メニューから編集したいファイルを選択し画面中央部で編集する操作と、画面下部のコンソール部分に直接コマンドを実行する大きく2パターンの操作があります。

image.png

SAM初期設定(sam init)

それでは実際にSAMの初期設定をしていきます。
画面下部のコンソールに sam init のコマンドを実行して初期設定します。

$ pwd
/home/ec2-user/environment
$ sam init

You can preselect a particular runtime or package type when using the `sam init` experience.
Call `sam init --help` to learn more.

Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: 1

Choose an AWS Quick Start application template
        1 - Hello World Example
        2 - Multi-step workflow
        3 - Serverless API
        4 - Scheduled task
        5 - Standalone function
        6 - Data processing
        7 - Infrastructure event management
        8 - Lambda EFS example
        9 - Machine Learning
Template: 1

 Use the most popular runtime and package type? (Python and zip) [y/N]: y

Project name [sam-app]: sam-example

Cloning from https://github.com/aws/aws-sam-cli-app-templates (process may take a moment)

    -----------------------
    Generating application:
    -----------------------
    Name: sam-example
    Runtime: python3.9
    Architectures: x86_64
    Dependency Manager: pip
    Application Template: hello-world
    Output Directory: .

    Next steps can be found in the README file at ./sam-example/README.md


    Commands you can use next
    =========================
    [*] Create pipeline: cd sam-example && sam pipeline init --bootstrap
    [*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch


SAM CLI update available (1.53.0); (1.40.1 installed)
To download: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html
$

実際の入力値は以下の4つ

  • Choice: 1(1 - AWS Quick Start Templates)
  • Template: 1(1 - Hello World Example)
  • Use the most popular runtime and package type? (Python and zip) [y/N]: y
  • Project name [sam-app]: sam-example

sam-example というプロジェクト名で、実行環境 python3.9、samテンプレート Hello World Example を選択(テンプレートはすぐに自分で編集するのでなんでも構いません)しています。

sam init コマンドが完了するとひと通り必要なフォルダ・ファイル群が作成されます。

IMG_0358.jpeg

この中で重要なのが、

  • app.py:Lambdaのソースプログラムが記載されているファイル
  • template.yml:Lambdaの設定が記載されているファイル

の二つになります。

IMG_0357.jpeg

それぞれ中身を簡単に見てみます。
まずは template.yml から。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-example

  Sample SAM Template for sam-example

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
        - x86_64
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get

Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

Hello World Example のテンプレートの場合、LambdaとAPIGatewayが含まれています。
Resources: 部がそれらの記述に該当しますが

  • Type: AWS::Serverless::Function:Lambdaであることを示しています
  • Type: Api:APIGatewayであることを示しています

今回は、最小限のLambdaだけの設定にしたいので以下に書き換えます。(ついでにコメントも消してすっきりさせます)

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-example

  Sample SAM Template for sam-example

Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: app.lambda_handler
      Runtime: python3.9

Outputs:
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

DescriptionOutputs は無くても良い設定のため必要なのは、GlobalsResources 部だけになり、たった 9行 です。

次は app.py です。
このファイルがLambdaの本体のプログラムになります。
今後、自分でプログラムを書き換えるときはこのファイルを編集します。

import json

# import requests


def lambda_handler(event, context):
    """Sample pure Lambda function

    Parameters
    ----------
    event: dict, required
        API Gateway Lambda Proxy Input Format

        Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format

    context: object, required
        Lambda Context runtime methods and attributes

        Context doc: https://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html

    Returns
    ------
    API Gateway Lambda Proxy Output Format: dict

        Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
    """

    # try:
    #     ip = requests.get("http://checkip.amazonaws.com/")
    # except requests.RequestException as e:
    #     # Send some context about this error to Lambda Logs
    #     print(e)

    #     raise e

    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": "hello world",
            # "location": ip.text.replace("\n", "")
        }),
    }

こちらはシンプルですね。
コメントがたくさんありますが、戻り値にjson形式の hello world も返却しているだけになってます。

SAMビルド/デプロイ(sam build/sam deploy)

ビルド

では、ビルド/デプロイをやっていきましょう。
template.yml を編集したため、シンプルに Lambda関数1つ を作成するsamテンプレートになっています。

では、ここからはコンソール操作になるので、Cloud9画面下部のコンソール部分でコマンド実行します。
まず、カレントフォルダを ~/environment/sam-example/ (自身で入力したプロジェクトフォルダ)に移動して、ビルドコマンド sam build --use-container を実行します。

実際の実行コマンドは以下の2つ

cd ~/environment/sam-example/
sam build --use-container

では、やってみます。

$ cd ~/environment/sam-example/
$ sam build --use-container
Starting Build inside a container
Building codeuri: /home/ec2-user/environment/sam-example runtime: python3.9 metadata: {} architecture: x86_64 functions: ['HelloWorldFunction']

Fetching public.ecr.aws/sam/build-python3.9:latest-x86_64 Docker container image...............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Mounting /home/ec2-user/environment/sam-example as /tmp/samcli/source:ro,delegated inside runtime container
Traceback (most recent call last):
  File "samcli/__main__.py", line 12, in <module>
  File "click/core.py", line 829, in __call__
  File "click/core.py", line 782, in main
  File "click/core.py", line 1259, in invoke
  File "click/core.py", line 1066, in invoke
  File "click/core.py", line 610, in invoke
  File "click/decorators.py", line 73, in new_func
  File "click/core.py", line 610, in invoke
  File "samcli/lib/telemetry/metric.py", line 153, in wrapped
  File "samcli/lib/telemetry/metric.py", line 122, in wrapped
  File "samcli/lib/utils/version_checker.py", line 42, in wrapped
  File "samcli/cli/main.py", line 90, in wrapper
  File "samcli/commands/build/command.py", line 228, in cli
  File "samcli/commands/build/command.py", line 318, in do_cli
  File "samcli/lib/build/app_builder.py", line 172, in build
  File "samcli/lib/build/build_strategy.py", line 42, in build
  File "samcli/lib/build/build_strategy.py", line 53, in _build_functions
  File "samcli/lib/build/build_strategy.py", line 129, in build_single_function_definition
  File "samcli/lib/build/app_builder.py", line 572, in _build_function
  File "samcli/lib/build/app_builder.py", line 705, in _build_function_on_container
  File "samcli/local/docker/container.py", line 308, in wait_for_logs
RuntimeError: Container does not exist. Cannot get logs for this container
[19020] Failed to execute script __main__

おそらく、 RuntimeError: Container does not exist. Cannot get logs for this container エラーが発生します。
ビルドコマンドのオプションで --use-container(実行環境をコンテナ上に作成するオプション)を付けているのですが、Cloud9の初期ディスクだと足りません。。。
(非常にわかりにくいエラーメッセージですね。。。)

なぜなら、、、

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        484M     0  484M   0% /dev
tmpfs           492M     0  492M   0% /dev/shm
tmpfs           492M  468K  491M   1% /run
tmpfs           492M     0  492M   0% /sys/fs/cgroup
/dev/xvda1       10G  8.2G  1.9G  82% /
tmpfs            99M     0   99M   0% /run/user/1000

すでにディスク容量の 82% しており、 1.9G しか残りがないからです。。。
(sam init で大量にディスクを消費したのではなく、Cloud9は最初からディスクが少ないようです。。。)

Cloud9ディスク拡張

では、Cloud9のディスクを増やしましょう。
Cloud9はEC2のLinux上で実現されているのでEC2のメニューからLinuxのディスク拡張操作を行います。
Linuxの場合、ディスク拡張は簡単で、Cloud9を作成すると自動的にEC2のメニューに専用のEC2が出来上がっているので、そのEC2を止めた状態で、EC2のボリュームのメニューのディスクの変更からサイズを増やすだけです。

image.png
image.png

以上です。

再度EC2を起動し、Cloud9のコンソールからディスクが増えていることを確認します

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        484M     0  484M   0% /dev
tmpfs           492M     0  492M   0% /dev/shm
tmpfs           492M  464K  491M   1% /run
tmpfs           492M     0  492M   0% /sys/fs/cgroup
/dev/xvda1       15G  8.2G  6.9G  55% /
tmpfs            99M     0   99M   0% /run/user/1000

使用率 55% 残り 6.9GB になりました。
では、改めてビルドしましょう。

再ビルド

$ cd ~/environment/sam-example/
$ sam build --use-container
Starting Build inside a container
Building codeuri: /home/ec2-user/environment/sam-example runtime: python3.9 metadata: {} architecture: x86_64 functions: ['HelloWorldFunction']

Fetching public.ecr.aws/sam/build-python3.9:latest-x86_64 Docker container image...............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Mounting /home/ec2-user/environment/sam-example as /tmp/samcli/source:ro,delegated inside runtime container

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

requirements.txt file not found. Continuing the build without dependencies.
Running PythonPipBuilder:CopySource
$

今度は成功しました。
ビルド後のディスク容量も確認しておきましょう。

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        484M     0  484M   0% /dev
tmpfs           492M     0  492M   0% /dev/shm
tmpfs           492M  464K  491M   1% /run
tmpfs           492M     0  492M   0% /sys/fs/cgroup
/dev/xvda1       15G   11G  4.6G  70% /
tmpfs            99M     0   99M   0% /run/user/1000
$ 

使用率 70% 残り 4.6GB になりました。
ビルド前と比較すると 2.3GB 使用するようですね。結構使いますね。。。

デプロイ

では、いよいよデプロイです。
sam deploy --guided --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND デプロイ時のガイド付き、ロール等は自動で作成するオプションを付けています。

実行コマンドは以下の1つ。

sam deploy --guided --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND

実行します。

$ sam deploy --guided --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND

Configuring SAM deploy
======================

        Looking for config file [samconfig.toml] :  Not found

        Setting default arguments for 'sam deploy'
        =========================================
        Stack Name [sam-app]: sam-sample
        AWS Region [ap-northeast-1]: 
        #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
        Confirm changes before deploy [y/N]: y
        #SAM needs permission to be able to create roles to connect to the resources in your template
        Allow SAM CLI IAM role creation [Y/n]: y
        Save arguments to configuration file [Y/n]: y
        SAM configuration file [samconfig.toml]: 
        SAM configuration environment [default]: 

        Looking for resources needed for deployment:
         Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-bncdmvrv3w3n
         A different default S3 bucket can be set in samconfig.toml

        Saved arguments to config file
        Running 'sam deploy' for future deployments will use the parameters saved above.
        The above parameters can be changed by modifying samconfig.toml
        Learn more about samconfig.toml syntax at 
        https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html

Uploading to sam-sample/1c2f1111422c1a9a068bc3d12653d3c4  7913 / 7913  (100.00%)

        Deploying with following values
        ===============================
        Stack name                   : sam-sample
        Region                       : ap-northeast-1
        Confirm changeset            : True
        Deployment s3 bucket         : aws-sam-cli-managed-default-samclisourcebucket-bncdmvrv3w3n
        Capabilities                 : ["CAPABILITY_IAM", "CAPABILITY_AUTO_EXPAND"]
        Parameter overrides          : {}
        Signing Profiles             : {}

Initiating deployment
=====================
Uploading to sam-sample/cc7378c1e1ecf6a93a04bc81b3006223.template  768 / 768  (100.00%)

Waiting for changeset to be created..

CloudFormation stack changeset
-------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation                               LogicalResourceId                       ResourceType                            Replacement                           
-------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Add                                   HelloWorldFunctionRole                  AWS::IAM::Role                          N/A                                   
+ Add                                   HelloWorldFunction                      AWS::Lambda::Function                   N/A                                   
-------------------------------------------------------------------------------------------------------------------------------------------------------------

Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:changeSet/samcli-deploy1651456975/245e03ef-407d-b1c6-43702e5cd1b3-e61b


Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y

2022-05-02 02:03:09 - Waiting for stack create/update to complete

CloudFormation events from changeset
-------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                          ResourceType                            LogicalResourceId                       ResourceStatusReason                  
-------------------------------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS                      AWS::IAM::Role                          HelloWorldFunctionRole                  -                                     
CREATE_IN_PROGRESS                      AWS::IAM::Role                          HelloWorldFunctionRole                  Resource creation Initiated           
CREATE_COMPLETE                         AWS::IAM::Role                          HelloWorldFunctionRole                  -                                     
CREATE_IN_PROGRESS                      AWS::Lambda::Function                   HelloWorldFunction                      -                                     
CREATE_IN_PROGRESS                      AWS::Lambda::Function                   HelloWorldFunction                      Resource creation Initiated           
CREATE_COMPLETE                         AWS::Lambda::Function                   HelloWorldFunction                      -                                     
CREATE_COMPLETE                         AWS::CloudFormation::Stack              sam-sample                              -                                     
-------------------------------------------------------------------------------------------------------------------------------------------------------------

CloudFormation outputs from deployed stack
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Outputs                                                                                                                                                      
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Key                 HelloWorldFunctionIamRole                                                                                                                
Description         Implicit IAM Role created for Hello World function                                                                                       
Value               arn:aws:iam::XXXXXXXXXXXX:role/sam-sample-HelloWorldFunctionRole-11AUZUABC6ASS                                                           

Key                 HelloWorldFunction                                                                                                                       
Description         Hello World Lambda Function ARN                                                                                                          
Value               arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:sam-sample-HelloWorldFunction-y2SU9rABc52s                                           
--------------------------------------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - sam-sample in ap-northeast-1
$ 

ガイド付きなので何回か質問があるので確認して選択しましょう。
Stack Name は、自分で決める任意の名称になります。

ちなみに次回以降の更新の時は選択内容が保持されるため sam deploy コマンドでサクッとデプロイできます。

$ sam deploy
Uploading to sam-sample/287342c7c37cb1d8020451b36647bd1f  452838 / 452838  (100.00%)

        Deploying with following values
        ===============================
        Stack name                   : sam-sample
        Region                       : ap-northeast-1
        Confirm changeset            : True
        Deployment s3 bucket         : aws-sam-cli-managed-default-samclisourcebucket-bncdmvrv3w3n
        Capabilities                 : ["CAPABILITY_IAM", "CAPABILITY_AUTO_EXPAND"]
        Parameter overrides          : {}
        Signing Profiles             : {}

Initiating deployment
=====================
Uploading to sam-sample/17c228278a608cc7c3f55da042cf1ae7.template  768 / 768  (100.00%)

Waiting for changeset to be created..

CloudFormation stack changeset
-------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation                               LogicalResourceId                       ResourceType                            Replacement                           
-------------------------------------------------------------------------------------------------------------------------------------------------------------
* Modify                                HelloWorldFunction                      AWS::Lambda::Function                   False                                 
-------------------------------------------------------------------------------------------------------------------------------------------------------------

Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:changeSet/samcli-deploy1651457546/3cc5876f-4d81-a290-7cbc821840ed-5d26


Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y

2022-05-02 02:12:41 - Waiting for stack create/update to complete

CloudFormation events from changeset
-------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                          ResourceType                            LogicalResourceId                       ResourceStatusReason                  
-------------------------------------------------------------------------------------------------------------------------------------------------------------
UPDATE_IN_PROGRESS                      AWS::Lambda::Function                   HelloWorldFunction                      -                                     
UPDATE_COMPLETE                         AWS::Lambda::Function                   HelloWorldFunction                      -                                     
UPDATE_COMPLETE_CLEANUP_IN_PROGRESS     AWS::CloudFormation::Stack              sam-sample                              -                                     
UPDATE_COMPLETE                         AWS::CloudFormation::Stack              sam-sample                              -                                     
-------------------------------------------------------------------------------------------------------------------------------------------------------------

CloudFormation outputs from deployed stack
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Outputs                                                                                                                                                      
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Key                 HelloWorldFunctionIamRole                                                                                                                
Description         Implicit IAM Role created for Hello World function                                                                                       
Value               arn:aws:iam::XXXXXXXXXXXX:role/sam-sample-HelloWorldFunctionRole-11AUZUANR6ASS                                                           

Key                 HelloWorldFunction                                                                                                                       
Description         Hello World Lambda Function ARN                                                                                                          
Value              arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:sam-sample-HelloWorldFunction-yrJDo52s2SU9                                         
--------------------------------------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - sam-sample in ap-northeast-1
$ 

Outputs に作成されたLambda関数のARNが表示されているので確認して、AWSコンソールからLambdaを確認してみましょう。今回の例だとLambda関数名は sam-sample-HelloWorldFunction-yrJDo52s2SU9 になります。

デプロイされたLambdaの設定を画面を確認すると --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND オプションのおかげで必要なロールが自動作成されていることがわかります。

image.png

もちろん app.py の内容がLambdaの コードソース 部分で確認できると思います。

image.png

あとは通常のコンソール操作のtestから動作確認可能です。簡単ですね。

まとめ

お疲れ様でした!

今回はLambdaでsamを使って作成してみました。簡単なLambdaであれば、AWSコンソールで十分なのですが、Lambdaと連携するAWSサービスが増えてくれるとAWSコンソールだけではどこに何を設定したか把握しきれず限界が来ると思います。
そこでプログラムを app.py に、環境設定を template.yml にしておけば非常に管理しやすくなりますね。(テキストなのでGitでバージョン管理したり差分比較したり簡単になります)
samを使ってプログラムに集中出来るサーバーレスLambdaがもっと便利になって、開発者はより業務ロジックに集中出来る世の中になれば良いなと思います(^^)

本投稿が少しでも皆さんの良いサーバーレスライフの助けになればと思います(_ _)

Java初心者がJavaのプロになるためのおすすめ本

概要~Java初心者が現場使えるJavaプログラムを理解するまでのおすすめ参考書ロードマップ~

仕事を始めてJavaに取り組むようになった方は多いのではないでしょうか。
私も実は仕事を始めて初めてJavaを知った/勉強したのですが、最初色んな言葉が出てきて大混乱。勉強が結構大変だったことを覚えています。

そんな経験があったため、最近入ってくる新人さん向けに私が10年働く間にJava初心者に何を学んでもらえばいいか考え、行き着いた結果の良質と考えている参考書10選を今回紹介します。

つまり、個人的Java初心者が現場使えるJavaプログラムを理解するまでの参考書ロードマップの紹介です。

想定読者

  • 仕事を始めてJavaプログラムが必要になった人
  • Javaの勉強を始めて専門用語が多過ぎて勉強に挫折しそうな人

結果

忙しい人はとりあえず結果だけご覧ください。

Java良書10選

  1. やさしいJava
  2. スッキリわかるJava入門
  3. スッキリわかるJava入門 実践編
  4. リーダブルコード
  5. オブジェクト指向でなぜつくるのか
  6. Webを支える技術 ―― HTTP,URI,HTML,そしてREST
  7. 独習Java
  8. プロになるJava
  9. Java言語で学ぶデザインパターン入門
  10. Effective Java

やさしいJava

それでは紹介です。最初はやさしいJavaです。

やさしいJava

まず最初の一冊はわかりやすさを重要視して選んでいます。なぜならJavaの特徴として、他の言語に比べわかりにくい専門用語多く、初心者にはプログラムの理解より言葉の理解最初のハードルがまず高い事が挙げられるからです。

そのため、Javaの入門書は今となってはたくさんありますが、まずは入門書としてタイトルの通り非常にわかりやすいこの本から入るのがいいかなと思っています

スッキリわかるJava入門

次はスッキリわかるJava入門です。

スッキリわかるJava入門

Javaの入門書は1冊ではちょっと物足りないため、もう一冊入門書的な位置づけの本を入れています。
2冊を読み比べて重要なところ、1冊では理解できなったところをもう1冊で補完して、自分の理解力を高めることが重要と考えています。
Javaは1冊だけでは書ききれない重要な概念が多いため、出来れば2冊入門書を読みましょう。

スッキリわかるJava入門 実践編

次はスッキリわかるJava入門の続編、スッキリわかるJava入門 実践編です。

スッキリわかるJava入門 実践編

1歩進めて実践編が本書になります。実際に現場で使える内容となっているので、基礎を理解した上で、読み進めるといいかなと思います。

リーダブルコード

次はリーダブルコードです。
ちょっと箸休めです。

リーダブルコード

内容を知っている人は、なぜここでリーダブルコード?と思う人もいると思うのですが、私はこのタイミングがベストと思います。
プログラム初心者が読む本として位置付けされることもあると思いますが、私はJavaが分かってから読むべき(一度読んでいても再読すべき)と考えています。
自身でJavaコードをある程度書けるようになってからこの本を読むとよりリアルな気づきがあると思います。そう言えばあの時書いたあのコード、リーダブルではなかったな。など。

オブジェクト指向でなぜつくるのか

次はオブジェクト指向でなぜつくるのかです。
こちらもJavaに特化した内容ではないため箸休め第2弾です。

オブジェクト指向でなぜつくるのか

そもそもなぜJavaがここまで流行ったのか、オブジェクト指向はどんなに便利なのか、Javaでオブジェクト指向で作るというのはどういうことなのか理解するのに良い本と考えています。

Webを支える技術 ―― HTTP,URI,HTML,そしてREST

次はWebを支える技術 ―― HTTP,URI,HTML,そしてRESTです。
箸休め第3弾(最後の箸休め)です。そろそろプログラムを見ることに疲れた人向けです(^^;)

Webを支える技術 ―― HTTP,URI,HTML,そしてREST

皆さんがJavaを勉強する理由は様々だと思いますが、最近はWebシステムを作るケースが多いのではないでしょうか。
そんな人向けの本になっているので、私はWeb関係ないという人は飛ばしてもらっていいのですが、Javaで「HTTP,URI,HTML,そしてREST」をプログラミングするという人はぜひ読んでおいてください。
コードが書けるだけではWebシステムは完成しません。なぜそのようなコードが必要かを理解できるようになると思います。

独習Java

箸休めが終わりまとめ編になります。
まとめ関連のおすすめは独習Java です。この本を読んで基礎の振り返りをしっかりする、自信の技術力として定着化するイメージで選んでいます。

独習Java

この本は昔からある良書の扱いになるので教科書的な本になります。そのため丁寧なのですが、最初の1冊としては他の本に読み易さという点で譲りましたが、重要なポイントの抑え方、記載テーマ、サンプルコードなどがやはり入門本からは1つレベルアップしたような教科書的な良書 になっています。いつでも振り返れるよう手元に置いておきたい内容になっています。

プロになるJava

次はプロになるJavaです。
タイトルの通りですが、ここからプロになりましょう(^^)

プロになるJava

ここまでで基礎を固める -> 実践を学ぶ -> プロになる というレベルアップを想定しています。
印象としては、実践を学ぶ -> プロになる 部分はちょっと飛躍的レベルアップなのですが、その部分は実際に自分の手を動かしてプログラミングした結果や実際やったこと読んだことをGoogle検索等で補完しながらレベルアップすることを想定しています。(ここまで読んだ読者ならそれが出来るだけのレベルアップがされていると考えています)

Java言語で学ぶデザインパターン入門

プロになったら次はデザインパターンを学びましょう。

Java言語で学ぶデザインパターン入門

正直プロなったところがJavaで給料をもらえるというスタートラインと思います。
つまり、ここまでのJavaプログラマーでは現場で技術力の差別化が出来ません。
そこで、オッこの人はJavaがかなり出来るなと思ってもらえるようにデザインパターンを学びましょう。
現場でこれはファクトリーデザインパターンですね。なんて、会話が出来るとJavaで自信をもって仕事をしているなと言えると思います。

Effective Java

ついに最後の1冊、10冊目です。
Effective Java です。

Effective Java

もはや説明はいらないくらいJavaをしっかり勉強したことがある人なら誰でも知っている名書と思います。
ただ、いきなりこの本を読んで理解できる人は少ないと思うので今回の最後の1冊として紹介する形で記載しました。
皆さんもぜひここまで読み進めてみてJavaの理解を深めてください!

まとめ

今回は、Java初心者が現場使えるJavaプログラムをプロとして理解するまでのおすすめの参考書10冊を紹介しました。
これらを理解すれば間違なく私はJavaのプロフェッショナルです。と、自信をもって仕事ができる人材になれるかなと思って選抜しているので、これからJavaを頑張ろうと思っている人がいたらぜひ参考に1冊でも読んでみてください。

本投稿が少しでも皆さんの良いJavaライフの助けになればと思います(_ _)

AWS Amazon Lightsailなら固定IPも無料!Lightsailを使って運用料金最安値?でWordPress(ブログ)を運用する

概要~LightsailでWordPress構築・固定IPアドレス設定~

いろいろ調べたところWordPressを使ったブログ運用にはAWSのAmazon Lightsailを利用するのが最安値で最も簡単なのではないか?という結論に達したためAmazon LightsailでWordPressを構築する手順を投稿します。

運用料金

月額 $3.5 安い!
しかも今なら最初の3か月間は無料!

構築時間

15分

できるようになること

  • WordPressにログインできる
  • ブログが公開できる

作業手順

  1. インスタンス作成
  2. WordPressログインパスワードの確認
  3. 静的IPの設定
  4. WordPressログイン確認

たったの4手順作業時間15分でWordPressが構築できブログが公開できます!
それでは詳細手順を見ていきましょう。

1.インスタンス作成

まずはWordPressを構築するインスタンスを作成します。
AWSコンソールでAmazon Lightsailのサービスメニューを開き、インスタンスの作成をクリックします。

作成するインスタンスの種類を選択する画面に遷移します。
特にこだわりがなければすべてデフォルトの設定のままで良いと思います。
今回はWordPressの構築なので設計図の選択でWordPressが選択されていることを確認しましょう。

インスタンスプランの選択で月額料金が決定します。
人気ブログになったら変更しないといけないかもしれませんが、初期構築は最小で十分だと思うので、月額$3.5を選択します。
以上で設定は完了のため最後にインスタンスの作成をクリックします。簡単ですね。

無事に作成されると以下のように作成されたインスタンスが確認できる画面になります。

2.WordPressログインパスワードの確認

それでは次の手順に移ります。
次は作成されたインスタンスのWordPressにログインするためのパスワードを確認します。
パスワード確認にはインスタンスにsshでログインする必要がありますが、Amazon Lightsailの場合、ブラウザから簡単にログインできます。
具体的には以下の接続用ボタンを押します。(ちょっとわかりにくいですが、赤枠で囲んでいるオレンジの■部分です)

自動的にログインされ、以下のターミナルがブラウザで表示されます。

パスワードはファイルに記載されているため以下のコマンドを実行します。

cat $HOME/bitnami_application_password

ここではpasswordと表示されたとして手順を進めます。

3.静的IPの設定

設定としては最後の手順になります。
今のままでもWordPressにアクセスでき、ブログ公開もできるのですが、IPアドレスが変わってしまう可能性があり、不便なので固定の静的IPを設定します。
この静的IPアドレスは追加料金無し無料で設定できます。

それでは設定していきます。
まずはAmazon Lightsailのホーム画面に戻りネットワーキングをクリックします。

ネットワーキングのサービスメニューから静的IPの作成をクリックします。

インスタンスへのアタッチで作成したインスタンスを選択し、

作成ボタンで完了です。

完了画面に静的IP(18.XXX.XXX.XXX部)が表示されます。(画像はマスクしています)

4.WordPressログイン確認

準備は全て整いました!
後はログインするだけです。
ログイン用アクセスURLは以下になります。

http://{18.XXX.XXX.XXX(静的IP)}/wp-login.php

WordPressのログイン画面が表示されるので、WordPressの初期ユーザ(user)と、前の手順で確認したパスワードを入力してログインします。

無事にダッシュボードが表示されれば作業完了です。
お疲れ様でした!
後はWordPressを使ってサクッとブログを公開してしまいましょう。

まとめ

作業手順は4手順で作業完了です。
具体的な手順としてもコマンド1つだけであとは画面操作だけなので非常に簡単だったのではないでしょうか。
しかも月額$3.5です。Amazonさん凄いです。
しばらくこれで運用して様子を見ようと思います。(このブログもAmazon Lightsailで運用しています)

補足

最後補足としてAmazon Lightsailのさらに便利なところを紹介していきます。
それは管理画面からいろいろ確認できるところです。
管理画面は以下からアクセスします。

管理画面にアクセスすると以下のサービスメニューが表示されます。
ここでは、便利そうなものをいくつか紹介します。

まずはメトリクス。いろいろ見れるようです。

CPUの概要はこんなグラフです。

送信ネットワークトラフィックだとこんな感じ。

ネットワーキングでファイアフォール設定も確認できました。

履歴でインスタンスの変更履歴が確認できるようです。

削除も簡単にできそうです。

以上!Amazon Lightsailかなり簡単!便利!!安い!!!のではないでしょうか。

SE/システムエンジニアとして大切な10のこととは?

概要

気がつくとSEとして10年を超える会社員人生を過ごしていたので、
そんな10年を振り返って仕事を進める上で大切と思える10のことをまとめてみた。
具体的な知識/技術ではなく敢えてSE/システムエンジニアとしての行動というより普遍的な内容に絞って記載。
忙しさで忘れないための備忘録と定期的に思い出し/更新して自分への戒めとするための記事にしたい。
行動することの重要性を忘れないよう、いつでも行動に移すための具体的な行動も記載。

10年という経験を通したノウハウとして書いているので書籍とは違った生の声として誰かの役に立てばと思う。

SEとして大切な10のこと

  • 仕事は人との関わりであることを知る
  • 人との調整ごとは早めに行動する
  • プログラムを学ぶ
  • いつも目的意識を持つ
  • チーム全体としての生産性を考える
  • 今やるべきことは未来からの逆算で決める
  • 勉強する習慣を身につける
  • 時間の重要性を意識する
  • できるだけ経験し失敗する
  • 変化は当たり前と考える

仕事は人との関わりであることを知る

仕事である以上、1人で完結することはあり得ない。少なくとも仕事に対する対価をもらうお客さんはいるはずで、お客さん以外にもお客さんのお客さん(いわゆるエンドユーザー)や上司/チームメンバや他社のメンバなど様々な人との関わり合いで成り立っていることを認識する。つまり、技術力/論理的思考といった技術面のスキルだけではなく、相手の立場に立ち感情/共感といった心の部分にも働きかけることができるスキルも大切になる。それらはコミュニケーション力や人間力を磨くことによって培われる。
アウトプット(成果)の観点から見ると、世界一/日本一というトップクラスの技術力を持つ一部のスペシャリストを除くと、技術面の個人的スキルでの成果には限界があり、他者と協力して出した成果の方が大きくなることが多い。私も含め大多数の人はスペシャリストなるには非常にハードルが高く、すると自然と他者との協力による成果で仕事をすることになる。(ただし、他者の協力を得るためにはある程度個人の技術スキルに基づた信頼関係が必要)

〇明日からできる具体的な行動

  • 身だしなみに気を付ける/元気に挨拶をする
  • 1日1回雑談をする
  • たくさんの人に話をして普段から仕事に巻き込んでおく
  • つまらない雑用こそ大切に。小さな実績/小さな信頼を積み重ねる

人との調整ごとは早めに行動する

仕事は人との関わりである以上、必ず人の仕事を手伝う/または人に仕事を依頼する場面がある。10年仕事をしていると自分でできる仕事は大抵自分さえ頑張ればなんとかなる。問題になるのは、仕事をお願いしていた人が思った通りに動いてくれない時。そのため、人に仕事を依頼する上で大切なのは借りは作らずできるだけたくさんの貸しを作っておくこと、また出来る限り早く依頼することが重要。
こういった調整ごとは先手先手で対処すれば、本来それほど難しい問題とならないことがほとんどで、依頼が遅れて後手になるほど条件が厳しくなる。

〇明日からできる具体的な行動

  • 普段からたくさんの貸しを作れるよう誰かのために行動する
  • 遅くても2週間後の見据えた計画を立てる
  • 普段から良好な関係が築けるようコミュニケーションを大切にする

プログラムを学ぶ

どんなに大きなシステムになっても行き着く先はプログラム。例え、ノーコードやパッケージソフトであっても、プログラム工程を外注先に丸投げしていても、どのようにプログラムされているかを理解することは重要。特に大規模になればなるほど性能部分や他システムとの連携部など、コアになる部分で問題が発生することがあり、その部分の解決にはプログラムはなぜ動くのかという根本的な理解が必要。
プログラムを知ることで技術者としての誇り/自信を持つことができる。

〇明日からできる具体的な行動

  • 自分の手を動かしてプログラムを書いてみる
  • 常に自分だったらどうプログラムするかをイメージする
  • 流行りの本もいいが昔からあるいわゆる名書を読む

いつも目的意識を持つ

10年間仕事していても華やか瞬間は一瞬。思い返しても数回程度。過ごしてきた時間の大部分は単調な作業、繰り返し作業となる。それらを意識した上で、この作業は最終的にどんな目的達成のために行っているかを理解することで、単調な作業でも作業効率や細部の作業品質が変わってくる。
つまらない仕事と愚痴る前に、目の前の仕事がどういうもので、何を目指し、今どういう状況であるかということを見極めて、自分自身で考え、必要であれば変えていくという意識が大切。
いわゆる「3人のレンガ職人」。レンガを積む仕事は、ただ積んでいるだけなのか?それとも大聖堂の一部を作っているのか?を意識するのとしないのでは積み上げたレンガに大きな品質の違いが出ることがある。
目の前のプログラムはただ文字を解析するだけなのか、実は世界を支える重要なシステムの一部なのかを意識するのは非常に重要。
人間は、自然と不要なものは意識しない脳になっているため、目的を理解して初めて意識できることが多い。

〇明日からできる具体的な行動

  • 作業を始める前に本来の目的を把握する
  • 仕事の全体を俯瞰して理解する
  • 全体を理解した上で自分の作業がどのような影響を与えるか考える

チーム全体としての生産性を考える

自分がたとえどんなに仕事の天才だとしてもできる作業は1人分(多くて1.5人分とか)。それ以上の成果を出すには自分で極端に無理をするかメンバにお願いする必要がある。メンバにお願いする時、メンバに対し威圧的な態度や仕事の責任として作業を押し付けて無理やりやらせることをしない。メンバの生産性を最大限に引き出すためは、同じ目標に向かってメンバ自ら行動してもらう事が重要になる。

〇明日からできる具体的な行動

  • メンバのモチベーションを考えて行動する
  • メンバと目的を共有する場を繰り返し作る
  • 作業をお願いするときは意志決定の過程を含め話しをする

今やるべきことは未来からの逆算で決める

目的意識のところでも書いたように、人間の脳は不要なものは無視するように出来ている。今の仕事を今後の自分にどれだけ活かせるかは、自分が将来どこに向かっているかを意識することが重要。そのために自分の軸/仕事に対する価値観を早めに認識し、その未来に向かって今の自分が何をすべきかを考え行動する。

〇明日からできる具体的な行動

  • 自分の3年後をイメージする
  • 3年後に向かって1年間の目標を立てる
  • 1年間の目標から今日からできる具体的な行動を書きだし行動する

勉強する習慣を身につける

SEという仕事は、技術の進歩が速いと言われる業界、また時代の流行りもあり生涯1つの専門性、1つの業務知識だけでやり遂げられることは不可能と思える。結局、その時その時にあった技術/業務を学べるよう勉強する習慣をつけておく必要がある。

〇明日からできる具体的な行動

  • 1日または1週間に〇時間と決めて勉強する時間を習慣化する
  • 自分の興味の延長で勉強することが一番習慣化しやすいため興味のある分野を見つける
  • 定期的に本屋に通うなど新しい技術に触れる機会を増やす

時間の重要性を意識する

10年は長いようであっという間。10年間の時間の使い方で今後10年分の給料は稼げる可能性はあるが、時間は絶対に戻せない。
お金のために時間を使うのでなく、時間のためにお金を使う価値観にシフトする
人生には必ず終わりがありそれまでの日数と1日24時間しかないことは決まっている。時間を何に投資するかを考え行動する。

〇明日からできる具体的な行動

  • 自分自身にアポを取り自己成長など有効に使う時間を意識的に確保する
  • 言われた作業を単調にこなすだけのために時間を使わない
  • やらないという選択肢も視野に入れる

できるだけ経験し失敗する

勉強は大切だが10勉強するより1回経験する方が圧倒的に身に付くことが多い。
何事も経験するチャンスがあればチャレンジする。特に若いうちは。
10年後にやっておいてよかったと思い返すことは大成功した経験より失敗した経験の方が多い。チームでの仕事は後から思い返しすと失敗した経験が楽しい思い出になることが多い。逆にチャレンジせずにうまくこなしていた日々を思い出すことはない。
これは山登りに似ている。平坦な道を歩いても心が晴れ渡るような景色は見られない。つらい想いをして登った山の方が素晴らしい景色が見える。
失敗とはうまくいかなかった時点であきらめること、またはチャレンジしないこと。あきらめずに次の行動を決めて、決めたことを本気で実行し続けることが大事。それが将来大きく成功するための唯一の方法。

〇明日からできる具体的な行動

  • チャンスがあればまずチャレンジする
  • チャンスにむけて事前に準備(人との関係作り、勉強等)する
  • 失敗しても失敗はいつか終わることを知る

変化は当たり前と考える

すべては作られた時から陳腐化が始まる。この記事も仕事のやり方も。
他人は変えられないが、自分は意志さえあればいつでも変えられる。
変化に合わせて常に自分の方向性の方を修正する

〇明日からできる具体的な行動

  • 自分を振り返る時間を作る
  • 自分を疑う時間を作る
  • いつでも挑戦者である気持ちで臨む

まとめ

10年を振り返っていろんな経験/書籍から得たことをまとめてみた。
いずれも個人的な経験をもとにしているため万人に通じるものではないが誰かの役に立てばと思う。

最後に書いたように、変化は当たり前。これからも記事のアップデート、自分の行動のアップデートを忘れずにいたい。

いくつか書籍の文章をそのまま載せているところもあるため、参考文献を以下に記載。

参考書籍


SEの基本 この1冊ですべてわかる
【Kindle版】SEの基本 この1冊ですべてわかる


ドラッカーさんに教わったIT技術者が変わる50の習慣
【Kindle版】ドラッカーさんに教わったIT技術者が変わる50の習慣


大富豪からの手紙
【Kindle版】大富豪からの手紙

AWS ECSでDocker環境を試してみる

概要

AWS資格取得に向けて利用してみたAWSサービスの具体的な利用方法についての投稿です。
今回はAWS上でのDocker利用、 Amazon ECS(Amazon Elastic Container Service)を利用してみる編です。15分程度でDockerを利用したWebアプリケーションが公開できます。
勉強していてコンテナ、タスク、サービス、クラスターと言った用語に混乱してきたので実際にやってみました^^;

資格試験の勉強法は記事は以下を参照。

AWS初心者がAWS 認定ソリューションアーキテクト – アソシエイト資格試験に合格した時の勉強法
AWS初心者がAWS 認定ソリューションアーキテクト – プロフェッショナル資格試験に合格した時の勉強法

想定読者

  • AWSでコンテナと言えばECSって気がするけど実際どうやってECS上でコンテナを動かすか知りたい人
  • ECSのコンテナ、タスク、サービス、クラスターをAWSコンソールで確認して理解を深めたい人

できるようになること

  • Amazon ECSでのWebアプリケーションの公開

およその作業時間

  • 15分
  • ECSの「今すぐ始める」メニューをやってみます
  • すべてデフォルト値でも構築できその場合、5クリック5分で完了します^^;

必要な知識

  • Docker
  • Amazon ECS

予想料金

残念ながら無料ではありません。今回利用するのはAmazon ECSのFargate起動タイプになるので以下の料金がかかります。

image.png
参照元:https://aws.amazon.com/jp/fargate/pricing/

CPUのvCPU単位とメモリのGB単位で料金がかかります。あと、ポイントなのはコンテナイメージのダウンロードを開始した時点からということですね。コンテナの起動有無に関わらず作成したら途中でコンテナ停止しても料金がかかっていることになります。(と言っても後述の必要なタスクの数で定義したコンテナが常時起動するので停止はあまり意味がないようです^^;)

今回の作成サンプルでざっくり計算するとCPU:0.25 vCPU(256)、メモリ:0.5GB(512)を利用するので、仮に一週間起動し続けたとすると

  • CPU:0.05056USD x 0.25vCPU x 24時間 x 7日 = 約2.12USD
  • メモリ:0.00553USD x 0.5GB x 24時間 x 7日 = 約0.46USD

合計 約2.58USD となります。
お試しであれば1日24時間も起動することはないと思うので安い!のではないでしょうか。
(もちろん他のサービス同様、使用用途によってはデータ転送量やCloudWatch利用料とかが追加されることはあるのでご注意ください)

手順の概要

ではやってみましょう。
とは言うものの、ECSの「今すぐ始める」メニューのウィザードに従って入力するだけです。
最初に全体像だけ説明すると、ECSの概念としては、

image.png

図のように、Container definitionTask definitionServiceClusterの4つがあり、こらをウィザードに従って3画面で設定してきます。

これがAmazon ECS理解の最初のハードルと思ったコンテナ、タスク、サービス、クラスターといった用語による混乱です。
それぞれの説明は以下のブラックベルト資料が分かりやすいと思いますが、なんとなく画面を進めながら設定値を眺めながらやっていくと理解できるようになると思います。

image.png
参照元:https://www.slideshare.net/AmazonWebServicesJapan/20200422-aws-black-belt-online-seminar-amazon-elastic-container-service-amazon-ecs

では、始めます。
ECSの初期画面、またはクラスターの今すぐ始めるをクリックして開始します。

image.png
または
image.png
今すぐ始めるをクリックして開始します。(クリック1回目)

Container definition/Task definition設定

最初の画面でContainer definitionとTask definition設定を行います。
コンテナ定義では、デフォルトでhttpd、nginx、tomcatが用意されています。(今回はhttpdを選択)
コンテナ定義、タスク定義いずれも右上に編集ボタンが用意されており、一部パラメータのカスタマイズは可能です。
料金の所で書いたようにCPUとメモリは料金に関係してくれるの編集でカスタマイズしても良いと思います。
とりあえず今回はデフォルトのままをクリック。(クリック2回目)

image.png

Service設定

次はサービス設定です。ロードバランサーとしてALBを組み込めるようですが、とりあえずなしを選択。
この画面も編集ボタンで料金に関係する必要なタスクの数をカスタマイズできます。ただデフォルト値の1から減らすことはできないので、最小限という意味ではこのままをクリック。(クリック3回目)

image.png

Cluster設定

最後にクラスター設定です。と言ってもクラスター名だけなのでデフォルトのままをクリック。(クリック4回目)

image.png

確認画面

確認画面が表示されるので、確認して作成をクリック。
以上!クリック5回で作成完了です!!

image.png

作成画面

内部的にはCloudFormationを使っているようなので、頑張ってVPCから作ってくれていて問題がなければ2,3分後に作成されます。

image.png
2,3分後、、、
image.png

サービスの表示をクリックしてみましょう。
作成されたVPCやサブネット、セキュリティグループの情報が確認できす。

image.png

タスクタブから作成されたタスクをクリックすると

image.png

パブリックIPが割り当てられているので、
http://{割り当てられていたパブリックIP}/
でアクセスしてみます。

image.png

↓が表示されていれば問題なく作成できています。
AWS ECSでのWebアプリケーションの公開完了です!

image.png

実体としては、コンテナ定義の中に定義されている以下のようです。

image.png

はい、クリック5回完了です。
あとはコンテナ定義などいじくり倒しましょう^^

コンテナ確認

ここからは作成されたものを1つ1つ見てみます。まずはコンテナから。
タスク定義のなかにコンテナ定義があります。

image.png

ポートマッピングやマウントポイントなど、コンテナ定義の名前そのままと言ってしまえばそれまでですが、Dockerfileの内容に関連する定義があることがわかります。

タスク確認

次はタスク定義です。

image.png

まず、タスク定義の中にコンテナ定義が含まれています。それに加えて、ネットワークモード、ロールやタスクサイズ(メモリやCPU)がタスク定義として役割のようです。(ブラックベルト資料の具体的定義がこの画面で確認できます)

サービス確認

次はサービスです。クラスターメニューから具体的なサービス名をクリックして確認します。

image.png

まずは必要数(必要なタスクの数)があって、加えてロードバランシング設定、VPCやサブネットといったネットワークアクセス設定があります。

image.png

タスクタブに移動するとタスク定義があり、この画面から複数タスク定義設定が可能なことがわかります。

クラスター確認

最後はクラスターです。

image.png

複数サービスを定義できる画面構成です。
ブラックベルト資料では、実行環境、IAM権限の境界と表現されています。
サービス定義、タスク定義でどのコンテナ定義をまとめるかにも依存すると思いますが、ロードバランシングがサービス定義にあることから、Webサーバ群のサービスとAPサーバ群のサービスの2つのサービスを1つのクラスター配下に定義する。といった使い方がイメージしやすいかなと思います。

補足1:自作Webアプリケーションのコンテナイメージの設定

Container definitionのcustom設定ボタンで自分で作成した今回のようなhttp(80ポート)のWebアプリケーションのコンテナイメージを指定するだけで簡単にWebアプリケーションの公開ができそうですね。

image.png
開いた画面でコンテナのイメージを設定
image.png

コンテナイメージの作成には以下の記事も投稿しているので参考までに。

Windowsで構成情報をDockerfileに定義してイメージを作成してみる

補足2:作成したタスクの停止

試しにタスクタブから停止してみても、、、

image.png

1,2分で再PROVISIONINGされ

image.png

すぐにRUNNING状態になります。

image.png

補足3:作成したWebアプリケーションの削除

クラスターメニューのクラスターの削除から簡単にできます。
CloudFormationを使っているのでVPCからコンテナのタスク定義までまるっと削除されます。
残しておくと料金がかかり続けるので不要になったら必ず削除しましょう。

image.png

まとめ

想像したよりずっと簡単に作成できました。
誰かのコンテナ、タスク、サービス、クラスター理解に役立てればと思います。
今のままだとデフォルト設定のままなので今後は設定内容等、もう少し詳しくみてみる。。。かもしれません(^^;)

AWS EC2 でDocker環境を無料で試してみる

概要

少し前にWindowsにDockerをインストールしていろいろ試してみてたけど
そもそもAWS EC2の方が気楽にいろいろ試せるのでは?と思ってやってみた
思った以上に簡単にできたのでそのやり方を記載

windows版は以下を参照

 WindowsでDocker環境を試してみる

AWS ECS版は以下を参照

 AWS ECSでDocker環境を試してみる

Docker本は以下が詳しくわかりやすいオススメ本です

プログラマのためのDocker教科書

【Kindle版】プログラマのためのDocker教科書


できるようになること

  • AWS EC2でのDocker環境の構築

およその作業時間

  • 10分
  • 5コマンドで完了

必要な知識

  • AWS EC2
  • SSH
  • Docker知識^^;

手順の概要

1.EC2インスタンス作成
2.AMI選択
3.インスタンスタイプ選択
4.インスタンス確認
5.接続用キーペア設定
6.EC2にDockerインストール

参考:公式 Amazon Linux2 に Docker をインストールする

1.EC2インスタンス作成

とりあえずEC2インスタンスを作成するためAWSコンソールからEC2からインスタンス起動を選択

image.png

2.AMI選択

無料枠のAmazon Linux 2を選択

image.png

3.インスタンスタイプ選択

こちらも無料枠を選択し、あとはデフォルトのまま「確認と作成」をクリック

image.png

4.インスタンス確認

作成されるインスタンスをふんふんと確認し、「起動」ボタンをクリック

image.png

5.接続用キーペア設定

SSH接続のために新しいキーペアか既存のキーペアをからキーペアを設定
(画面は既存のキーペアを設定)
最後に「インスタンスの作成」をクリック

image.png

EC2が作成されるまで2,3分待ちましょう。。。

6.EC2にDockerインストール

EC2が作成されたらSSHで接続します
SSH接続の説明は割愛
↓あたりを参考

https://dev.classmethod.jp/cloud/aws/aws-beginner-ec2-ssh/
image.png

SSH接続後、いよいよDockerインストールのコマンドを実行していきます
とりあえずインストールされているパッケージ更新

sudo yum update -y
image.png

完了するとこんな感じ

image.png

いよいよDockerインストール

sudo amazon-linux-extras install docker
image.png

途中確認が表示されたら「y」とか入力

image.png

あっという間にインストールが完了
するとこんな感じ

image.png

インストールできたのでサービス起動

sudo service docker start
image.png

sudo を使用せずに Docker コマンドを実行できるように、ec2-user を docker グループに追加

sudo usermod -a -G docker ec2-user
image.png

一度EC2からログアウト、再度SSH接続する
すると、、、dockerコマンドが普通に使えるように

docker info
image.png

はい、簡単5コマンドでDockerインストール完了です
あとはDockerをいじくり倒しましょう^^

まとめ

想像するよりずっと簡単に環境構築できました
AWSなのでここでいろいろDocker試してみて使い終わったら消してしまえば無料です
消すときはAWSコンソールで↓で完了
EBSとか残ってると微量請求がきてしまうのでまとめて消しておきましょう^^;
時々やってしまうAWSから突然微量請求きてしまうあるあるかと

image.png

EBSの料金について以下に参考記事を書きました。良かったらこちらも^^

 AWS初心者がEC2を最低限の利用料金で利用する