Docker Volumeが削除できない!
背景
ローカルマシンのDocker VolumeのMount先を変更しようとしたときに、Volumeが消せなくなって困った
環境
エラーメッセージ
Cannot remove volume XXX. Reason: Error invoking remote method 'docker-remove-volume': Error: (HTTP code 500) server error - remove XXX: volume has active mounts
結論
- 利用しているコンテナは停止した上で、きちんとGUIから削除する
- 削除した後もVolumeがコンテナの残骸を見てることがあるので、Docker Desktopを再起動する
docker system prune
をやってもダメだった
改めて調べてみたら docker compose down --volumes
を実行すればよかったっぽい。
確かに docker compose
から作成したボリュームだった・・・。
Docker Desktop (M1 Mac) でVolumeが作れない
課題
docker compose up
を実行すると、以下のエラーが発生する
ERROR: for postgresql Cannot start service db: error while mounting volume '/var/lib/docker/volumes/postgresql_db/_data': failed to mount local volume: mount /tmp/postgresql/data:/var/lib/docker/volumes/ghost-postgresql_db/_data, flags: 0x1000: no such file or directory
環境
結論
Preferences > General にある Use gRPC FUSE for file sharing
のオプションを無効化する
関連するGitHub issue:
状況
version: "3.9" ... volumes: db: driver_opts: type: none device: /tmp/postgresql/data o: bind
こんな感じで、ローカルにマウントするボリュームを書いていると、冒頭のエラーが発生しContainerが立ち上がらない。
Volumeは作成されているものの、そんなファイルはない、と怒られてしまう。
結論に書いた通り、オプションのせいで動かなかった。 詳細は調べてないので、わかる方いたら教えてほしいです。。
社内システムの認証にOktaを使って楽をする
背景
- 社内システムを使うのにアカウントの管理が面倒だった
- ちょうどOktaを使い始める風潮があったので相乗りしたかった
前提
- Oktaを導入している
やること
- Oktaのアプリを登録する
- フロントエンドでOktaのSSOを実装する
- バックエンドでアクセストークンの検証をする
参考
- フロントエンド (Next.js)
- バックエンド (NestJS)
実装の一部
フロントエンド
// pages/api/auth/[...nextauth].ts import NextAuth from 'next-auth'; import provider from 'next-auth/providers'; export default NextAuth({ providers: [ provider.Okta({ clientId: process.env.OKTA_CLIENTID, clientSecret: process.env.OKTA_CLIENTSECRET, domain: process.env.OKTA_DOMAIN, }), ], theme: 'auto', });
アプリを登録した際に発行されるClient ID/Client Secretを渡してあげる。
DomainはHTTPスキーマを抜いた形式 (xxx.okta.com/oauth2/$issuer
)
pages/api/auth/[...nextauth].ts
のパスはnext-authの指定。
NextAuth.jsに処理を以上するためには/api/auth/*の形式である必要がある。
バックエンド
基本的には参考したURLのものそのままだが、やることは以下
- passport jsの実装
- guardsの実装
Passport Strategyをまず実装する。
// auth/http.strategy.ts import { HttpException, Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-http-bearer'; import { AuthService } from './auth.service'; @Injectable() export class HttpStrategy extends PassportStrategy(Strategy) { constructor(private readonly service: AuthService) { super(); } async validate( token: string, done: (error: HttpException, value: boolean | string) => any, ) { try { return await this.service.validateToken(token); } catch (error) { done(error, 'token is invalid'); } } }
AuthService内で実際の検証作業を実施する。 validateはAuthGuardによって呼ばれており、User等を返すとそのままリクエストに付与してくれる。
ガードしたいエンドポイントにデコレータで宣言すれば終わり。
// user.controller.ts @Get() @UseGuards(AuthGuard('bearer')) async getUsers(): Promise<User[]> { return this.service.getUsers(); }
CoverityとJIRA CloudをIntegrationする
背景
- Coverityで発見された脆弱性をJIRAに起票したい
- 大したことは書かないけどちょっと詰まったので脳から消す意味でも書き残す
参考
環境
- Coverity Platform
やること
- Configuration > System > バグ追跡システム:JIRA から設定を作成する
詰まりポイント
- JIRA サーバーの設定で
場所
をどこに設定するか - パスワードは何を設定するか
JIRA サーバーの設定で 場所
をどこに設定するか
https://XXXX.atlassian.net/
を指定する。
ログイン直後ではなく、このURIを指定する必要がある。
内部的にはJavaで実装され、AtlassianのSDKを利用している。
そのため、接続方法はそれに則る必要がある。
パスワードは何を設定するか
上記の通り、AtlassianのSDKに実装されている方法で設定を組む必要がある。
参考に挙げた2件目で言及されている通り、Basic認証時に利用するパスワードの値が変更されたため、
JIRAでAPIトークンを発行し、その値を利用する必要がある。
Cloud Run x Cloud SQLでGrafanaをTerraformで立てる
背景
- プロダクトの監視に安くダッシュボードを作りたい
- 運用コストをあんまり上げたくない
=> (フル)マネージドな環境でGrafanaを立てればええやん
TL;DR
前提
- GCPのプロジェクトがセットアップされている
構築手順
- Terraformを記述する
- Deployする
以上
Terraformの環境セットアップ
terraform --help
コマンドが使えない人向け。
公式に従ってインストールするのも良いけれど、バージョン管理が面倒だと思うので、tfenv
を入れる。
GitHubに記載の手順に従ってインストールする。
Macなので brew install tfenv
を実行すれば良い。
その後、tfenv install latest && tfenv use latest
を実行すると terraform --help
が使えるようになる。
.tfファイルを実装する
必要になるのは大きく分けて2つ。
- GCPの定義を書いた.tfファイル
- Grafanaの定義を書いた.tfファイル
またそれらのProviderを管理するためのファイルの3つで管理すると見通しが良い。
GCPの定義
作成する必要があるのは、
3つ目はCloud SQLをPublicなネットワークに公開する覚悟がある人は不要だと思う。
私は自信がないのでVPCを貼ってその上で接続するようにしている(というか参考にしたものがそうだったのでそれに乗っかっただけ)。
詳細は 参考先のソース を見てもらったほうが早い。
複数人で運用する想定なら、tfstatをGCSにあげて管理するのも考えて良いかも。 その場合は以下追記する。
terraform { backend "gcs" { bucket = "事前に手作業で用意したバケット名" prefix = "バケット内のパス(必要があれば)" } }
terraform"を"管理するためのリソースはterraform外で管理されるべき、というどこかで聞き覚えたものに従ってるので手作業が必要。
(元ネタ誰か分かったら教えてほしいです、、、)
Deployする
Service Accountでの適用が望ましいため、GCP上でService Accountおよびキーの払い出しを行い、
GOOGLE_APPLICATION_CREDENTIALS
に取得した鍵ファイル(.json)のパスを指定してあげる。
その上で、terraform apply
を実施する。
defaultが未定義な変数に関しては対話式で聞かれるので回答してあげればOK。
初回はDB構築等も含まれるので5分以上かかるかも。
以上。
ハマりポイント
- Service Accountの権限
必要な権限のみを割り当てるべき、という大原則は認識しているものの、洗い出しが面倒だったのでオーナー権限付けた。
特にネットワークの構成あたりで死んでたのはこれで解決した。編集者じゃ足りない模様。
- Cloud SQLの削除に失敗して
terraform destroy
もterraform init
も通らんくなる
コンソールから残ってしまったリソースを削除した上で、tfstatファイルも削除する。
と、terraform apply
が通るようになる。
ボツにした構成
- GKEに立てる
- GCEにインスタンスを立てて、その上でDocker Composeで拡張性を考慮した構成にする
GKEに立てて上げるほどのものでもなかったので、 && キャッチアップコストが高すぎたので却下
GKEに慣れている人は多分サクッと構築出来るんだと思う。
GCEにインスタンス立ててやるのはSSL証明書の準備やロードバランサの構成等を考えるのが面倒だったので却下。
またContainer Optimized OSの癖が強すぎるのもあったw