docker-tag: name: Tag docker images runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: aws-actions/configure-aws-credentials@v2 with: #... - name: Tag branch to docker images run: | MANIFEST=$(aws ecr batch-get-image --repository-name my-repo --image-ids imageTag=${{ github.sha }} --output json | jq --raw-output --join-output '.images[0].imageManifest') aws ecr put-image --repository-name my-repo --image-tag latest --image-manifest "$MANIFEST"
Slack用のChatGPTボットを作った
Slackで会話できるChatGPTボットを作った。 Getting Startedの通りにすれば10分ぐらいでインストールできると思う。
すでにSlackの中の人がChatGPT-in-Slackとかchatgpt-on-denoというのを作っていてそっちの方がはるかに高機能だけど、社内のSlackボットを細々とメンテしているので、その延長で作ってみた。
仕組み
スレッドの発言をconversations.repliesでとってきて、ボットへのメンションをuser
、ボットの発言をassistant
としてChat Completion APIに投げている。
すぐにトークンの上限に達するかと思ったけれど、そこそこきちんと動いているように見える。
system message
DEFAULT_SYSTEM_MESSAGEという環境変数でsystem messageを送るようにしてボットの振る舞いを変えることができる。たとえば
DEFAULT_SYSTEM_MESSAGE="あなたはメイド喫茶のメイドです。語尾には「にゃん」をつけてください"
と設定すると、こんな感じの会話になる。
また、system
をメッセージの頭につけることで、ボットの振る舞いを動的に変えられるようにした。
Chromeの拡張機能を作った
GitHub Actions issue linkというChromeの拡張機能を作った。
pushイベントで実行されたGitHub ActionsにはマージされたPRへのリンクはないが、タイトルには「#1234」とPR(Issue)番号があることが多いので、それをPR(Issue)へのリンクに変換する拡張機能。develop→masterへのPRがマージされたタイミングでGitHub Actionsが走った場合などに、ActionsのページからトリガとなったPRへ遷移できる。
手始め
拡張機能の作成にあたって、まずは公式のチュートリアルドキュメントとサンプルを参考にした。
manifestがV2からV3への移行中なのでサンプルの一部がアーカイブされていたりしたが、JavaScriptで書く分には十分に網羅されていると思う。
最初、content_scriptsでコンテンツを置換していたが、SPAだと置換されないので onUpdated をフックして置換するようにした。
TypeScript
その後、TypeScriptで実装したくなったので調査。ググるとWebpackを使った解説が多かったがそこまで必要性を感じず、vite@latestを使った r7kamuraさんのやり方 を参考にした。@crxjs/vite-plugin
は 現在の vite@latest
に対応していないので @crxjs/vite-plugin@beta
をインストールする必要があるが、それ以外はほぼほぼそのまま。
Chrome Web Storeでの公開
Chrome Web Storeでの公開方法もオフィシャルのドキュメントに概ね従った。
ただ、プライバシーポリシーや住所が必須と書かれているわりに必須でなかったり(素直に住所を登録すると拡張機能のページでインターネット公開されてしまった)、欧州経済領域(EEA)のトレーダー申告が必要だったり、gemやnpmのライブラリを公開するのとは趣が違うことに戸惑った。
結局、
- プライバシーポリシーのURLはなし
- 住所は未登録(登録したが削除した)
- 「欧州経済領域(EEA)のトレーダーではない」
として、審査を通した。
審査期間は2〜3日ほど。「host_permissionsを必要としているので時間がかかるかも」とのメッセージが出ていたが意外に時間はかからなかった。
その他
- 公開にあたってアイコンが必須だったので icooon-mono.com のアイコンを使わせてもらった
- iconfinderで購入したアイコンは「ロゴへの使用禁止」という項目があり、Chrome Web Storeに表示されるアイコンがロゴにあたるのかよくわからくて利用を避けた
- プライバシーポリシーが必須だった場合に備えてポリシーを作ってくれるサービスを探した
- 結局使わなかったが、そのうち使う機会があるかもしれない
バベル案内での「STLの作者がOOPは嫌いだと言ったという話」
昔読んだSteve Yeggeの「バベル案内」のC++ の話に「STL作者が OOP は嫌いだと言っていてショックを受けた」ということが書いてあって、ふーんと思っていたが、最近Alexander Stepanovのインタビュー記事を読んでいてそれっぽい話があった。
Yes. STL is not object oriented. I think that object orientedness is almost as much of a hoax as Artificial Intelligence.
この人の別のインタビュー記事も面白い。
Using animals as an example (OO people love animals)
動物を例にとると (OO 人は動物が大好きです)
Let's consider now why C is a great language. It is commonly believed that C is a hack which was successful because Unix was written in it. I disagree. Over a long period of time computer architectures evolved, not because of some clever people figuring how to evolve architectures---as a matter of fact, clever people were pushing tagged architectures during that period of time---but because of the demands of different programmers to solve real problems. Computers that were able to deal just with numbers evolved into computers with byte-addressable memory, flat address spaces, and pointers. This was a natural evolution reflecting the growing set of problems that people were solving. C, reflecting the genius of Dennis Ritchie, provided a minimal model of the computer that had evolved over 30 years. C was not a quick hack. As computers evolved to handle all kinds of problems, C, being the minimal model of such a computer, became a very powerful language to solve all kinds of problems in different domains very effectively.
なぜ C が優れた言語なのかを考えてみましょう。C は Unix が C で書かれているために成功したハックであると一般に信じられています。同意しません。長い時間をかけてコンピュータ アーキテクチャが進化したのは、一部の賢い人々がアーキテクチャを進化させる方法を考え出したからではありません。実際の問題を解決するためのさまざまなプログラマ。数値だけを処理できるコンピューターは、バイト アドレス指定可能なメモリ、フラットなアドレス空間、およびポインターを備えたコンピューターに進化しました。これは、人々が解決しようとしていた一連の問題の増大を反映した自然な進化でした。C は、デニス リッチーの天才を反映して、30 年以上にわたって進化してきたコンピューターの最小モデルを提供しました。Cは簡単なハックではありませんでした。コンピューターがあらゆる種類の問題を処理するように進化するにつれて、そのようなコンピューターの最小モデルである C は、さまざまなドメインのあらゆる種類の問題を非常に効果的に解決するための非常に強力な言語になりました 。
Fargate: nginxコンテナをreadonlyRootFilesystemで動かす
監査上の理由からFargateがreadonlyRootFilesystemで動いてほしかったので、nginxコンテナを使った検証のメモ。
基本方針
- nginxイメージそのままでは動かないのでカスタムイメージを作る
/var
をタスクストレージにマウントする/tmp
は/var/tmp
へのsymlink- 二つ以上のタスクストレージをマウントできなかったため(二つ目以降のmountPointは無視された)
Dockerfile
FROM --platform=linux/amd64 nginx VOLUME /var # `VOLUME` を指定しておかないと # 元々のイメージにあるファイルが # マウントしたボリュームにコピーされなかった RUN rmdir /tmp && \ ln -s /var/tmp /tmp && \ rm /var/run /var/lock && \ mv /run /var/run && \ ln -s /var/run/lock /var/lock # このイメージでは `/var/run` `/var/lock` は # ぞれぞれ `/var/run` 配下へのsymlinkになっているので # 構成を変更する
ECSタスク定義 (ecspresso)
{ containerDefinitions: [ { cpu: 0, essential: true, image: '123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/my-nginx:latest', name: 'my-nginx-ro', portMappings: [ { containerPort: 80, hostPort: 80, protocol: 'tcp', }, ], readonlyRootFilesystem: true, mountPoints: [ { sourceVolume: 'var', containerPath: '/var' }, ], }, ], cpu: '256', memory: '512', taskRoleArn: 'arn:aws:iam::123456789012:role/MyTaskRole', executionRoleArn: 'arn:aws:iam::123456789012:role/MyExecRole', family: 'my-nginx-ro', networkMode: 'awsvpc', requiresCompatibilities: [ 'FARGATE', ], volumes: [ { name: 'var' }, ], // 必須ではない // ephemeralStorage: { // sizeInGiB: 50, // }, }
動作確認
root@ip-10-0-3-229:/# touch x touch: cannot touch 'x': Read-only file system root@ip-10-0-3-229:/# touch /tmp/x root@ip-10-0-3-229:/# touch /var/tmp/x root@ip-10-0-3-229:/#
その他
- 何もマウントしないと
/etc/hots
がタスクストレージにマウントされているように見えたが、なぜ… /var
がread onlyになるとECS execできなくなるということがわかった- タスクストレージで複数のmountPointを使う方法はわからなかった
- タスクストレージ以外でマウントするとなるとEFSかsidecarのボリュームか
- DockerボリュームはFargateでは使えないっぽい*1
参考
- Fargate タスクストレージ - Amazon Elastic Container Service
- バインドマウント - Amazon Elastic Container Service
- Docker ボリューム - Amazon Elastic Container Service
- コンテナのセキュリティ対策!AWS ECS (fargate)でタスクをreadonlyRootFilesystemで運用する | SEEDS Creators' Blog | 株式会社シーズ
2023/05/28 追記
ephemeralStorageをマウントしなくても書き込み可にはなった あとVOLUMEを複数書けば symlinkをごにょごにょしなくても、書き込み可のディレクトリ増やせた
ecs-login-helperの実行時に環境変数を追加するやつ
複数のAWSアカウントのECRからdocker pullするときに、いちいちプロファイルを指定するのがめんどくさいことがあったので(docker-composeとか)、環境変数を追加するecs-loginのラッパーを作った。
~/.docker/ecr-login-env.json
に以下のような感じで設定を書いておいて
{ "123456789012.dkr.ecr.us-east-1.amazonaws.com": { "AWS_PROFILE": "my-profile" } }
~/.docker/config.json
の ecr-login
を ecr-login-with-env
に差し替えると
{ "credHelpers": { "123456789012.dkr.ecr.us-east-1.amazonaws.com": "ecr-login-env" } }
docker pull/pushなどをするときにecr-loginに環境変数 AWS_PROFILE=my-profile
が渡されるようになる。