AWS の Fargate のロードバランサーの設定でめちゃくちゃハマった

AWS のFargate でめちゃくちゃハマった

結論からいうと動かない原因は、ロードバランサーのターゲットの種類はipである必要があった。

f:id:ororog:20181018181507p:plain

これは公式ドキュメントにも当然書いてある
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/AWS_Fargate.html

awsvpc ネットワークモードを使用するタスクを含むサービス (例: 起動タイプが Fargate のサービス) では ... ターゲットタイプとして instance ではなく、ip を選択する必要があります。

この問題にハマるポイントは2つあって、

  • ターゲットの種類のデフォルトは instance なので、特に何も考えずに設定すると instance になってしまう
  • サービスを Fargate で構築する時、ターゲットグループが instance のロードバランサーも選択できてしまう

と、いう問題がある。特に二番目は検出して警告なり出してほしい。

ちょろっとハマったところ

ロードバランサーアベイラビリティ〜ゾーンは、サービスと合わせる

ここと

f:id:ororog:20181018182229p:plain

ここ

f:id:ororog:20181018182420p:plain


ヘルスチェックのパスはちゃんと応答するところにする(404とかじゃだめ)
つまり当たり前かもしれないけど、Fargate はHTTP(S)サーバーじゃないとだめ。
f:id:ororog:20181018182630p:plain

パブリックIP の自動割当は ENABLED のほうが良さそう。
サービスをコンテナから作る前提で、docker pull するためには public ip が必要だと思われるので。でももしかしたら VPC 内から docker pull できれば public ip 必要ない気もする。セキュリティ的にアクセスできないほうがいいし。

どうしても動かないときは

公式のチュートリアルにそって動かせばとりあえず動くと思うので、動くものと動かないものを比較して考えるか、公式のドキュメントを1から読むのがいいと思う(動かないときにググるのが難しい)
https://ap-northeast-1.console.aws.amazon.com/ecs/home?region=ap-northeast-1#/firstRun

牛耕式ビューワー

ブログを取得したドメインに移行したいけど何もできてない。。。

牛耕式?

先日こんなツイートで牛耕式というのを知った。

牛耕式文章とは、簡単に説明すると読む方向を左、右、左、右と1行ごとに変え、右から読む列は文字自体も反転して鏡文字になっている文章のこと。

牛耕式 - Wikipedia

慣れたら早く読めるかも!というの気になったので試してみたいと思って作ってみた。

牛耕式ビューワー

作ってみた感想

なんだろう。。。思ったより読みづらい。ツイートの画像はきれいに読めるのに。
思うに、一行が長いのでスラスラ慣れが必要だと思う。あとフォントが小さめだったり文章自体が長かったり文字自体が小さかったりしている。ツイートの画像は文章量が少ないからそれなりに読める気分になっているかも。
あと、英語は対称にすると b, d とか p q とかがマヂ無理なので結構向かないかも。日本語も ちとさ に問題があるけど、英語ほど辛くは無い気がする。結局なれかも。

実装とか

実装の要点は、一行を 1 div に収めること。1div に収まれば、その div を transform: rotateY(180deg); することで反転できます。それを1行ごとに交互にするだけ。

1行1div に収めるには、文字を足したり減らしたりして高さが変わるところで一行としてました。
イメージ的には

var text = "this is a pen.";
var dom = new Div();
var index = 0;
while (height(dom) < 2行分の高さ) {
  dom.text += text[i++];
}
// 一文字余計なので、dom.text から一文字消す

くわしくは
GitHub - ororog/vue-boustrophedon


ついでなので新しい技術をいくつか試していて、 github.io を使って静的ページを公開してみたり、vue + vuetifyjs をつかってた。dom の操作は jquery を使っているけど、せっかくなので jquery を使わないで書きたい。その場合普通に js 書くのかな? vue でオブジェクトを変更して、オブジェクトに連動して view が変わるのが正当な使い方だと思うけど、今回のように dom を操作したい場合なにでやるのがいいのかな?

alpine に lxml をインストールした docker を構築する

alpine に lxml をインストールしようとするとこんなエラーが出る。

...
** make sure the development packages of libxml2 and libxslt are installed **
...
*********************************************************************************
Could not find function xmlCheckVersion in library libxml2. Is libxml2 installed
*********************************************************************************
error: command 'gcc' failed with exit status 1
...
Command "/usr/local/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-96bb0z1d/lxml/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-i0hoswq1/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-install-96bb0z1d/lxml/

結論としては Dockerfile を次のようにしてインストールできた。

FROM python:3-alpine
RUN apk --no-cache add gcc libc-dev libxml2-dev libxslt-dev
RUN pip3 install lxml

libxml2-dev と libxslt-dev は本家に必要と書いてあった
https://lxml.de/installation.html
また g++ と gcc をインストールしてたが、こちらの stackoverflow によるとlibc-dev と gcc でよさそう
https://stackoverflow.com/questions/35931579/how-can-i-install-lxml-in-docker

Docker を調べるのに使ったリンク集

Docker を調べるのに使ったリンクをまとめておく

docker コマンドまとめ
https://qiita.com/voluntas/items/68c1fd04dd3d507d4083
https://qiita.com/curseoff/items/a9e64ad01d673abb6866

起動中のコンテナのシェルに入る
https://qiita.com/sekizo/items/27cc9b406332afc674f6
alpine の場合は
https://qiita.com/yutaChaos/items/56dd7ea09d7e2b0d9173

docker-compose コマンドまとめ
https://qiita.com/wasanx25/items/d47caf37b79e855af95f#down
https://qiita.com/zembutsu/items/9e9d80e05e36e882caaa

Docker コンテナとイメージを消す
https://qiita.com/tifa2chan/items/e9aa408244687a63a0ae

Docker イメージをいろいろと小さくする工夫
https://qiita.com/pottava/items/970d7b5cda565b995fe7

ベストプラクティス。あとで読み返したい。
http://docs.docker.jp/engine/userguide/eng-image/dockerfile_best-practice.html#add-copy

docker のタイムゾーンを設定
http://yoru9zine.hatenablog.com/entry/2017/01/12/224637

ここらへんを読んでなんとなーく Docker を構築できるようになった

ドメイン取りました

http://ororog.org を取得した。
色々調べたところ、無料でドメインを設定してくれるところがあるっぽいので、いくつか試してブログ部分が移行できるか試したい。
ホストとしては、次の2つを試す

有名

  • netlify

調べてたら知った。CI とかできて便利そう。

ブログツールとしては hugo を試す。
hatena みたいに web だけで完結しないので、更新がめんどくなるかもしれないしそうでもないかもしれない。

Requests + BeautifulSoup で html から form データの雛形作成他

Requests と BeautifulSoup は忘れた頃に使って何度も調べるのでメモ。小ネタ。

Requests を使ってログイン処理をするときはだいたいこんな処理をかく。

s = requets.Session()
r = s.get('http://example.com/login')
soup = BeautifulSoup(r.content, 'html.parser')
payload = {
  'id': 'id',
  'password': 'password'
}
s.post('http://example.com/login', data=payload)

payload の部分がこれくらいシンプルならいいけど、csrf token とかをつけて送る場合に BeautifulSoup を使って token 部分を抜き出す必要がある。そんなときはだいたい以下のようなコードを書いて payload の雛形を作る

内包表記ver

payload = {
    input['name']: input['value'] if input.has_attr('value') else ''
    for input in soup.select('form input')
    if input.has_attr('name')
}

for でシンプルに書くとこんな感じ

payload = {}
for input in soup.select('form input'):
    if not input.has_attr('name'):
        continue
    value =  input['value'] if input.has_attr('value') else ''
    payload[input['name']] = value

あとはこの payload に適当に id/pass を詰め込んで post すればよい。

その他メモ

  • BeautifulSoup はdict の ように in を使って要素があるか問い合わせてはダメ('value' in input みたいな)。has_attr を使う。
  • Cookie とか使うなら Session を使う。
  • Session の save / load は pickle でいけそう
import requests, requests.utils, pickle
session = requests.session()
with open('somefile', 'w') as f:
    pickle.dump(session, f)
with open('somefile') as f:
    session = pickle.load(f)
  • findAll ? find_all ? どっちやねん > find_all らしい (最近のpythonのスタイルに従う)

python - beautifulsoup findAll find_all - Stack Overflow

AtCoder ABC 105 D

python に慣れるため久しぶりにプロコンをやってみた。今の AtCoder になってから初だと思う。

D: Candy Distribution - AtCoder Beginner Contest 105 | AtCoder

code

from collections import defaultdict

N, M = map(int, input().split())
A = list(map(int, input().split()))

Amod = defaultdict(int)
sum_mod = 0
for v in A:
    sum_mod = (sum_mod + v) % M
    Amod[sum_mod] += 1

sum_mod = 0
ans = 0
for v in A:
    ans += Amod[sum_mod]
    sum_mod = (sum_mod + v) % M
    Amod[sum_mod] -= 1

print(ans)

解き方、感想

0 .. r (r = 0 .. N) の範囲の和の mod を hash に覚えておく。
0 .. l で l を動かして、0 .. r の和のmodから 0..l の 和の mod を引いて、mod が 0 になるようなもの (hash[ 0..l の和のmod] で個数がすぐに出せる)を足していく感じ。

python は慣れてないけど、defaultdict ないと面倒くさそう。
他の人のコードみて勉強せな。

  • AtCoder は気軽に他の人のコード見れない?topcoder は見れるから勉強しやすい。
  • AtCoder の解説は結構あっさりしてて、わかる人向けの解説って感じがする(解いたけど解説読んでもよくわからない…)。動画を見ればいいのかな。