8tako8tako8’s blog

ソフトウェアエンジニア

スクールに入会して 2 ヶ月経ったので振り返り

Cloud Pratica Advent Calendar 2025 の 6 日目の記事です。

10 月に Cloud Pratica に入会してから 2 ヶ月経ったので振り返りをします。

自己紹介

関西在住のソフトウェアエンジニア 5 年目です。 BtoB SaaS 企業でバックエンドエンジニアをしています。

現在は、ユーザー数が300万人のプロダクトの開発に従事しており、この数年は主にパフォーマンス改善に取り組んでいます。 普段は Ruby と TypeScript を書くことが多く、インフラは Google Cloud で運用しています。

趣味は、格闘技とマラソンです。

Cloud Pratica とは

@engineer_ryoma が運営するインフラ技術に特化したエンジニア向けオンラインスクールです。

【完全解説】Cloud Praticaのカリキュラム - esa-pages.io

入会のきっかけは Kubernetes を学びたかったから

一番の理由は Kubernetes を学びたかったからです。

5 年前、未経験エンジニア時代に所属していた 42Tokyo で、Kubernetes の課題に取り組んだことがありました。当時の自分にとって、Kubernetes を学ぶのはかなり難しく、課題を完了するのに 1 ヶ月半かかり苦労した記憶があります。

当時コミットしたリポジトリを載せておきますが、今見てもほとんど覚えていないです(笑)

https://github.com/8tako8tako8/ft_services

あの時、完全に理解できなかった Kubernetes を学びたいと思い、実践的な課題が豊富にある Cloud Pratica に入会を決めました。

完了したコースの振り返り

2 ヶ月で 2 コースを終えました。あまり時間を取れていなかったので、想定していたより進捗が悪いです。

AWS 基礎コース

AWS 基礎コースでは、VPC、サブネット等のネットワークまわりと、ECS + RDS 構成で簡単なヘルスチェックが通る状態を構築しました。バックエンドは、Go 言語で実装済みのリポジトリを使います。

AWS を触るのは 3 年ぶりでしたが、意外と覚えていたことが多くて安心しました。

基礎コースなので難易度は易しいですが、本番運用でのテクニック等がたくさんあって勉強になりました。

Cloud Pratica の素晴らしい体験として、先駆者が良質な質問をしてくれているので、自分が持っていない観点からも吸収できたことが大きかったです。

AWS 実践コース

AWS 実践コースでは、ユーザーへの通知機能として SES を組み込んだり、EventBridge Scheduler と SQS を組み合わせた非同期のバッチ処理パイプラインを構築しました。さらに、フロントエンドの配信には Amplify や S3、CloudFront を用いました。

EventBridge Scheduler と SQS など、初めて触るサービスを学べたのが楽しかったです。

また、なんとなくでしか使ったことがなかった CloudFront を深ぼって学べたのが一番の収穫でした。CloudFront は奥が深くて、細かい要件に対して実際に運用するには難しそうな印象でした。Lambda@Edge と CloudFront Functions は存在すら知らなかったのですが、細かい要件に対応するのに非常に便利そうでした。

他にも、課題内で実装されているコードのコードリーディングを通して、Go 言語や、シグナル処理を用いて実装されているグレースフルシャットダウンを学びました。

このコースを進めるのは、とにかく楽しかったです。

最後に

ここまでのコースを通して得られるものが多く、既に入会して良かったと満足しています。 次のコースでは、Terraform について学んでいきます。 来年には、Kubernetes の理解が深まっているはず...!

デブサミ2024関西 参加レポート

Developers Summit 2024 KANSAI(2024.09.18)

デブサミには初参加。近所での開催だったので行ってみた。

ノベルティ

5年のアジャイル推進で見つけた、壁の乗り越え方 -現場から変革にチャレンジ-

5年のアジャイル推進で見つけた、壁の乗り越え方 -現場から変革にチャレンジ-

大企業で5年間アジャイル開発を推進してきた話。推進していく上で大事なことは「諦めない」+「無理しない」。JTCでアジャイルを推進するのはやりがいがありそうだけど、ジョブローテーションと開発組織は相性が悪そうに思えた。特に、アジャイルが根付いていない組織において、メンバーの頻繁な入れ換えは、アジャイル定着の障害になりそう。

誰でもできる!OpenAI Embedding APIを活用して、高度なレコメンド機能を実現してみよう

誰でもできる!OpenAI Embedding APIを活用して、高度なレコメンド機能を実現してみよう

OpenAI Embedding APIがレコメンド・類似検索・異常値検出に使える話。簡単に使える・費用安い・パフォーマンス良いとのこと。特に費用に関して値下げによって破格になったみたい。文章をベクトルで表して、ベクトル同士のコサインをとって算出する(コサイン類似度と呼ばれるやつ)。Redisにベクトルキャッシュしておくことで、さらに費用が安くなる。テキストに変換できるものなら、なんでもレコメンドなどできたりで、toCサービスだと結構使い所ありそうだった。

マネジメントor技術は二者択一?「中途半端」なエンジニアの生存戦略

マネジメントor技術は二者択一?「中途半端」なエンジニアの生存戦略

技術とマネジメントの両立についての話。エンジニアキャリア形成に役立ちそうな何かが得られそうだったので聴講。マネジメントor技術は二者択一ではなく、実際にはグラデーションがある。プレイヤー業務もマネージャー業務も欲している環境を選び、どっちもある程度やれる状態を目指すのがオススメみたい。自分がマネージャーに向いているとは思えないけど、機会があったらやってみるのもありかもしれない(身近な誰かもそんなこと言ってた気がする)。このようなエンジニアキャリアの話もっと聞きたい。

デブサミ2024関西コミュニティLT

デブサミ2024関西コミュニティLT

関西を拠点に活動しているコミュニティのLT。セキュリティやサーバレスなど様々な分野のコミュニティがあるのを知れて良かった。ハックバー行ってみたい。

Findy Team+ ドリンクアップ

オフィシャルの懇親会の枠が埋まっていたが、こちらは当日でも参加できたので行ってみた。

初めてましての方ばかりだったけど、たくさんの方と話せて楽しい時間を過ごせた。開発生産性の話はあまりしなかったけど。スタートアップのCTOが多かった印象、すごい。

まとめ

アジャイル推進やAI技術の活用について学び、多くの新しい視点を得ることができた。特に、技術とマネジメントの両立についての話は、今後のキャリアに役立ちそう。関西のコミュニティ活動も興味深く、いつか参加するかも。

大阪Ruby会議04 参加レポート

Rubyistになって1年、初めての地域Ruby会議参加でした

大阪Ruby会議04の名札

5月の RubyKaigi に参加したのもあって、以前よりは発表内容を理解できたはず...!

スポンサーブースを運営しました

会場のキャパに対して来場者は少なめだったかも

Keynote: 最高の構文木の設計 2024年版

Keynote: 最高の構文木の設計 2024年版

抽象構文木の基本がわかりやすく解説されていた。親ノードから子ノード、子ノードから親ノードの両方向から辿るの大変だと思いつつ、普段使ってるLSPなどがやってくれてることを知れてよかった。

dRuby 入門者による あなたの身近にある dRuby 入門

dRuby 入門者による あなたの身近にある dRuby 入門

発表を聞く前は dRuby について全く知らなかったけど、dRuby = distributed(分散) ruby らしい。他のプロセスのオブジェクトのメソッド呼べるの凄い。

RubyKaigi公式スケジュールアプリ開発で得た、Hotwireの使い方

RubyKaigi公式スケジュールアプリ開発で得た、Hotwireの使い方

RubyKaigi で実際に使ったスケジュールアプリの話。Hotwire でモーダル実装するの難しそう。Campfire のモーダルが完全に独立したURLをもたせたページになっていて、なるほどだった。

Re-line 〜 IRB・Reline 複数行編集の裏側

Re-line 〜 IRB・Reline 複数行編集の裏側

普段使っている irb の裏側を少し知れてよかった。複数行編集の話を聞いて、駆け出しエンジニアの頃にやった bash の再実装で、ターミナルの位置移動に苦しめられたのも思い出した。差分レンダリング面白くて興味出てきた。(恥ずかしながら、)私は gets、puts を ゲッツ、プッツと呼んでいたけど、ゲット"エス"、プット"エス" と呼ぶのが一般的っぽい。

Rustで作るTreeSitterパーサーのRubyバインディング

Rustで作るTreeSitterパーサーのRubyバインディング

発表を聞く前は Ruby のカンファレンスで Rust !? な気持ちだったけど、めっちゃ面白かった。Rust 側でメソッド終了時にスタックから消えてしまう問題なるほど。

GCによって何が開放されるのか理解してないと、SEGVに繋がる。

これめっちゃ難しそうだった

競技プログラミングでみる Ruby の豊かさ

競技プログラミングでみる Ruby の豊かさ

短いコードで動くの面白い!

Minify Ruby Code

Minify Ruby Code

ソースコードのサイズを小さくするのに考えること大盛りだった。ヒアドキュメントに対応するのかなりキツそう。

strscanなしで文字列をスキャンする

strscanなしで文字列をスキャンする

strscanを使いたくない理由が「なるべくgemを使いたくない」で、落ちが strscan便利 なの面白かった。

どうしてこうなった?から理解するActive Recordの関連の裏側

どうしてこうなった?から理解するActive Recordの関連の裏側

普段の業務でお世話になってるActive Recordの話で興味深かった。save したときに定義されるコールバックの順序を知って勉強になった。細かい知識だけど、将来役立ちそうな知識だった。

Keynote: 令和の隙間産業——PicoRubyはどこから来て、どこへ行くのか

Keynote: 令和の隙間産業——PicoRubyはどこから来て、どこへ行くのか

PicoRubyのこれまでを聞いて本当に偉業だと感じた。ラズパイピコが発表されたタイミングでモチベーション上げて開発した話良かったし、開発者にとってモチベーションは本当に大事。最近、電子工作に興味を持ち始めていたので、PicoRuby 使って何か作りたい欲出てきた。

まとめ

5月に参加した RubyKaigi のおかげで初見の知識が少なく、理解できた部分が多かった。来年も開催されたら参加したいし、他の地域Ruby会議にも行ってみたくなった。来場はあまり多くなかったので、関西在住の Rubyist はもしかして少ないのかも(増えて欲しい)

activerecord-import を使って Bulk Insert してみる

この記事について

DB アクセスを減らす方法に Bulk Insert があります。この記事では、activerecord-import という gem を使って、Bulk Insert の有無で発行されるクエリがどのように変わるかを調査します。

記事内で使用するコードは以下で公開しています

github.com

記事の注意点

この記事に記載されている SQL クエリは Rails のログから取得したものであり、実際にデータベースに発行される SQL とはプレースホルダ($1, $2 など)やパラメータの形式が異なる場合があります。

単一モデルの場合

Bulk Insert を使わない場合

users = []
2.times do |i|
  users << User.new(name: "User #{i}")
end
users.each(&:save)

発行されるクエリ

INSERT INTO "users" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["name", "User 0"], ["created_at", "2024-06-02 09:59:23.743831"], ["updated_at", "2024-06-02 09:59:23.743831"]]
INSERT INTO "users" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"

登録するデータ分だけINSERTクエリが発行されています

Bulk Insert を使う場合

users = []
2.times do |i|
  users << User.new(name: "User #{i}")
end
User.import users

発行されるクエリ

INSERT INTO "users" ("id","name","created_at","updated_at") VALUES (nextval('public.users_id_seq'),'User 0','2024-06-02 09:59:00.372040','2024-06-02 09:59:00.372040'),(nextval('public.users_id_seq'),'User 1','2024-06-02 09:59:00.372040','2024-06-02 09:59:00.372040') RETURNING "id"

INSERTクエリ1つで複数のデータを登録できました

複数モデルの場合

class Parent < ApplicationRecord
  has_many :children, dependent: :destroy
end

class Child < ApplicationRecord
  belongs_to :parent
end

Bulk Insert を使わない場合

parents = []
2.times do |i|
  parent = Parent.new(name: "Parent #{i}")
  parents << parent
  2.times do |j|
    parent.children << Child.new(name: "Child #{i}-#{j}")
  end
end
parents.each(&:save)

発行されるクエリ

INSERT INTO "parents" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["name", "Parent 0"], ["created_at", "2024-06-02 09:38:18.979115"], ["updated_at", "2024-06-02 09:38:18.979115"]]
INSERT INTO "children" ("name", "parent_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["name", "Child 0-0"], ["parent_id", 4], ["created_at", "2024-06-02 09:38:18.981327"], ["updated_at", "2024-06-02 09:38:18.981327"]]
INSERT INTO "children" ("name", "parent_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["name", "Child 0-1"], ["parent_id", 4], ["created_at", "2024-06-02 09:38:18.982622"], ["updated_at", "2024-06-02 09:38:18.982622"]]
INSERT INTO "parents" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["name", "Parent 1"], ["created_at", "2024-06-02 09:38:18.984042"], ["updated_at", "2024-06-02 09:38:18.984042"]]
INSERT INTO "children" ("name", "parent_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["name", "Child 1-0"], ["parent_id", 5], ["created_at", "2024-06-02 09:38:18.984823"], ["updated_at", "2024-06-02 09:38:18.984823"]]
INSERT INTO "children" ("name", "parent_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["name", "Child 1-1"], ["parent_id", 5], ["created_at", "2024-06-02

複数モデルの場合も同様に、登録するデータ分だけINSERTクエリが発行されています

Bulk Insert を使う場合

関連モデルも Bulk Insert したければ recursive: true をつけます

parents = []
2.times do |i|
  parent = Parent.new(name: "Parent #{i}")
  parents << parent
  2.times do |j|
    parent.children << Child.new(name: "Child #{i}-#{j}")
  end
end
Parent.import parents, recursive: true

発行されるクエリ

INSERT INTO
  "parents" ("id", "name", "created_at", "updated_at")
VALUES
  (
    nextval ('public.parents_id_seq'),
    'Parent 0',
    '2024-06-02 09:57:44.364529',
    '2024-06-02 09:57:44.364529'
  ),
  (
    nextval ('public.parents_id_seq'),
    'Parent 1',
    '2024-06-02 09:57:44.364529',
    '2024-06-02 09:57:44.364529'
  ) RETURNING "id"
INSERT INTO
  "children" (
    "id",
    "name",
    "parent_id",
    "created_at",
    "updated_at"
  )
VALUES
  (
    nextval ('public.children_id_seq'),
    'Child 0-0',
    14,
    '2024-06-02 09:57:44.366677',
    '2024-06-02 09:57:44.366677'
  ),
  (
    nextval ('public.children_id_seq'),
    'Child 0-1',
    14,
    '2024-06-02 09:57:44.366677',
    '2024-06-02 09:57:44.366677'
  ),
  (
    nextval ('public.children_id_seq'),
    'Child 1-0',
    15,
    '2024-06-02 09:57:44.366677',
    '2024-06-02 09:57:44.366677'
  ),
  (
    nextval ('public.children_id_seq'),
    'Child 1-1',
    15,
    '2024-06-02 09:57:44.366677',
    '2024-06-02 09:57:44.366677'
  ) RETURNING "id"

build メソッドを使っても Bulk Insert できます

parents = []
2.times do |i|
  parent = Parent.new(name: "Parent #{i}")
  2.times do |j|
    parent.children.build(name: "Child #{i}-#{j}")
  end
  parents << parent
end
Parent.import parents, recursive: true

発行されるクエリ

INSERT INTO
  "parents" ("id", "name", "created_at", "updated_at")
VALUES
  (
    nextval ('public.parents_id_seq'),
    'Parent 0',
    '2024-06-02 10:07:01.316129',
    '2024-06-02 10:07:01.316129'
  ),
  (
    nextval ('public.parents_id_seq'),
    'Parent 1',
    '2024-06-02 10:07:01.316129',
    '2024-06-02 10:07:01.316129'
  ) RETURNING "id"
INSERT INTO
  "children" (
    "id",
    "name",
    "parent_id",
    "created_at",
    "updated_at"
  )
VALUES
  (
    nextval ('public.children_id_seq'),
    'Child 0-0',
    16,
    '2024-06-02 10:07:01.319007',
    '2024-06-02 10:07:01.319007'
  ),
  (
    nextval ('public.children_id_seq'),
    'Child 0-1',
    16,
    '2024-06-02 10:07:01.319007',
    '2024-06-02 10:07:01.319007'
  ),
  (
    nextval ('public.children_id_seq'),
    'Child 1-0',
    17,
    '2024-06-02 10:07:01.319007',
    '2024-06-02 10:07:01.319007'
  ),
  (
    nextval ('public.children_id_seq'),
    'Child 1-1',
    17,
    '2024-06-02 10:07:01.319007',
    '2024-06-02 10:07:01.319007'
  ) RETURNING "id"

レコード重複の場合

class Token < ApplicationRecord
  validates :name, uniqueness: true
end

レコードが重複する場合に更新したいカラムがあれば、on_duplicate_key_update で指定します

Token.create({ name: 'token 0' })

tokens = []
2.times do |i|
  tokens << Token.new(name: "token #{i}")
end
Token.import tokens, on_duplicate_key_update: { conflict_target: [:name], columns: [:name] }

発行されるクエリ

INSERT INTO
  "tokens" ("id", "name", "created_at", "updated_at")
VALUES
  (
    nextval ('public.tokens_id_seq'),
    'token 0',
    '2024-06-02 13:03:04.221739',
    '2024-06-02 13:03:04.221739'
  ),
  (
    nextval ('public.tokens_id_seq'),
    'token 1',
    '2024-06-02 13:03:04.221739',
    '2024-06-02 13:03:04.221739'
  ) ON CONFLICT (name) DO
UPDATE
SET
  "name" = EXCLUDED."name",
  "updated_at" = EXCLUDED."updated_at" RETURNING "id"

コールバック

activerecord-import を使用する際、通常のActiveRecordコールバック(before_create, after_create, before_save, after_save など)は呼び出されません

これは、activerecord-import が大量のデータを一括で挿入するため、各レコードのインメモリオブジェクトにアクセスできないためです

コールバックを実行したい場合は、手動でコールバックを実行する必要があります

参考: callbacks

バリデーション

デフォルトでバリデーションが行われます。バリデーションをスキップする場合は以下のようにします

Product.import! products, validate: false

まとめ

  • activerecord-import を使用することで、複数のレコードを一度に挿入し、データベースアクセスを減らすことでパフォーマンスを向上させることができる
  • コールバックやバリデーションの動作にも注意する必要

RubyKaigi 初参加してきた

Rubyistになって約1年、RubyKaigi初参加、人生4度目の沖縄でした

RubyKaigi 2024の名札

Day1

Writing Weird Code

Writing Weird Code - RubyKaigi 2024

「Rubyでこんなことまでできるのか!」と興奮しました!ビットマップ画像に実行可能なRubyコードを埋め込むなんて良い意味で変態でした。

The grand strategy of Ruby Parser

The grand strategy of Ruby Parser - RubyKaigi 2024

parser の現状から今後の展望までわかりやすかったです。BNFでパーサーを作ったことがあったので、少し内容理解できました。他のセッションとの関連性も紹介されててよかったです。

Let's use LLMs from Ruby 〜 Refine RBS types using LLM 〜

Let's use LLMs from Ruby 〜 Refine RBS types using LLM 〜 - RubyKaigi 2024

様々なLLMで評価していて、結果を比較するの面白かったです。GPT4-o速くて良き。

Generating a custom SDK for your web service or Rails API

Generating a custom SDK for your web service or Rails API - RubyKaigi 2024

英語のセッションだったので、あまり理解できずでした。

Ractor Enhancements, 2024

Ractor Enhancements, 2024 - RubyKaigi 2024

英語のセッションでしたが、日本人の英語だったので、なんとかついていけました。Ractor とは何かがわかったり、GC によるパフォーマンス悪化についてふむふむしました。

Day2

Leveraging Falcon and Rails for Real-Time Interactivity

Leveraging Falcon and Rails for Real-Time Interactivity - RubyKaigi 2024

英語についていけなくて、(Ractorと比較して)Falconの優位性がよくわからなかったです。ゲーム作りは面白そうだったので、今度やってみます。 https://github.com/socketry/flappy-bird

RuboCop: LSP and Prism

RuboCop: LSP and Prism - RubyKaigi 2024

LSPの仕組みがなんとなくわかりました。入力中にフォーマットされて困るのは「確かに〜」となりました。気持ちのこもった発表で胸が熱くなりました。

Day3

Ruby Committers and the World

Ruby Committers and the World - RubyKaigi 2024

英語で話される & 難しくて、議論されてる内容ほとんどわかりませんでした。でも、議論している様子は面白かったです。RBS 全然詳しくないので、触ってみようと思いました。GVL を取ったら速くなる?みたいな話が面白かったです。GVL をなくすとロックが増えたり Mutex を取ったりが必要になるのは「なるほどな〜」となりました。

Discord で流れてきた以下のコメントも共感できました

  • Ruby コードってロックとか Mutex を取るべきところで使われてないことがたくさんあって、それは GVL があるからスレッドセーフティに対する意識がめっちゃ低いからだとは思ってる
  • GVLがあるから完全な初学者でもスレッド安全性を気にせずrailsを学習し始めたりできるんだと思っているので無くさないほうがよいのでは寄り

YJIT Makes Rails 1.7x Faster

YJIT Makes Rails 1.7x Faster - RubyKaigi 2024

残念ながら英語についていけなかったです><

Make Your Own Regex Engine!

Make Your Own Regex Engine! - RubyKaigi 2024

基礎的なことからわかりやすい説明でした。ソースコード上、パーサーが一番長いコードになってるの笑えました。空ループの話?はよくわからなかったです。博士課程で研究されてるのめっちゃかっこいい。

Matz Keynote

Matz Keynote - RubyKaigi 2024

パフォーマンスが段々と速くなってるの超ありがたいです。色んなパーツが組み合わさって、昔考えていた理想の Ruby に近づいているの感動的でした。次回の松山も楽しそうです。

ブース

ブースのスタンプラリー。全部回れなかった。

頂いたノベルティの一部

SimpleForm さん

架空の登記簿を見て怪しい会社を見つけるクイズが面白かったです。私は全くわからなかったのですが、同僚が見事に正解していて探偵かと思いました。

IVRy さん

電話でレストランを予約する体験ができて面白かったです。どうやって作ってるのか気になりました。

イベント

Findy Drinkup at RubyKaigi 2024 Day 1

楽しかった。 勢いのある大学院生がいて、刺激をもらえました。 終盤にご飯がたくさん出てきてフードファイトが始まりました。

Chura DATA Drinkup at RubyKaigi 2024

外国人の多いテーブルに座って英語で話してみました。 隣に座っていたオーストラリア人の方が、私の拙い英語を理解してくれようと頑張ってくれたので助かりました。 後半、島唄ライブがあって大盛り上がりでした。

RubyKaigi 2024 After Party

DeNAさんがチームで集まってる所にお邪魔しました。 出社・リモートの話題になり、DeNAさんのチームは普段から出社されていて、そのおかげでメンバー同士仲良くなれたみたい。 後半は会場を歩き回って、初対面の人に話しかけてました。

RubyMusicMixin 2024

雰囲気だけ味わってすぐ退散。 クラブに行くの初だったので新鮮でした。

感想

Ruby熱

Ruby コミュニティの盛り上がりを肌で感じました。これまで特定のプログラミング言語への熱意はなかったのですが、Ruby をもっと深く知ろうという気にさせられました。1m以内に Matz がいて興奮しました。

英語力

英語を5年ぶりに話した結果、全然言いたいことが言えなかったです。英語の勉強します...。

交流

前職も含めて他社の人と話す機会がほとんどなかったので新鮮でした。ブースやドリンクアップ等で交流して、魅力的な企業が多かったです(身体が複数あれば参画したいくらい)。技術への関心や、働くモチベーションの向上に繋がりました。

おまけ

タコライス

キングタコス 喜友名店 - 宜野湾市/アジア・エスニック | 食べログ 地元の人オススメのタコライス屋さん。

「タコライス」を注文すると肉とライスのみになるので、野菜やチーズが欲しい場合は「タコライスチーズ野菜」を注文する必要があるとのこと。今回は券売機に写真付きが載っていたのですが、他店舗だと口頭で注文するので気をつけポイントのようです。

キングタコスの券売機

味もボリュームも大満足でした。

キングタコスのタコライスチーズ野菜

タコス

メキシコ (MEXICO) - 宜野湾市/タコス | 食べログ 地元の人オススメのタコス屋さん。

美味しかったです。タコライスを食べた直後だったので、1ピースしか食べられませんでした。(写真の5ピースのうち4ピースは同僚が食べました)

メキシコのタコス

Rails + React アプリを ECS Fargate にデプロイする【8. CloudFront編】

これは何?

React と Rails で実装したWebアプリを AWS 環境にデプロイするまでの備忘録の CloudFront 編です

総集編を読んでいない方は コチラ

本記事でやること

以下のインフラ構成図のように CloudFront を作成します

作成手順

フロントエンドのビルド結果を S3 にアップロードし、CloudFront で配信します

ビルド前にソースコードを書き換えます

ビルドして S3 にアップロードします

> yarn run build
> cd build
> aws s3 cp ./ s3://8tako8tako8-hoge-web/ --recursive

次に、AWSサービス: CloudFront から「ディストリビューションを作成」をクリックします

以下のように設定し「ディストリビューションを作成」をクリックします

次に、AWSサービス: Route 53 から「ホストゾーン」をクリックします

「ホストゾーン名」をクリックします

「レコードを作成」をクリックします

以下のように設定し「レコードの作成」をクリックします

これで、CloudFront の作成・設定完了です

最後に、CORSを設定しておきます

# config/initializers/cors.rb

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'http://localhost:3000', "https://web.example.com"

    # 省略
end

動作確認

登録したドメインでWebアプリが動いていれば構築完了です!

最後に

今回は、 CloudFront の作成・設定しました

これで全て構築完了です! お疲れさまでした!

Rails + React アプリを ECS Fargate にデプロイする【7. ECR・ECS編】

これは何?

React と Rails で実装したWebアプリを AWS 環境にデプロイするまでの備忘録の ECR・ECS 編です

総集編を読んでいない方は コチラ

本記事でやること

以下のインフラ構成図のように ECR・ECS を作成・設定します

作成手順

ECR

AWSサービス: Elastic Container Registry から「リポジトリを作成」をクリックします

プライベート、リポジトリ名: hoge-api-ecs として作成します

リポジトリの詳細から「プッシュコマンドの表示」をクリックします

表示されたコマンドを順に実行します

M1, M2 Mac の場合、2 の build コマンドに --platform linux/amd64を追加します(ビルドするとECSで起動できないことがあるから)

ECS

AWSサービス: Elastic Container Service から「新しいタスク定義の作成」をクリックします

起動タイプ: AWS Fargate、タスクロール: ecsTaskExecutionRole を選択します

ECRに登録したイメージを選択します

パラメータストアで登録したパラメータを ValueFrom で取得し環境変数に設定します

その他の設定はデフォルトとして「作成」をクリックします

次に、「クラスターの作成」をクリックします

その他の設定はデフォルトとして「作成」をクリックします

最後に、「サービスの作成」をクリックします

以下のように設定し、「作成」をクリックします

タスクが 実行中 になればコンテナ起動完了です

これで、ECR・ECS を作成・設定完了です

最後に

今回は、ECR・ECS を作成・設定しました

次は、CloudFront 編 に進みましょう!