Cloud StorageのFake Serverをdocker-composeで実行する

Cloud Storage*1使っていますか?

私は最近、画像の保存場所によく使っています。

最近使ったものだと、大学のプロジェクトで作っているWebアプリのユーザアバターを保存する場所として使っています。

github.com

さて、このCloud Storageですがテストを書いたりデバッグをする中でローカルで実行させたいという話題がでます。

そのため、このブログではCloud Storageをdocker-composeで実行させる方法とかちょっと便利な使い方とかを紹介します。

fake-server

Cloud Storageは公式でローカルのDockerイメージは提供されていません。

そのため、fsouza/fake-gcs-serverを使用します。

github.com

version: '3'

services:
  gcs:
    image: fsouza/fake-gcs-server
    tty: true
    ports:
      - 4443:4443
    volumes:
      - ./.data:/data/[bucket name]
      - ./.storage:/storage
    command: -scheme http -public-host ${URL:-localhost}:4443

ここで、注意しておきたいのがvolumes/data/以下がbucket nameになる点です。ここで、bucket nameの空のディレクトリを作成しておかないとbucket nameを指定して接続した際にエラーが発生してしまいます。

また、fake-server実行時の-public-hostフラグはhttpで使用する際には必須となります。これは、その画像にアクセスできるホストを定義するもので通常、デバッグ用途などで使用するならlocalhostで十分です。しかし、SSHで作業している場合など特殊な場合を想定してURL環境変数が定義されている場合はそちらを使用するようにします。

docker-composeの環境変数.envに書くかexportするかで定義することができます*2

さらに、fake-serverで保存されているファイルは.storageにマウントすることでテストなどでちゃんと設定できているかも確認できます。

アプリケーションコード

これは、fake-serverが例を紹介しています。

github.com

おそらく、全てGoogle公式のGCSのパッケージを使用してアクセスできます。

Goとかはアクセスするのが一番簡単でSTORAGE_EMULATOR_HOST環境変数にfake-serverのホストを入れればそのままそこにアクセスしてもらえます。

// Set STORAGE_EMULATOR_HOST environment variable.
err := os.Setenv("STORAGE_EMULATOR_HOST", "localhost:9000")
if err != nil {
    // TODO: Handle error.
}

// Create client as usual.
client, err := storage.NewClient(ctx)
if err != nil {
    // TODO: Handle error.
}

// This request is now directed to http://localhost:9000/storage/v1/b
// instead of https://storage.googleapis.com/storage/v1/b
if err := client.Bucket("my-bucket").Create(ctx, projectID, nil); err != nil {
    // TODO: Handle error.
}

https://pkg.go.dev/cloud.google.com/go/storage#section-readme

Node.jsなんかは、そういった便利な環境変数は定義できないのでStorageオブジェクトのコンストラクタに引数で指定します。

// Creates a client
const storage = new Storage({
  apiEndpoint: "http://localhost:8080",
});

上記コードだとローカルしか実行できないので、以下のようにすると良さそうです。

let config = undefined;

if(process.env.NODE_ENV !== "production") {
  config = {
    apiEndpoint: "http://localhost:8080",
  };
}

const storage = new Storage(config);

公開する

GCP内の実行環境にデプロイすれば特に設定することもなく簡単にCloud Storageに接続できます。

// これで、何も設定しなくてもつながる(GCP内のサービスか、環境変数が設定されている場合)
const storage = new Storage();

また、別の環境でも同じことをしたい場合はGOOGLE_APPLICATION_CREDENTIALS環境変数にサービスアカウントキーの絶対パスを指定することでも可能*3です。

cloud.google.com

まとめ

GCSは便利なのでみんな使おう!!!

キーボード新調した

私のPCで使用しているキーボードは、6年ぐらい前に買ったものでした。

PCでゲームをよくするため、Logicool製の青軸ゲーミングキーボードです。

今、Amazonで調べたんですけどまだ売っているんですね。このキーボード、色が白でゲーミングによくあるカラフルにはできないのは欠点ですが音量調節ダイヤルがついていたりと色々使い勝手が良かったです。

買い替えた理由

主に3つあります。

1つ目は、このキーボードは青軸で結構音がうるさいことです。友達と通話しながらゲームをするときなどキーの音が入ってしまって結構ゲームに支障がありました。現在はDiscordがうまくフィルタしてくれているのでそういう問題はないと思いますが、家の壁が薄いので隣に響いてしまうぐらいには大きい音なのでいい加減新調しないとと思っていました。
(また、青軸は結構指が疲れるので長い時間ゲームをやっていると指が鍛えられるという問題?が起きていたのもあります。)

2つ目は結構使ってて寿命が来たことです。4年以上使っているのでDボタンのキーキャップが壊れていれ応急処置的にPgUPのキーとキャップを交換していてDボタンがPgUPになっていました。

最後はマイナポイントという不労所得が入ったことです。15000円貰えました!やったぜ

新しいキーボード

新しく買ったキーボードはRazerのBlackWidow V3 JP Yellowです。

青軸以外のゲーミングキーボード触るのってお店の展示以外はないので実際にゲームやるとすごく新鮮です。まじで指が疲れない!!!

また、このキーボード前のキーボードと同じく音量調節ダイヤルがついているのもポイント高いです。

新しいキーボードの欠点

1つあります。

黄軸はアクチュエーションポイントが1.2mm*1と短いのでキーに指を置いているだけで誤動作してしまうことが結構あります。多分慣れの問題なので時間が経てばなくなると思いますが勝手にピン刺されたりもの捨ててしまったりするので今は結構厄介な問題です。

まとめ

買ってよかった!!マウスもキーボードと同じぐらいの時期に買っているで早めに新調したい!!

自分に合った会社を選ぶということ

去年あたりに辞めた2年間ぐらいやっていたインターンで、メンターが推していた本を思い出した。

Soft Skillsというソフトウェア開発者がどう人生を生きるかの説明書みたいな本で当時、日本語版を買っていたが就活で会社選びに大いに役に立ったものがあったので少しメモ程度に。

  • 買ったのは、3年ぐらいまえなので第1版である。

小、中、大企業にはそれぞれメリット・デメリットがある

これは、当時すごく衝撃的でいまでも良く思い出す。就職活動をするときなどにも自分に合っているのかを見極めるため大いに役に立った。

内容は要約すると以下のようになる。

メリット デメリット
小企業 柔軟、高い報酬の可能性 コードを書くだけではない、安定しない
中企業 安定 変化のペースが遅い
大企業 教育、大規模プロジェクトに関われる 官僚的

私は、ぶっちゃけると官僚的な職場はあまり行きたくない。特に日本だと年功序列*1が根強くのこっているイメージがあり、楽しく仕事ができなさそうな気がする。

また、ソフトウェア開発会社かソフトウェア開発者がいる会社かという問題もある。

自分は、ソフトウェア開発会社が好き。

*1:年功序列はメリットもあることは認識しているが、自分の性格に合わない気がする

MySQLのテーブルをGitHubリポジトリで操作する

最近、趣味アプリ用にCloudSQLでSQLのサーバを作成しました。

そこで、SQLマイグレーションを自動化するべくGitHubリポジトリで操作しようと思います。

以下の記事を参考にしました。

blog.fukkatsuso.com

作成したリポジトリは以下です。

github.com

CloudSQLに接続できるようにする

gcr.io/cloudsql-docker/gce-proxyを使用してDocker経由でCloudSQLに接続します。

公式ドキュメントにはdocker runを使用していますが、私はdocker-composeを推しているのでこちらで実行できるようにします。

version: "3"

services:
  datastore:
    image: gcr.io/cloudsql-docker/gce-proxy
    ports:
      - "127.0.0.1:3306:3306"
    volumes:
      - ./config/:/config
    command:
      [
        "/cloud_sql_proxy",
        "-instances=$CLOUDSQL_INSTANCE_CONNECTION_NAME=tcp:0.0.0.0:3306",
        "-credential_file=/config/sa_key.json"
      ]

設定として、.config/sa_key.jsonにサービスアカウントキーを置きます。 また、リポジトリのルートに.envを作成しCLOUDSQL_INSTANCE_CONNECTION_NAMEを設定します。 この値はCloudSQLの「接続名」を入れます。

これで、docker-compose up -dを実行することでMySQLに接続ができます。

マイグレーション

今回、このMySQLは複数のアプリケーションで使用することを想定しています。そのため、データベースを複数作成したいという話題があります。そのため、ディレクトリでデータベースを分けられるような設定を追加します。

db/**ディレクトリ名 = DB名とします。

#!/bin/bash

FILES="db/*"

source ./.env

for DATABASE_PATH in $FILES; do

  DATABASE=${DATABASE_PATH##*/}
  echo "------- Migration DB: ${DATABASE} -------"

  MYSQL_DSN="mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@tcp(127.0.0.1:3306)/${DATABASE}"

  migrate -path "${DATABASE_PATH}" -database "${MYSQL_DSN}" up

done

このスクリプト環境変数.envMYSQL_USERMYSQL_PASSWORDを設定します。 これで、このスクリプトを走らせることでマイグレーションができます。

マイグレーションを実行する

テーブルを作成していない場合は直接CREATE DATABASEしましょう。

migrate create -ext sql -dir ./db/[table name] [migrate operation name]

を実行してファイルを作成し、作成された.sqlファイルにマイグレーションするクエリを追加します。 上のスクリプトを実行してマイグレーションを実行します。

Github Actionsに設定する

今回の話題はこれです。 GitHub Actionsに設定し、mainブランチにpushされかつdb/**が変更された場合に走らせます。

name: Migration

on:
  push:
    branches:
      - main
    paths:
      - './db/**'
  workflow_dispatch:

jobs:
  migrate-db:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      
      - name: Setup Env
        run: |
          echo "CLOUDSQL_INSTANCE_CONNECTION_NAME=${{ secrets.CLOUDSQL_CONNECTION_NAME }}" > .env
          echo "MYSQL_USER=${{ secrets.MYSQL_USER }}" >> .env
          echo "MYSQL_PASSWORD='${{ secrets.MYSQL_PASSWORD }}'" >> .env
          echo '${{ secrets.GCP_SA_KEY }}' > ./config/sa_key.json
      - name: Start Cloud SQL Proxy
        run: |
          docker-compose up -d
      - name: Install migrate
        run: |
          curl -L https://packagecloud.io/golang-migrate/migrate/gpgkey | sudo apt-key add -
          echo "deb https://packagecloud.io/golang-migrate/migrate/ubuntu/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/migrate.list
          sudo apt-get update
          sudo apt-get install -y migrate
      - name: Migrate DB (up)
        run: ./scripts/migrations.sh

Githubで設定するsecretは、

  • CLOUDSQL_CONNECTION_NAME
  • MYSQL_USER
  • MYSQL_PASSWORD
  • GCP_SA_KEY

です。

まとめ

これで開発が楽しくなりそう!

ぼくがかんがえたさいきょうのプログラミング言語べんきょーほうほう

エンジニアは新しいものが好きである*1。そのため、新しいものを使うために新しい言語を習得するということは日常茶飯事である。

このブログでは私が新しくプログラミング言語を勉強する際に実施している勉強法を書く。

TL;DR

  • 公式のドキュメントを眺める
  • 他の言語と比較しその言語独自の使用などを軽くMarkdownでまとめる
  • その言語でGitHubから検索して数個ほどリポジトリをクローンする
  • クローンしたリポジトリを読み仕組みを理解する
  • なにか作る

解説

公式のドキュメントを眺める

プログラミング言語を勉強する上で一番の情報源は、本でもTwitterでもいかがでしたか系サイトでも技術記事でもなく公式ドキュメント*2である。その言語の開発者がどういう意図でそういう設計をしたのかがわかる。
また、公式ドキュメントを先に読むことで技術記事のバージョンの違いで動かない事象を事前に回避することができる。

ドキュメントを眺めるのはとくに面白みはないのでTwitterで実況するのがおすすめである。

他の言語と比較しその言語独自の使用などを軽くMarkdownでまとめる

プログラミング言語にはその言語独自の仕様を持つ場合が多い。例えば、Pythonなどはインデントでブロックを表現したりGoなどはエラーを第二戻り値にしてスローはしない。Rustはセミコロンがない文はreturnになるなど様々である。

そのような仕様は書く場合にこんがらがってしまう場合が多いので後で索引できるようにMarkdownなどにまとめる。あと、少し書くと記憶に残りやすい。残らなくてもそれをまとめたなっていうことを覚えていればあとで検索できるしね。

その言語でGitHubから検索して数個ほどリポジトリをクローンしてリポジトリを読み仕組みを理解する

これは一番大事である。これに9割時間を費やしてもいいかもしれない。

プログラミング言語は、仕様がわかって書けるようになったところでいざ〇〇を作る!とかなるとどうしていいのかわからなくなる事が多い*3。そういう問題に対応するため予めその取得したい言語で書かれたリポジトリを読み仕組みを理解するはめちゃくちゃ効率が良い。

さらに、その言語で使われるパッケージマネージャーや命名規則ディレクトリ構成も一緒に理解できるためおすすめである。

私は実際にRustの勉強をした際には、tokei*4をクローンしてコードを読んだ。このリポジトリは、ビルド時にbuild.rsが実行されlanguages.jsonの内容をテンプレートエンジンで.rsに上書きするという仕組みがありすごく面白かった。

なにか作る

ずっとインプットでは覚えない。そのため、アウトプットをする。なにか目標をたてて、実際にその言語を使用して作ってみる。

まとめ

私の好きな言語は、Go、TypeScript、Rustです!!!!

*1:要検証

*2:ソースコードという人もいる

*3:個人の感想

*4:Rust製のファイル解析ソフト。ディレクトリを再帰的に解析しどの言語が何行存在するかがわかる。

社会人になると学割サブスクが効かなくなるので月にどれくらい増えるか計算してみた

私は今学生です。ちょうど学部4年度で、来年は就職をします。

来年学生じゃなくなるのです。そうするとどんな問題が出てくるのか、

学割の終了です。

今、世の中にはいろいろなサブスクリプションサービスがあります。さらにそのサブスクも学生は申請すると無料だったり割引価格になるのもあります。 ということは、今のまま学生が終了すると月当たりのサブスクによる出費が増えます。 就職していきなり出費が大きくなったらびっくりしてしまうので今のうちにどれくらい出費が多くなるか計算していきたいと思います。

学割サブスクを洗い出す

学割で契約しているサービスを洗い出します。

意外と少なかったです。Amazonプライムにも学割はありますが、なぜか契約してません。理由は謎です。

就職しても契約するもの

  • YouTube Premium
    • 生活必需品です。
  • Adobe CC
    • 迷いましたがなんだかんだ使ってるので契約します。
  • GitHub Pro
    • GitHub大好きなので必須です。

MS Officeは大学のレポートなどはGoogleドキュメントを使用しており元々使っていないため就職したら契約はしないつもりです。

差額を計算する

サブスク名 通常 学割 差額
YouTube Premium 1180円/月 680円/月 500円/月
Adobe CC 6480円/月*1 0円 6480円/月
GitHub Pro $4/月 $0/月 523円/月*2

合計すると、7503円/月サブスク料金があがる。

まとめ

やはりAdobeCC高い。。。しかし、Amazomセールで1年ライセンスを購入するれば半額ぐらいで利用できるためそれも検討していきたい。

あとは、あと数ヶ月の学生生活を堪能したい。

*1:https://www.adobe.com/jp/creativecloud/plans.html より。2022/6/5時点

*2:$1 = 130.84 円の円安時に計算