2021年12月22日水曜日
GitHub Container Registryに公開リポジトリを作ってみた
みなさんはコンテナイメージはどこに置いているでしょうか。
シタテルでは「基本はECR、GCPで利用するイメージはGCR」というまあ普通な構成になっています。
ですがこの度、「せっかく作ったし公開しておいてもいいかな」というコンテナイメージの置き場としてGHCRを使い始めました。
GHCRとは
コンテナレジストリの利用 - GitHub Docs
GHCRはGitHub Container Registryの頭文字で、GitHub上でいろいろなパッケージを公開できるGitHub Packagesの一機能といったところでしょうか。
DockerfileをGitHubで管理するならGitHub上でイメージ配布まで完結するわけですね。
料金ですが、パブリックなパッケージについては無料となってます。今回のニーズにはちょうどいいですね。
About billing for GitHub Packages - GitHub Docs
イメージのpull/push等は ghcr.io/<OWNER>/<IMAGE_NAME>:<tag>
という表記になります。(OWNERはGitHubのユーザー名やorganization名になります)
push前などに認証する場合は以下のようになります。
-
write:packages
スコープを持つアクセストークンを作っておく $ echo <token> | docker login ghcr.io -u USERNAME --password-stdin
リポジトリ作成・push
というわけで、organizationのPackagesにコンテナイメージをアップロードして公開してみましょう。
上記のコマンドで認証したら、好きなイメージ名とタグ名をつけてpushするだけです。
$ echo $GH_TOKEN | docker login ghcr.io -u sitateru --password-stdin
$ docker pull hello-world:latest
$ docker tag hello-world:latest ghcr.io/sitateru/hello-world:latest
$ docker push ghcr.io/sitateru/hello-world:latest
アップロードしたパッケージは、https://github.com/orgs/<OWNER>/packages
のURLで一覧できます。
organizationにアップロードすると、最初はInternalというアクセス設定になるようです。
公開するためには、設定画面から Change package visiblity
をクリックしてPublicを選択。
確認のためパッケージ名を入力してボタンをクリックすれば完了です。
リポジトリと紐づけ
作成したパッケージにはリポジトリを紐づけできるようになっています。
パッケージのページで Connect Repository
をクリックしてリポジトリを選択すればOKです。
紐づけするとリポジトリのREADMEがパッケージのREADMEとして表示されるほか、パッケージのアクセス権限を「紐づけたリポジトリと等しくする」ことができます。管理の手間が楽になってありがたいですね。
どんなイメージを公開するか
現在のところ、ローカル開発環境やCIで使うために公式イメージに一手間加えたようなものばかりです。詳しくはリポジトリをご参照ください。
GitHub - sitateru/docker-images
ご利用はご自由にどうぞなのですが、保証やサポート等はできませんのでご了承ください🙇♂️
タグ追加などの要望があれば、issueなりPRなりいただければできる限り対応しますのでよろしくお願いします。
2021年1月15日金曜日
GitHub dependabot でDockerタグをバージョン指定する
寒い日が続きますね。
ところで皆さんはGitHubのdependabotは使っていますでしょうか?
リポジトリをスキャンして、使っているライブラリやパッケージの脆弱性をお知らせしてくれるサービスですね。
そのdependabotでちょっとした問題を調べて解決したので記録しておこうと思います。
題して「特定のDockerタグを無視する設定の書き方」です。
dependabotの概要や初期設定などはこの記事ではちょっと飛ばしますのでご了承ください🙇
dependabotはDockerタグにも対応していて、脆弱性対応された新しいバージョンタグがある場合はそれを出すようになっています。
例えばリポジトリの docker/Dockerfile
をスキャン対象にする場合、コミットしておく設定ファイル .github/dependabot.yml
はこのようになります。
version: 2
updates:
- package-ecosystem: "docker"
directory: "/docker"
さて、基本的にはdependabotはメジャーバージョンアップも含めて最新バージョンにアップデートさせるように動作するようです。
そのため、Dokerfileで node:14.x.x
イメージを使っている場合
このように node:15
系にアップデートしなよ!というPRが作成されるのです。
でもNode.jsはバージョン14はLTSで15はLTSじゃない・・・更新するなら14系の最新にしてほしい!
というわけで、「Dockerタグの特定バージョンを無視する設定」を調べて入れてみました。
こちらのドキュメントによると、あるバージョンへの更新を無視するためにはdependabot.ymlにそのバージョンを明記すればいいのですが、
範囲を定義する場合は、パッケージマネージャーの標準パターンを使用します
Dockerタグの標準パターンって何だ・・・?🤔
結局わからなかったのでソースを見てみたところ、判定しているのはおそらくこのあたり。
dependabot-core/update_checker.rb at main · dependabot/dependabot-core · GitHub
バージョンの取り扱いに使っているのは Gem::Versionクラス のようです。
class Gem::Version (Ruby 3.0.0 リファレンスマニュアル)
ということはGemfileでバージョンを指定するのと同じ記法で良さそうですね。
dependabot.ymlはこうなりました。
version: 2
updates:
- package-ecosystem: "docker"
directory: "/docker"
ignore:
- dependency-name: "node"
versions: ["~>15.0"]
# nodeイメージの 15.x 系は無視
これでnodeイメージは 15.x
を対象外にして更新するようになりました。
新しく作られるPRは14系の範囲でバージョンアップするものになっていますね。
2018年12月18日火曜日
FirebaseのSDKのプルリクを追ってみた
こんにちは、シタテルの鶴巻です。 devops&インフラ担当です。
最近、firebase/firebase-admin-goの実装で気になったところがあり、プルリクエストから経緯を知ることができました。
GitHub上のソースコードで気になった箇所の経緯を追うことは今後もあると思うので、整理がてら方法を紹介します。
要約
- firebase/firebase-admin-goの実装で気になったところがあった
git blame
コマンドで、ソースコードが最後に編集されたhashを特定- 対象のソースコードが追加されたプルリクエストで経緯が分かった
firebase-admin-sdk-goの実装で気になった箇所
firebase-admin-sdk-goは、名前の通りFirebaseサービスをGolangから扱うためのSDKです。
Firebase Authenticationを試してみた際に、弊社で使用しているRubyのSDKがなかったため、GolangのSDKの実装を少し読んでみました。
そこで、Googleのサーバから公開鍵を取得するメソッドの中で排他制御が行われていることに着目しました。
私はここで排他制御を実施している理由がわからなかったので、経緯を調べることにしました。
該当ソースコードは以下です。
https://github.com/firebase/firebase-admin-go/blob/master/auth/token_verifier.go#L66-L76
func (k *httpKeySource) Keys(ctx context.Context) ([]*publicKey, error) {
k.Mutex.Lock()
defer k.Mutex.Unlock()
if len(k.CachedKeys) == 0 || k.hasExpired() {
err := k.refreshKeys(ctx)
if err != nil && len(k.CachedKeys) == 0 {
return nil, err
}
}
return k.CachedKeys, nil
}
プルリクエストを見つける手順
1. git blame
コマンドで、対象のソースコードが最後に編集されたcommitのHash値を特定
- 対象のソースコードが最後に変更されたcommiのHash値は
f3174984
ということが特定できます$ git blame auth/token_verifier.go | grep -e "k.Mutex.Lock()" -e "defer k.Mutex.Unlock()" f3174984 auth/crypto.go (Hiranya Jayathilaka 2017-05-18 13:45:30 -0700 67) k.Mutex.Lock() f3174984 auth/crypto.go (Hiranya Jayathilaka 2017-05-18 13:45:30 -0700 68) defer k.Mutex.Unlock()
2. GitHubの対象レポのプルリクエストをHash値で検索
- プルリクエストが見つかりましたー!🎉🎉🎉
https://github.com/firebase/firebase-admin-go/pull/3
実装の理由は?
- プルリクエストのコメントにありました
- 複数のスレッドが共有している公開鍵のキャッシュを同時に更新するのを防ぐためにmutexを導入したみたいです。
Introduced a mutex to prevent multiple threads from updating the shared cache concurrently.
- ソースコードを追うと、公開鍵取得のメソッドは httpKeySource構造体に定義されており、さらにhttpKeySourceはClient構造体に定義されています。SDKを使う際に最初にClientの初期化を行いますが、初期化した同一のClientで公開鍵取得メソッドがconcurrencyに実行されても安全なように実装されているのかなと考察しました。
firebase-admin-sdk-goはgit-flow
firebase-admin-sdk-goはgit-flowで開発されているようです。
そのため、masterのソースコードのcommitのHash値がプルリクエストがマージされた時のHash値と同じで、プルリクエストが見つけやすかったです。
おまけ(nodejsの実装)
Node.jsのSDKの同じ箇所の実装についても少し覗いてみました。
Node.jsを書いたことはありませんが、見る限り排他制御はしていないように見えます。
Node.jsはシングルスレッド推奨だから排他制御しなくていいのか・・・など思い、言語の特性の違いが垣間見えて面白いですね。
- firebase-admin-node
- 公開鍵取得 https://github.com/firebase/firebase-admin-node/blob/master/src/auth/token-verifier.ts#L260
まとめ
- オープンソース文化いいですね。今回の例だとfirebaseの中の人が書いたソースコードや、そのプルリクを見ることができています(もしかしたら中の人じゃないかもしれませんが)。エンジニアとしては当たり前な文化ですが、ブラックボックス化されている業界が多いなか改めて良い文化だと思いました。
- シタテルはRailsを使用しているので、RubyのSDKがあればFirebase Auth導入してみたかったのですが残念です。
2018年11月16日金曜日
githubイシュー/PRの管理にjasperを導入したら幸せになった話
こんにちは!
シタテルで エンジニアをしている建山です。
主に工場向けのマイオペというシステムの開発を行っています。
シタテルではgithubを使ってソースコード・イシュー/PR管理などをしています。
その中で、困るなとおもっていたのがイシューへのアサインやコメントに気づく仕組みでした。
PRやイシューで自分にアサインやコメントされているにもかかわらず、気づくかない、気づくのが遅くなるなど、あげくのはてに、slackでメンションもらったりということもありました。
そこで、リアルタイムに通知を受け取ったり、メンションにもれなく気づけるようになりたいとおもっていたところ、社内のエンジニアにjasperよさそう!とおしえていただいて実際便利でしたので紹介します。
jasper以外にもいい方法はいくつかあるとおもいますが、今回はjasperを使った方法を記載します。
jasperとは
githubのイシュー/PRを閲覧や管理をしやすくするソフトウェアです。
Mac版/Windows版/Linux版があります。
https://jasperapp.io/
cookpadのエンジニアの方がつくられているようです(https://techlife.cookpad.com/entry/2017/03/14/100000
)
ほとんどここに書かれています。
jasperを使った方法
jasperにはstreamsを登録する機能があります。こちらに登録しておくと、
条件ごとに一覧で見ることができて、通知を受け取りたい場合は、特定のstreamだけ通知を受け取るということもできます。
私が通知を設定しているstreamsはこちら。
公開中のイシューで自分にメンションもらっているリスト
is:issue is:open mentions:ユーザー名
公開中のイシューで自分に レビューリクエストもらっているリスト
is:open is:pr review-requested:ユーザー名
PRで自分にアサインもらっているリスト
is:open is:pr assignee:ユーザー名 archived:false
公開中のPRで自分にメンションもらっているリスト
is:pr is:open mentions:ユーザー名
まだ使いこなせていないのですが、ほかにもたくさんの用途にstreamを分けることができます。
https://jasperapp.io/doc.html#stream
個人的には、jasperを使いだして、github上でするべきコメントを、slack上でやることが減ったと感じています。github上にもコメントで経緯ものこるので、いいなと感じています。
日々、改善しながらやっていきたいと思います!
2018年11月6日火曜日
DXF TIIPビューワ
こんにちは!
シタテル株式会社CTOの和泉です。
シタテルではユーザー様からの相談を相談をお受けして、衣服の生産管理を行っています。
その際、衣服のパターンデータをいただきますが、このパターンデータはDXFという形式のファイルで送られてきます。
正確にはDXFを拡張したアパレルCADデータ互換のTIIP規約としてフォーマットが規定されています。
このファイルは通常、専用のソフトウェアを使って編集、閲覧するのですが、
「ブラウザ上でユーザー様とメッセージのやり取りをしている中でいちいちダウンロードして確認してというのは効率が良くないから、ブラウザで見たい!」
という現場からの要望がありました。
ということで、DXF TIIPのファイルをブラウザ上で閲覧できる簡易ビューワーを作りました!(1年ぐらい前に)
突貫工事で作ったのであまりできはよくないですが、ザックリとファイルの中身を 見られるので重宝していただいてます。
シタテルの SCSやマイオペレーター、マイアトリエにも組み込まれています。スマホでも見られるので外出先でちょっと確認したいときにも便利です。
フォーマットが見つからなかった、、、
実装するときにファイルフォーマットをダウンロードしよう思ったのですが、ちょっと探しただけでは見つけられず。
いや、きっと私の探し方が悪かっただけだと思うんですが、、、
結果、バイナリエディタとにらめっこしながらなんとなくで作りました。
TIIPはDXFのコメントエントリ(用語適当です、ごめんなさい)の部分を拡張してあるフォーマットだったので、なんとなくで読み取ることができました。
DXFの読み取り
DXF自体の読み込みには three-dxf を利用しました。
そのままだと読み取りできない部分があったのでもとのリポジトリをフォークして少し編集しています。
おわりに
今回のDXFの話はちょっとした部分を便利にしただけですが、 シタテルではこのように現場の声を毎日聞きながらエンジニアが開発を行うことで、現場にフィットした機能を作り、効率性を高めることで多くの相談をすばやく処理して、ユーザー様の衣服づくりをサポートしています。
2018年10月29日月曜日
シタテルの技術ブログについて
こんにちは!
シタテル株式会社CTOの和泉です。
今日はシタテルの技術ブログの管理について紹介します。
シタテルは衣服づくりのプラットフォームを提供しているスタートアップ企業ですが、
実は3分の1以上がエンジニア、デザイナーというIT企業でもあります。
(あまり知られてないので主張します!)
突然ですが、ここで質問です!
プログラマの好きなもの3つはなんでしょう?
答えは!?
GitHub
マークダウン
デプロイ自動化
ですよね!そうに違いない!
この独断と偏見に基づいて、シタテルの技術ブログはマークダウンで記述して、GitHubで管理レビューをして、
CircleCIによって自動的にデプロイされる仕掛けにしてみました。
この仕組で社内のメンバーの皆さんに1スプリントに1ブログをお願いしています。
さて、今回はその 仕組みと投稿の手順を簡単に紹介します。
しくみ
仕組みと行っても難しいことをしているわけではないのですが、、、
APIの充実したブログサービスとして、知識のない私はBloggerしか思いつきませんでした。
しかし、Bloggerはマークダウンでは投稿できません。なので、マークダウンで記述したファイルをプログラムでHTMLに変換しています。
また、画像等のファイルは マークダウンで書いたテキストそのままを投稿してもどうにもなりませんので、変換後のHTMLのDOM構造からリンクURLを抽出してAmazon S3にアップロード&URLの書き換えを行っています。
以下の手順に出てくるURLはシタテル社員限定公開なのですが、
こちらの公開リポジトリでその部分のコードはご覧いただけます。
https://github.com/shinobushiva/blogautomation
手順
前準備(初回のみ)
1. https://github.com/sitateru/tech-blog をクローン
git clone https://github.com/sitateru/tech-blog
2. masterブランチから新しいブランチを作成してチェックアウト
git branch shinobu.izumi
git checkout shinobu.izumi
ここでは例として shinobu.izumi
というブランチを作っています。
ブランチは1人1つを使いまわしても、各自が記事ごとに切るなどしても構いません。
3. posts/blog/
配下に個人のフォルダを作成(フォルダ名は個人が特定しやすい名前にしてください)
ここでは例として shinobu.izumi
というフォルダを作っています。
新しい記事を追加する場合
0. masterブランチをpull
最新のmasterブランチを忘れずにpullします。
1. 自身のフォルダ内に記事のフォルダを作成(フォルダ名は自由)
2. フォルダ内に記事を作成
最低限必要なファイルは content.md
とmeta.json
です。
content.md
投稿する記事の内容をマークダウン形式で記述します。
meta.json
記事のメタ情報を記述します。親フォルダの内容を継承しますが、子フォルダの内容で上書きされます。
例は最後に記述してあります。
3. ブランチをリモートリポジトリにプッシュ
git push origin shinobu.izumi
4. publish ブランチ向けにPR
GitHub上で publishブランチに向けてPRを出します。
レビュー後にマージします。
meta.json 例
{
"blogId": "1797929185044797553",
"isDraft": true,
"publish": false,
"revert": false,
"isPage": false,
"ignore": false,
"forcePost": false,
"contentPath": "content.md"
}
{
"ignore": false,
"resource": {
"title": "シタテルのオンライン衣服生産システム"
}
}
以下はBloggerAPIへの指定パラメーター(の一部)です。
キー | 意味 |
---|---|
blogId | 投稿対象とするブログのIDです |
isDraft | true - 下書きとして投稿します |
publish | true - 下書きのものを公開に変更します |
revert | true - 公開のものを下書きに変更します |
resource.title | 記事のタイトルを指定します |
以下は本システム向けの設定です。
キー | 意味 |
---|---|
isPage | true - ページとして投稿, false - 記事として投稿 |
ignore | true - そのフォルダの記事に対する処理を無視 |
forcePost | true - すでに記事が存在している場合でも新しく記事を投稿 |
contentPath | マークダウンファイルの名前(変更の必要なし) |
記事のブログへの公開
publishブランチにマージすると、CircleCIが動いて自動的にブログに投稿します。
CircleCIの内部で公開日時などのメタ情報を更新したものをmasterブランチにプッシュします。これにより公開情報をGithubに記録しています。
おわりに
以上、シタテルの技術ブログの管理についてでした。
これから、シタテルで働いているメンバーが使っている技術や日々の業務の中で取り組んだ内容などをお伝えしていきます !