OmniAICreator/Qiita-1.07M huggingface dataset:
ストレージのセキュリティについて【管理アクセス/バックアップ編】

https://qiita.com/cruel_summer/items/ffe561ba6266aad06b6e

この前回投稿の続きから。ユーザとしてのアクセスの話をしたので、管理者のアクセスの話にまず触れていく。

## 管理者としてのアクセス

ストレージリソースの監視と管理。ネットワーク内の全てのデバイスに関わっているため、ユーザアクセスよりも悪用された際のダメージはずっと高い。

そのためにとっかかりとしてはネットワークの外から管理プラットフォームへのアクセスを防がなければならない。
適切なセキュリティ機能がきちんと制御されていて、それがストレージリソースの保護に役立つのか。一般的に利用されている管理者としてのネットワーク接続手法として、SSHやSSL/TLSを利用しているシステムは多い。
ネットワークに入ってからストレージ機器へのアクセス制御も挟み、そこでLDAP認証やActive Directoryなどの機能を統合することでよりセキュリティを強固にできる。

また不正なアクセスを特定するための手段としてイベントログを吐かせる、というのも有効だ。ただそのログをストレージシステム内に置いてしまうと不正アクセスされた際にそれらのログごと消去されてしまうため、別の場所に設置することが望ましい。ログ用サーバを新たに設置したり別のセキュリティ対策を講じているクラウドストレージへの保存を考えたりと、様々な選択肢がある。

強力な最終権限を一人の管理者に集約させないことも大事だ。ロールベースのアクセス制御を用いて様々な管理機能を割り当てることの方がメリットは大きい。

最後にデバイスの制限という手法もある。ルーターやスイッチの機能で特定のホストからのアクセスでないと弾く、という制御を行なうだけでも脅威が小さくなる。
どのホストにどのストレージ機器や領域への管理アクセスを許可するか。アクセスの限定だけでなく、実行コマンドの制御も行なえるためストレージ内のデータ消去さえも防ぐことができる。

ネットワーク内の機器間の通信監理、管理データをどのように保護して侵入させないか、ネットワークや機器の可用性なども踏まえて、管理者アクセスのセキュリティに取り組んでいく必要がある。

## バックアップ(レプリケーション、アーカイブ)の保護

本番サイトに置かれているデータはもちろん、バックアップ、もしくはディザスタリカバリ用の別サイトに置いているデータについてもセキュリティ保護を考えなければならない。
なぜならば本番サイトのネットワーク内の侵入は防げても別サイトネットワークへの侵入を許してしまったら大変な脅威にさらされてしまうからだ。

このケースでは不正な侵入者は本番サイトと別サイトへの侵入以外にも、両サイト間でデータ転送のために利用されるディススタリカバリネットワークへの侵入も狙っている。
それを許すとデータ改ざんや各ストレージ機器へのDoS攻撃が仕掛けられる脅威が待ち受けている。

また余談の範疇になるが、テープ装置を使ったバックアップの場合はテープ保管場所のセキュリティも重要になってくる。物理的な侵入対策はもちろんテープ内のデータを暗号化して物理的な盗難の被害後の局面にも考慮していくことが必要だ。

といった感じで、ユーザ・管理者・バックアップと3つのケースによるセキュリティについて触れてきた。
それぞれの話の中で、具体的な手法は極力述べないようにして、あくまで考え方や注意点だけに終始してきたのは、将来的に最適な手段・方法が目まぐるしく変わっていくからだ。

あとはシステムによっても最適手法は変わってくる。抽象的で奥歯にものがはさまったような投稿になったが了承いただけたらと思う。

## ひとりごと

九州が梅雨入りした。関東も6月に入る前後あたりからの梅雨入りになるのだろうか。

学生時代、自宅は最寄駅から徒歩15分以上かかる場所にあったため、降雨時の通学が億劫で仕方なかった。
服は濡れるし、セットした髪型は崩れるし、湿気で汗ばむし。

その時から、いつか住宅を購入する時がきたら駅から近い場所で買おう、と決心した。
もうそろそろ住宅を購入する年齢にさしかかってきた。手元資金の少なさに焦る。もう徒歩で何分とか言ってる場合ではないぞ。
Databricksのテーブルに認定済みマークを設定してみました

## 前提
・利用環境：Databricks

https://www.databricks.com/jp/try-databricks?scid=7018Y000001Fi15QAC&utm_medium=paid+search&utm_source=google&utm_campaign=17377047998&utm_adgroup=138148229998&utm_content=trial&utm_offer=try-databricks&utm_ad=732035937815&utm_term=databricks%20%E3%83%88%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%AB&gad_source=1&gclid=CjwKCAiA8Lu9BhA8EiwAag16b8b3zbkIb3V7gp-8VUwKukXnhtVZRQ-1RY8SbETmGVgNT4bQramYmRoCX5wQAvD_BwE#account

## 操作手順（動画）
<iframe width="560" height="315" src="https://www.youtube.com/embed/vuAdCi_tZdg?si=bJgJmASGuzUnW77U" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
DatabricksのAI生成機能を利用して、コメントを一括生成してみた

## 前提
・利用環境：Databricks

https://www.databricks.com/jp/try-databricks?scid=7018Y000001Fi15QAC&utm_medium=paid+search&utm_source=google&utm_campaign=17377047998&utm_adgroup=138148229998&utm_content=trial&utm_offer=try-databricks&utm_ad=732035937815&utm_term=databricks%20%E3%83%88%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%AB&gad_source=1&gclid=CjwKCAiA8Lu9BhA8EiwAag16b8b3zbkIb3V7gp-8VUwKukXnhtVZRQ-1RY8SbETmGVgNT4bQramYmRoCX5wQAvD_BwE#account

## 参考ドキュメント

https://docs.databricks.com/gcp/ja/comments/ai-comments

## 参考ブログ

https://qiita.com/taka_yayoi/items/2273b99c4b0e480856db

## 操作手順（動画）
<iframe width="560" height="315" src="https://www.youtube.com/embed/13ZjzxLlSSM?si=3K3o7KephfOZtqgY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
DatabricksのGenieに自然言語で指示を追加してみた

## 前提
・利用環境：Databricks

https://www.databricks.com/jp/try-databricks?scid=7018Y000001Fi15QAC&utm_medium=paid+search&utm_source=google&utm_campaign=17377047998&utm_adgroup=138148229998&utm_content=trial&utm_offer=try-databricks&utm_ad=732035937815&utm_term=databricks%20%E3%83%88%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%AB&gad_source=1&gclid=CjwKCAiA8Lu9BhA8EiwAag16b8b3zbkIb3V7gp-8VUwKukXnhtVZRQ-1RY8SbETmGVgNT4bQramYmRoCX5wQAvD_BwE#account

## 参考ドキュメント

https://docs.databricks.com/aws/ja/genie/set-up

## 操作手順（動画）
<iframe width="560" height="315" src="https://www.youtube.com/embed/Dtd4IiA4VAI?si=SHuIn9-IoYvdK02k" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
Databricks Genieスペースのフィードバックラベル機能を試してみた

## 前提
・利用環境：Databricks

https://www.databricks.com/jp/try-databricks?scid=7018Y000001Fi15QAC&utm_medium=paid+search&utm_source=google&utm_campaign=17377047998&utm_adgroup=138148229998&utm_content=trial&utm_offer=try-databricks&utm_ad=732035937815&utm_term=databricks%20%E3%83%88%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%AB&gad_source=1&gclid=CjwKCAiA8Lu9BhA8EiwAag16b8b3zbkIb3V7gp-8VUwKukXnhtVZRQ-1RY8SbETmGVgNT4bQramYmRoCX5wQAvD_BwE#account

## 参考ドキュメント

https://www.databricks.com/jp/blog/whats-new-aibi-april-2025-roundup

## 操作手順（動画）
<iframe width="560" height="315" src="https://www.youtube.com/embed/1R-vu1UAduU?si=RBKXDb4w1333qt-y" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
Databricks AI/BI Dashboardのテーブル列の固定機能を試してみた

## 前提
・利用環境：Databricks

https://www.databricks.com/jp/try-databricks?scid=7018Y000001Fi15QAC&utm_medium=paid+search&utm_source=google&utm_campaign=17377047998&utm_adgroup=138148229998&utm_content=trial&utm_offer=try-databricks&utm_ad=732035937815&utm_term=databricks%20%E3%83%88%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%AB&gad_source=1&gclid=CjwKCAiA8Lu9BhA8EiwAag16b8b3zbkIb3V7gp-8VUwKukXnhtVZRQ-1RY8SbETmGVgNT4bQramYmRoCX5wQAvD_BwE#account

## 参考ドキュメント

https://www.databricks.com/jp/blog/whats-new-aibi-april-2025-roundup

## 操作手順（動画）
<iframe width="560" height="315" src="https://www.youtube.com/embed/q-A_y2CHBRs?si=Xhl7XQvAjfI2fyGf" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
【TailwindCSS】ボタンにホバーした際のカーソルをpointerにする方法


## v4では`button`の`cursor`は`default`

v4では`button`の`cursor`が`pointer`から`default`に変更されました。
よって、ボタンにホバーした際にカーソルがpointerになりません。

## すべての`button`の`cursor`を`pointer`にする

`global.css`に以下の記述を追加することですべての`button`と`role="button"`の要素（`disabled`を除く）の`cursor`が`pointer`に設定されます。
これにより、ボタンにホバーした際にカーソルがpointerになるようになります。

```css:global.css
@layer base {
  button:not(:disabled),
  [role="button"]:not(:disabled) {
    cursor: pointer;
  }
}
```

## 参考

https://tailwindcss.com/docs/upgrade-guide#buttons-use-the-default-cursor
DatabricksのAI Assistant機能でポイントマップを可視化してみた

## 前提
・利用環境：Databricks

https://www.databricks.com/jp/try-databricks?scid=7018Y000001Fi15QAC&utm_medium=paid+search&utm_source=google&utm_campaign=17377047998&utm_adgroup=138148229998&utm_content=trial&utm_offer=try-databricks&utm_ad=732035937815&utm_term=databricks%20%E3%83%88%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%AB&gad_source=1&gclid=CjwKCAiA8Lu9BhA8EiwAag16b8b3zbkIb3V7gp-8VUwKukXnhtVZRQ-1RY8SbETmGVgNT4bQramYmRoCX5wQAvD_BwE#account

## 参考ドキュメント

https://docs.databricks.com/aws/ja/dashboards/visualizations/types#%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%83%9E%E3%83%83%EF%BF%BD%EF%BF%BD%E3%83%97

## 参考ブログ
https://qiita.com/taka_yayoi/items/7e5358c59e6ffddb223f

## 操作手順（動画）
<iframe width="560" height="315" src="https://www.youtube.com/embed/HK3qsCdpghE?si=EbdSLkLx6r78i75L" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
DatabricksのダッシュボードをPDFでダウンロードしてみた

## 前提
・利用環境：Databricks

https://www.databricks.com/jp/try-databricks?scid=7018Y000001Fi15QAC&utm_medium=paid+search&utm_source=google&utm_campaign=17377047998&utm_adgroup=138148229998&utm_content=trial&utm_offer=try-databricks&utm_ad=732035937815&utm_term=databricks%20%E3%83%88%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%AB&gad_source=1&gclid=CjwKCAiA8Lu9BhA8EiwAag16b8b3zbkIb3V7gp-8VUwKukXnhtVZRQ-1RY8SbETmGVgNT4bQramYmRoCX5wQAvD_BwE#account

## 参考ドキュメント

https://docs.databricks.com/aws/en/dashboards#download-a-published-dashboard

## 操作手順（動画）
<iframe width="560" height="315" src="https://www.youtube.com/embed/Pt9YCCfjnuM?si=nGWgQjEDBLFT9M_v" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
CH221Kを使う際の注意点

## はじめに
　電子工作で電源を選択するとき、USB-PDを使用する人もいるだろう。USB-PDでは部品点数が多くなるという欠点がある一方、大きな電力を取り出せることが魅力である。
 　本記事はUSB PDシンクコントローラとしてCH22xシリーズを使う際に気を付けるべき点を簡単にまとめた。CH22xシリーズの使用を検討している人はぜひ参考にしてほしい。

## CH221Kの良いところ＆仕様
CH221Kは秋月電子で入手可能なUSB-PDシンクコントローラである

https://akizukidenshi.com/catalog/g/g118022/

　他シリーズ（CH224Kなど）と異なりCFGピンにつなぐ抵抗値の値で要求する電圧（電力）を変換するため、基本的に電圧は固定であり、CH224Kのように電気的に電圧を変更することは難しい。
しかしながら、
1\. Exposed Padが無いため手はんだ可能
2\. DATAピンを必要としないため、USB端子は6ピンのものが使用可能（＝手はんだのハードルが低い）
3\. ICが小さいので小型化に貢献
というメリットがある。

仕様はいろいろあるのだが、本記事に関わる内容は以下のよう
<table>
  <caption>Absolute Maximum rating of CH221K</caption>
  <thead>
    <tr>
      <th>ピン名</th> <th>説明</th> <th>Min</th> <th>Max</th> <th>単位</th>
    </tr>
  </thead>
  <tr>
    <td> VDD </td> <td>供給電圧</td> <th>-0.5</th> <th>5.8</th> <th>V</th>
  </tr>
</table>
<table>
  <caption>要求電圧</caption>
  <thead>
    <tr>
      <th>Resistance on CFG to VDD</th> <th>Request-voltage</th>
    </tr>
  </thead>
  <tr>
    <td> 10kΩ </td> <td>5V</th>
  </tr>
  <tr>
    <td> 20kΩ </td> <td>9V</th>
  </tr>
  <tr>
    <td> 47kΩ </td> <td>12V</th>
  </tr>
  <tr>
    <td> 100kΩ </td> <td>15V</th>
  </tr>
  <tr>
    <td> 200kΩ </td> <td>20V</th>
  </tr>
</table>

## CH221Kを使う際の注意点
　今回は要求電圧(VBUS)を20Vとして設計した。以下はその回路図である。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911381/2bfd8702-bdd5-4cbb-8a9a-80a916cab42c.png)
 問題はR1である。
 このR1の両端にかかる電圧を計測すると16.5Vであった。
 では、この抵抗で消費している電力Pはいくらだろうか。
```math
 \begin{align*}
P &= \frac{V^2}{R} \\
  &= \frac{16.5^2}{1000} \\
  &= 272.25\ \mathrm{[mW]}
\end{align*}
```
お気付きだろうか。
1/4Wを超えているのである。
したがって、**許容損失が1/2W以上のものを使用する必要がある。**
> ちなみに1/4Wの抵抗でも一応動作するが、火傷するくらい発熱していたのでやはり1/2W以上のものをオススメする。

私が回路図に「M1k」と書いているのは「ここは必ず金属皮膜抵抗 1kΩ 1/2W のものを使って！」という自分なりの警告である。
![S__228876292.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911381/e171a85a-6a40-466b-ba0b-9a40544463de.jpeg)

#### 抵抗値を変えてみたら良いのでは？
R1に2kΩを付けてみた。5Vしか来なくなった。
よってここは1kΩにしておくのが無難であろう。

## まとめ
#### **VBUSとVDDの間につける抵抗の許容損失には気を付けよう**
今回はCH221Kを参考に記したが、他のCH22xシリーズを使用する際も同様に気を付けるなければならない。おそらく15Vまでは1/4Wタイプでも問題ないが、20Vにする際はぜひ部品選定には細心の注意を払って設計する必要がある。

#### ここまで読んでいただきありがとうございました。
サロゲートキー vs 複合主キー

# 🔑 サロゲートキー vs 複合主キー：実例で解説

## ✅ サロゲートキーとは？

テーブルの主キーとして<b>人工的に付けた意味のないID</b>を使う方法です。

### 🌟 特徴
- 意味を持たないただの連番やUUID
- 他の列の変更に影響されない
- テーブル結合がシンプル

---

### 💡 実例：ユーザーと注文テーブル

```sql
-- usersテーブル（サロゲートキー：id）
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  name VARCHAR(100)
);

-- ordersテーブル（user_idは外部キー）
CREATE TABLE orders (
  id SERIAL PRIMARY KEY,
  user_id INT REFERENCES users(id),
  item VARCHAR(100),
  quantity INT
);
```

- <b>users.id</b> や <b>orders.id</b> がサロゲートキー
- 結合例：

```sql
SELECT o.id, u.name, o.item
FROM orders o
JOIN users u ON o.user_id = u.id;
```

---

## ✅ 複合主キーとは？

<b>複数のカラムの組み合わせ</b>で主キー制約をつける方法。

### 🌟 特徴
- 業務上の意味を持つ組み合わせ（自然キー）
- 冗長だが整合性が高い
- 結合やインデックスがやや複雑に

---

### 💡 実例：ユーザーごとのお気に入り商品

```sql
-- favorite_itemsテーブル（複合主キー）
CREATE TABLE favorite_items (
  user_id INT,
  item_id INT,
  added_at TIMESTAMP,
  PRIMARY KEY (user_id, item_id),
  FOREIGN KEY (user_id) REFERENCES users(id)
);
```

- <b>user_id + item_id</b> のペアが一意
- 同じユーザーが同じ商品を複数回登録できないよう制約

---

## ⚖ 比較まとめ

| 特徴 | サロゲートキー | 複合主キー |
|------|----------------|-------------|
| 主キーの意味 | <b>意味なし（人工的）</b> | <b>意味あり（業務ロジック）</b> |
| 可読性 | 低い | 高い（内容がわかる） |
| 柔軟性 | 高い（設計変更に強い） | 低い（構造変更に弱い） |
| 結合の簡易さ | シンプル | 複雑になりがち |
| 制約の厳格さ | 緩い | 厳密（自然キーの一意性を守れる） |

---
ChatGPTで鍛えるTOEIC L&R【練習問題生成法】

# 要旨
TOEIC L&Rを毎日コツコツ勉強したい人向けに，各大問1つずつチョイスしてミニテストにするプロンプトを紹介します．
（紹介するまでもなくみんなやってる気がするけど）

# プロンプト
## リスニングセクション
```
TOEIC L&R 990点取得を目指す人向けに，各問題カテゴリから1問ずつ練習問題を作って．回答は掲載しないこと．
まずはリスニングをお願い．生成してくれた文章をそのまま読み上げさせるので，そのつもりで生成して
Part 1の写真説明問題は写真が無いとできないのでスキップしてよい．その代わりにPart 2を2問生成すること．
Part 3と4の回答選択肢は全体の末尾に掲載すること．
```

## リーディングセクション
```
TOEIC L&R 990点取得を目指す人向けに，各問題カテゴリから1問ずつ練習問題を作って．回答は掲載しないこと．
リーディングセクションをお願い．
```
::: note warn
**未解決課題**
- 空所がどこかわかりにくい（UIがmdの記法と空所記号を混同しちゃうみたい）
- 空所補充のところが，空所が埋められた状態で出題されちゃう
:::

# 注意事項
生成される文章に関し，著作権等のリスクを慎重に考慮する必要があります．
サポート期限　検索ハブ

私自身が関係しているシステムのハブです。随時追記予定


Microsoft

https://learn.microsoft.com/ja-jp/lifecycle/products/

RedHat

https://access.redhat.com/ja/support/policy/updates/errata?extIdCarryOver=true&sc_cid=701f2000001OH7EAAW
Supabaseで取得したデータの表示順序を保持する方法


# はじめに
学習記録の一覧テーブルのデータを更新した際、更新したデータがテーブル一覧の最後に表示されてしまうという現象が発生しました。

そこで今回は、データの順番を変更せずに更新できるようにする方法について紹介します。


![データ更新ソート問題.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675924/b60ba430-0e2f-4675-8fbf-f2404d75d5d8.gif)



```:データ構造
export class Record {
    constructor(
        public id: number,
        public title: string,
        public time: number,
        public created_at: string 
    ) {}
}
```


``` study-record.ts
//データ取得
export async function GetAllRecords(): Promise<Record[]> {
    const response = await supabase.from("study-record").select("*")

    if (response.error) {
        throw new Error(response.error.message)
    }
    const recordsData = response.data.map((record) => {
        return new Record(record.id,record.title,record.time,record.created_at)
    })
    return recordsData
}


```

# 解決法
データ取得時にソート条件を指定することで、順番を保ったまま表示できました。
以下のように、created_at（作成日時）で昇順に並べるように .order() を追加しました。
```
//データ取得
export async function GetAllRecords(): Promise<Record[]> {
    const response = await supabase
                        .from("study-record")
                        .select("*")
                        // 作成日時の古い順にする
                        .order("created_at", { ascending: true})

    if (response.error) {
        throw new Error(response.error.message)
    }
    const recordsData = response.data.map((record) => {
        return new Record(record.id,record.title,record.time,record.created_at)
    })
    return recordsData
}
```
.order("created_at", { ascending: true}) の部分が重要で、これによりcreated_atフィールドの値で古い順（昇順）にソートしています。


# おわりに
今回は、データを更新した際に順番が変わってしまう問題に対して、ソート処理を追加することで解決する方法を学びました。
Supabaseでは、.order() を使うことで簡単に並び順を制御できることがわかり、Supabaseに対する理解が深まりました。

# 参考
https://shimotsu.hatenablog.com/entry/2022/02/02/140145

https://supabase.com/docs/reference/javascript/order
プログラムでのテストケース作成のベストプラクティス：UT/単体テスト効率化ガイド

<h2>導入（読者の共感・問題提起）</h2>
<p>プログラム開発の中で<strong>UT（Unit Test）</strong>や<strong>単体テスト</strong>は品質担保の要ですが、多くのエンジニアは「どうやってテストケースを設計すればよいのか」「テスト項目が抜け漏れていないか」などの悩みを抱えています。本記事では、テストケース作成に悩むエンジニア向けに、効率的かつ実践的な作り方のコツと注意点を解説します。</p>

<h3>背景や技術の概要（公式情報や社会背景）</h3>
<p>近年、アジャイル開発や継続的インテグレーション（CI）において、早期にバグを検出する<strong>テスト自動化</strong>の重要性が高まっています。JUnitやpytest、TestNGといったテストフレームワークが成熟し、CIツール（Jenkins, GitHub Actions）との連携も一般化。公式ドキュメントでは、テストピラミッドの適用やテストカバレッジの計測、Mock/Stubの利用方法が詳細に解説されていますが、実務では環境構築やテストデータ整備にギャップが生じやすいのが現状です。</p>

<h3>具体的な課題・エラー</h3>
<p>テストケースを作成する際にしばしば遭遇する問題例：</p>
<ul>
  <li><strong>網羅性不足</strong>：境界値や例外フローを見落とし、想定外の不具合が残る</li>
  <li><span style="color:red;">テストデータ管理の煩雑化</span>：ハードコーディングされたデータが多く、保守性が低い</li>
  <li>Mock設定ミスによる<span style="color:red;">フレークテスト</span>（不安定なテスト）が増加</li>
  <li>CIパイプラインでのテスト実行時間が長く、フィードバックループが遅延</li>
  <li>テストケースの重複や冗長性でテストコードが肥大化</li>
</ul>

<h3>解決策とコード例</h3>
<p>以下ではJava（JUnit5）とPython（pytest）のサンプルを示し、テストケース設計の基本パターンを解説します。</p>

<pre><code>// Java: JUnit5 の例
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {
    Calculator calc;

    @BeforeEach
    void setup() {
        calc = new Calculator();
    }

    @Test
    void testAdd_Normal() {
        assertEquals(4, calc.add(2, 2));
    }

    @Test
    void testAdd_Boundary() {
        assertEquals(Integer.MAX_VALUE,
            calc.add(Integer.MAX_VALUE - 1, 1));
    }

    @Test
    void testDivide_Exception() {
        assertThrows(ArithmeticException.class, () -> calc.divide(10, 0));
    }
}
</code></pre>

<pre><code># Python: pytest と parameterize
import pytest
from calculator import Calculator

@pytest.mark.parametrize("a,b,expected", [
    (2, 3, 5),
    (-1, 1, 0),
    (0, 0, 0),
])
def test_add(a, b, expected):
    assert Calculator().add(a, b) == expected

def test_divide_exception():
    with pytest.raises(ZeroDivisionError):
        Calculator().divide(1, 0)
</code></pre>

<p>ポイント：</p>
<ul>
  <li>テストメソッド名や@parametrizeの引数名で<strong>テスト条件を明確化</strong></li>
  <li>境界値・異常値を網羅し、例外発生を必ず確認</li>
  <li>モックライブラリ（Mockito, pytest-mock）で<strong>外部依存</strong>を切り分ける</li>
</ul>

<h3>ベストプラクティス・運用上の注意</h3>
<ul>
  <li><strong>テストピラミッド</strong>を意識し、UT（Unit Test）を多数用意して統合テストの負荷を軽減</li>
  <li>テストデータはFactory PatternやFixtureで再利用可能にし、<span style="color:red;">ハードコーディング</span>を避ける</li>
  <li>テストコードにもコードレビューを実施し、命名規則やドキュメント整備を徹底</li>
  <li>CI/CD設定で<span style="color:red;">並列実行</span>やキャッシュを活用し、テスト実行時間を最適化</li>
  <li>カバレッジ目標に固執せず、<strong>重要なロジックに対する実効性のあるテスト</strong>を優先</li>
  <li>テスト結果はダッシュボード化し、リーグレッションやテスト失敗傾向を可視化</li>
</ul>

<h3>まとめと今後の展望</h3>
<p>本記事では、<strong>プログラム</strong>での<strong>テストケース</strong>作成に関するコツと注意点を解説しました。効率的なテストケース設計は、開発スピードと品質を両立させる鍵です。今後はAIによるテストケース自動生成やMutation Testing、BDD（Behavior Driven Development）との連携が進み、さらにテスト戦略が高度化すると予想されます。まずは本記事で紹介したベストプラクティスを導入し、信頼性の高いUT/単体テストを実現しましょう。</p>
テーブル定義書管理方法（Excel vs スプレッドシート vs Notion vs マークダウン）

# はじめに
テーブル定義書の管理方法について比較検討してみたのでまとめました。
個人開発〜小規模プロジェクトで管理する場合を想定しています。

これが正解！というよりも、
それぞれの長所短所を理解して自分に合ったものを使うのが良いと思っております。
今回の記事では、その足がかりになればなと思います。

# 比較表

|  | Excel | スプレッドシート | Notion | マークダウン |
| ---- | ---- | ---- | ---- | ---- |
| 共有 | △ | ◎ | ◎ | × |
| 差分比較 | △ | ○ | △ | ◎ |
| 印刷 | ◎ | ○ | ○ | ○ |
| 項目選択（プルダウン） | ○ | ○ | ○ | × |
| 関数の有無 | ○ | ○ | × | × |

## 共有
|  | Excel | スプレッドシート | Notion | マークダウン |
| ---- | ---- | ---- | ---- | ---- |
| 共有 | △ | ◎ | ◎ | × |

クラウド上で管理している `スプレッドシート` と `Notion` がやや優勢。
`Excel` は共有ブックの存在があるので、×ではありませんが、共有フォルダに入れておかないといけなかったり、共有ブック慣れしていないメンバーがいると、ローカルにコピー→上書きされるという悲しい事故も。
`マークダウン` は特に機能を持っていないので共有×にしていますが、gitなどのバージョン管理ツールを用いる前提であれば、デメリットではありません。
むしろ、gitで一元管理できるということはメリットになり得ますかね。（`Excel` も同じく）

## 差分比較

|  | Excel | スプレッドシート | Notion | マークダウン |
| ---- | ---- | ---- | ---- | ---- |
| 差分比較 | △ | ○ | △ | ◎ |

比較の面では、テキストベースの `マークダウン` が圧倒的優勢ですね。
`スプレッドシート` も見やすい部類だと思います。
`Excel` は比較ツールの導入が必要なので、△にしました。
`Notion` は有料版であったり、やや見にくい気がしますが、慣れの問題でしょうか。

## 印刷
|  | Excel | スプレッドシート | Notion | マークダウン |
| ---- | ---- | ---- | ---- | ---- |
| 印刷 | ◎ | ○ | ○ | ○ |

`Excel` はやはり強いですね。ヘッダーフッターに色々入れられたり、柔軟に調整可能です。
紙文化が残っているのであれば、`Excel` はまだまだ強いと思います。
他はPDF出力→印刷で可能です。柔軟性はあまりありません。

## 項目選択（プルダウン）

|  | Excel | スプレッドシート | Notion | マークダウン |
| ---- | ---- | ---- | ---- | ---- |
| 項目選択（プルダウン） | ○ | ○ | ○ | × |

`Excel` `スプレッドシート` `Notion` にはあります。
どれも色を変えられたり、目立つようにできます。
`Excel` `スプレッドシート` は範囲指定できるので、追加したいときも簡単です。
`Notion` はその点、やや不利ですかね。
`マークダウン` はテキストベースなので、そういった機能はなく、データ型を定義するときは、コピペか直打ちになります。

## 関数の有無

|  | Excel | スプレッドシート | Notion | マークダウン |
| ---- | ---- | ---- | ---- | ---- |
| 関数の有無 | ○ | ○ | × | × |

ここは個人的にかなり大きいのですが、migration文などを生成するのに、関数がとても便利です。（DBファーストであれば、Create文やAlter文も）
ですので、私個人としてはこの機能がある `Excel` `スプレッドシート` の2択になります。
テーブル定義書から作成するようにすると、定義書が更新されていないということもなくなりますから、メリットが大きいと思っています。

# 結局自分に向いているのはどれ？

## Excelが向いている人
- 印刷をしなければならない
- 管理者がプログラマというよりマネジメント寄りのタイプ
- マクロなどの資産がある
- gitで管理したい

## スプレッドシートが向いている人
- 複数のデバイスから簡単に確認したい
- Excelに慣れているけど、Excelから脱出したい人
- 関数やGASを使いたい
- テーブル数が比較的少ない
    - 多い場合は、表紙とかにリンク貼るなどの対応をすると便利。Excelも同様

## Notionが向いている人
- Notionに慣れている
- ドキュメントを一元管理したい
- 新しいサービスを使ってみたい

## マークダウンが向いている人
- テキストベースこそ至高の人
- PlantUMLなどでER図作りたい
- gitで管理したい、比較も楽に見たい

ちなみに、マークダウン好きであれば、asciiDocもおすすめです。
プレーンなマークダウンより、ドキュメントに特化しており、テーマファイルでフォントなども良い感じに設定できます。（個別で設定も可能）

ただし、PDF出力に関して、日本語とアルファベットが入り混じるとやや謎のスペースが生まれてしまう問題があります。（2025年時点）

# 比較してみて個人的な話

私は今回、スプレッドシートを選択しました。
- 関数が便利
- 個人開発でテーブル数はそこまで多くない
- 他人と共有しない
- 複数のデバイスで確認したい

スプレッドシートで作成したテーブル定義書は以下のような感じです。
テーブル一覧や、各テーブル定義のところで、migrationのartisanコマンドや、migration内に記述するコードを生成しています。

※PHP Laravelです。

- テーブル一覧
![スクリーンショット 2025-05-19 19.26.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4050763/c8e00b49-ff34-4eba-938b-0d5bec1f5d32.png)

- テーブル定義
![スクリーンショット 2025-05-19 20.42.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4050763/452d02a9-c6df-48d7-ad4b-7ede05780554.png)


小数点がある場合は、精度も必要になりますが、今回は特に予定がないので作っていません。
製造していくうちに必要なものが増えたら更新していきます。

# おわりに
Excelオンラインは使ったことがないので、今回は比較対象外とさせてください。
外部データ投入は、マークダウンを除きすべて可能なので、色々試してみても良いかもしれませんね。

ここまでお読みいただきありがとうございます。
USBデザリングでVPN接続

Windows10のコントロールパネルでVPNの設定をしておきます。

USBデザリングすると下記のアイコンが出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/d2387175-33e6-4670-a7bb-8c71d2b85564.png)

これをクリックするとメニューの上の方にVPNのエントリーがあり接続・切断ができます。

WIFI接続だとアイコンが違いますが、同じようにメニューに表示されます。

rasphone.exeのショートカットを作って接続ダイアログを出す方法もあるようですが、上記のメニューで十分だと思います。
OCR

画像からテキストへのコンバーター オンライン OCR
https://www.onlineocr.net/ja/#google_vignette
Passwordを設定しているファイルは変換できない。
ERROR: Password protected

無料オンラインOCRツール
https://lightpdf.com/jp/ocr
３ファイルまで無料。

https://www.i2ocr.com/free-online-english-ocr
有料　14 day limited access ¥350

https://pdfguru.com/app/ja/choose-plan
7 日間の限定アクセス 150円

https://aws.amazon.com/jp/pm/textract/
3 か月間の無料トライアル
Detect Document Text API: 1,000 ページ/月

https://thebestpdf.com/ja/
7 日間の基本アクセス 一時的に利用したい方向け 150 円

https://ezocr.net/
10 pages/24 hours


https://acrobat.adobe.com/link/acrobat/ocr-pdf?x_api_client_id=adobe_com&x_api_client_location=ocr_pdf
Acrobat購入


https://tools.pdf24.org/en/ocr-pdf
PDF contains an encryption dictionary, please remove it with setAllSecurityToBeRemoved() or set a protection policy with protect()
【Nuxt3】loading=”lazy”を使用するとplaywrightのVRTテストに失敗する

## 概要

Nuxt3 でウェブサイトのパフォーマンス改善のため、画像に `loading="lazy"` 属性を追加することは一般的です。しかし、これを行うと Playwright を使ったビジュアルリグレッションテスト (VRT) が失敗するという問題に直面することがあります。この記事では、その原因と具体的な解決策について解説します。


## 原因

この問題の**原因**は、Playwright がページのスクリーンショットを撮影するタイミングにあります。`loading="lazy"` が設定された画像は、ビューポートに入るまで読み込みが遅延されます。Playwright がスクリーンショットを撮る際に、これらの画像がまだ読み込まれていない（表示されていない）状態であるため、期待される画像が表示された状態のスクリーンショットと比較すると差分が生じ、テストが失敗します。

## 解決策

この問題を解決するためのアプローチは、**テスト実行時に画像を強制的に読み込ませ、それが完了するまで待機する**ことです。

解決策のポイントは以下です。

*   遅延読み込みを**無効化**する (`loading = 'eager'`)
*   すべての画像の読み込みが**完了するまで待機**する
    *   この判定処理がないと一部のブラウザで失敗する場合がある
*   画像の読み込み処理は**並列処理**で対応する

以下は具体的な Playwright テストコードです。

```typescript
test('VRTテスト', async ({ page }) => {
  // ページ内の遅延読み込み画像を強制的に読み込み、完了を待つ
  await page.evaluate(async () => {
    // loading="lazy" 属性を持つ要素をすべて取得
    const elementsWithLazyLoad = document.querySelectorAll('[loading="lazy"]')
    // Promise を格納する配列
    const elementLoadPromises: Promise<void>[] = []

    // 画像の読み込み処理
    for (const element of Array.from(elementsWithLazyLoad)) {
      // 型チェック
      if (element instanceof HTMLImageElement) {
        // loading="lazy" を "eager" に変更して強制的に読み込みを開始
        element.loading = 'eager'

        // 画像の読み込み完了またはエラー発生を待つPromiseを作成
        elementLoadPromises.push(
          new Promise((resolve) => {
            // 読み込み完了またはエラー発生時のハンドラ
            const handleLoadOrError = () => {
              // イベントリスナーを解除
              element.removeEventListener('load', handleLoadOrError)
              element.removeEventListener('error', handleLoadOrError)

              // 待機Promiseを解決
              resolve()
            }

            // load/error イベントリスナーを追加
            element.addEventListener('load', handleLoadOrError)
            element.addEventListener('error', handleLoadOrError)

            // 既に読み込みが完了している場合は即座にハンドラを実行
            if (element.complete) {
              handleLoadOrError()
            }
          })
        )
      }
    }

    // すべての画像の読み込みPromiseが完了するまで待機
    if (elementLoadPromises.length > 0) {
      await Promise.all(elementLoadPromises)
    }
  })

  // 画像の読み込みが完了した状態でスクリーンショットを撮影し、VRTを実行
  await expect(page).toHaveScreenshot({
    fullPage: true
  })
})
```

## その他の検討事項
Playwright issue ([#19277](https://github.com/microsoft/playwright/issues/19277)) では、画像を読み込ませる方法として「画面をスクロールさせる」方法が議論されているようです。しかし、今回はその方法は採用しませんでした。その理由は、スクロールによって意図しない要素（例: CTAボタン）が表示されてしまい、想定しているスクリーンショットとの間に不要な差分が発生し、テスト結果が不安定になる可能性があるためです。前述の loading="eager" に変更して待機する方法の方が、テスト対象の要素に直接作用し、安定した結果を得やすいと考えられます。
ミスって設定したincusbr0を消したいとき

## 状況

ミスって設定したincusbr0を消したくて
```
sudo incus network delete incusbr0
```
とかしてみたけれど
```
エラー: The network is currently in use
```
って言われて困った

## 解決法

```
sudo incus profile device remove default eth0
sudo incus network delete incusbr0
```

eth0どっから生えてきた？
【AWS学習メモ】Amazon EBS（Elastic Block Store）仕組み・インスタンスストアとの違い・ストレージの種類と共有方法

# はじめに
今回はAWSのEBSについて学習しました。
内容も濃くまとめ上げるのも大変ですが頑張って記載していこうと思います。

Amazon EBS（Elastic Block Store）は、EC2インスタンスに接続できる永続的なブロックストレージサービスです。OSやデータベース、アプリケーションのデータ保存などに適しており、インスタンスを停止してもデータを保持できるのが特徴です。
一方で、EC2には一時的に使える「インスタンスストア」もあり、EBSとは性質が大きく異なります。

## ✅ 1. Amazon EBSとは？
・EC2インスタンスにアタッチ可能なブロックストレージサービス

・ボリューム単位で提供され、OSやDB、ログの保存先として利用

・永続性があるため、インスタンスを停止・再起動してもデータは保持される

・スナップショットを使ってS3にバックアップ可能

・アタッチ/デタッチが可能で、同一AZ内であれば別のインスタンスへ接続可能

## ✅ 2. EBSとインスタンスストアの違い
| 比較項目      | EBS                   | インスタンスストア           |
| --------- | --------------------- | ------------------- |
| 永続性       | **あり（停止してもデータ保持）**    | なし（停止・終了でデータ消失）     |
| パフォーマンス   | 安定、タイプにより異なる          | 高速（ホストに直接接続）        |
| 利用可能タイミング | インスタンスの起動後にアタッチ可能     | インスタンス起動時に割り当て      |
| コスト       | 別途料金発生（従量課金）          | EC2インスタンスタイプに含まれる   |
| バックアップ    | スナップショット（S3）対応        | 不可                  |
| ユースケース    | OS、DB、ログなど永続化したいデータ保存 | 一時ファイル、キャッシュ、バッファなど |

## ✅ 3. ストレージの種類の違い（EBS含む）
| 種類              | 特徴                                     | 代表例        | 主な用途                  |
| --------------- | -------------------------------------- | ---------- | --------------------- |
| **ブロックストレージ**   | データをブロック単位で保存。OSが直接管理。柔軟で高性能           | Amazon EBS | OS、DB、ログ、アプリのストレージなど  |
| **オブジェクトストレージ** | メタデータとユニークID付きのオブジェクト形式で保存、HTTP経由でアクセス | Amazon S3  | バックアップ、画像・動画、静的ファイル   |
| **ファイルストレージ**   | ディレクトリ構造で管理。複数インスタンスから同時アクセス可能         | Amazon EFS | ファイル共有、Webサーバーの共有領域など |

## ✅ 4. EBSボリュームのタイプと特徴
| タイプ                   | ストレージ種類       | 用途                 | 特徴                    |
| --------------------- | ------------- | ------------------ | --------------------- |
| gp3                   | 汎用SSD         | 一般的な用途             | IOPSとスループットのカスタム可能    |
| io2/io2 Block Express | 高性能SSD        | 大規模DB、重要なトランザクション系 | 高可用性・高IOPS・99.999%耐久性 |
| st1                   | HDD（スループット重視） | ビッグデータ、ログ処理        | 大容量、スループット重視          |
| sc1                   | HDD（低コスト）     | アクセス頻度が少ないデータ      | 最安、低パフォーマンス           |

## ✅ 5. EBSの仮想化技術（Xen/Nitro）
| 仮想化方式     | 特徴                                                    |
| --------- | ----------------------------------------------------- |
| **Xen**   | 従来型。ハイパーバイザー型仮想化。EBSアクセスは**ハイパーバイザー経由**               |
| **Nitro** | AWS独自の高速仮想化。ハードウェア支援で**EBSを直接I/O**できるため高速でオーバーヘッドが少ない |

## ✅ 6. EBSボリュームの共有方法

❗EBSは基本的に1つのインスタンスにしかアタッチできない

| 方法             | 説明                                      |
| -------------- | --------------------------------------- |
| **Amazon EFS** | ファイルストレージ。NFS経由で複数インスタンスと共有可能           |
| **NFSサーバー構築**  | EBSをアタッチしたEC2をNFSサーバーにし、他のEC2からマウントして共有 |

## ✅ 7. その他の重要ポイント
・スナップショットから新しいEBSを作成して別のAZでも利用可能

・EBSの料金はプロビジョンドサイズとスナップショット保存量に応じて従量課金

・IOPSやスループットを増やすにはボリュームタイプ選択とパフォーマンスチューニングが必要

## 📝 まとめ
・EBSは永続ストレージであり、EC2インスタンスの主要なディスクとして使われる

・用途やパフォーマンス要件に応じてタイプを選択することが重要

・EBSは単一アタッチの原則があるため、共有にはEFSやNFSを使う

・Nitroなどの仮想化技術の進化により、EBSのI/O性能は大きく改善されている
僕はなぜ技術の深掘りをしてしまうのか？

## はじめに

僕はとにかく、どんなことに対してもこう思ってしまう。

- 「なぜこうなるんだろう？」
- 「どうしたらこうできるんだろう？」

気づけばいつも、「仕組み」や「背景」を探ってしまう自分がいる。

それはただの知的好奇心ではなく、もっと根源的な衝動だと思う。  
なぜ、僕は探究してしまうのか？  
その原点を、いま改めて見つめ直してみたい。

---

## 泥団子をひたすらピカピカにする保育園児

保育園の記憶の中で、いちばん鮮明なのは「泥団子を磨いていた時間」だ。

砂が細かければ細かいほど、泥団子はピカピカになる。  
そのことを身体で覚えた僕は、手当たり次第サラサラな砂を探していた。

なぜサラサラを探すのか？  
それは「もっとピカピカにできるかもしれない」から。  
もっと言えば、自分がまだ見たことのない「究極のピカピカ」を見たいから。

このときから僕は、  
*「よりよく整えること」への欲求
*「その先にある未知の美しさへの探究心」
を持っていたんだと思う。

---

## 整えたい。それがすべての起点

気づけば僕は、こんなことにも夢中になっていた。

- コピーライターとして、情報や言葉を整えたら結果が出た  
- 食事法を調べ、縄文時代の食にたどり着いた  
- 瞑想をすると思考がクリアになるのが心地よかった  

物、言葉、情報、身体、思考
どんな対象であっても、僕は「よりよく整えたい」という衝動を抑えられない。

---

## 人と違うことにワクワクする

僕は、人と違うこと、まだ価値として認識されていないことに対して、強く惹かれる。

- みんなが英語を学ぶなら、中国語を学ぶ。  
- 中国がネガティブに語られるなら、自分の目で見に行く。  

****

なぜなら、そこにはまだ整えられていない価値が眠っているから。  
それを整えることで、誰かの役に立つかもしれない。

いや、仮に誰の役にも立たなくてもいい。  
僕はきっと、ただ整えたいから整えている。

でも、それが価値となり、誰かの助けになるなら、それほど嬉しいことはない。

---

## おわりに

僕は、見えないものをカタチにすることにワクワクする。  
技術の深掘りも、言葉の選び直しも、食や習慣の最適化も、すべては「整えたい」から始まっているように思える。

だから、これからも僕は整え続けるだろう。

> 夢中になれることを、夢中でやっていたら、  
> それが誰かの役に立っていた。  
> そんな働き方ができたら、どれだけ幸せか

自分の可能性に、ワクワクする。 
夢中になれることを、仕事にしていきたい。
Gitの用語復習

# はじめに
お久しぶりです。オガネソンです。今年の4月に就職いたしまして、先日Gitを使ったソフトウェア管理についての研修がありました。その復習として、用語を覚えている範囲で書き出していきます。

# Gitとは？
まずはGitとは何かについて説明します。

![v](https://www.creationline.com/tech-blog/cms_x3GWkuX/wp-content/uploads/2023/09/Git-logo-1024x576.png)

Git（ギット）は、**ソフトウェアをいつ、誰が、どのように更新したのかを管理することができるツールの一つ**で、自分の環境で更新したものを共有し合うことから<font color=red>分散型バージョン管理</font>ツールとも呼ばれます。

## どのように管理するの？
Gitの管理方法について説明します。

Gitは<font color=red>リポジトリ</font>を一人、または複数人で共有することができる**分散型バージョン管理ツール**です。

リポジトリとは、**ソフトウェアの変更、更新履歴が登録されているデータベース**のことです。ユーザは、Gitのリポジトリに<font color=red>コミット</font>することで変更履歴を更新していきます。コミットのコマンドは
```bash
git commit -m "コミットメッセージ"
```
です。

また、コミットの前に<font color=red>ステージング</font>します。ステージングとは、ファイルの変更があった際にファイルの状態を一旦固定しておくことを言います。コマンドは
```bash
git add  コミットしたいファイルまたはディレクトリ
```
で行います。

コミットした変更はそのままではgitに反映されません。反映させるには<font color=red>プッシュ</font>という操作が必要になります。プッシュのコマンドは
```bash
git push リモートユーザ名 ブランチ名
```
です。

## ブランチとは？
ここでは<font color=red>ブランチ</font>という重要な概念について説明します。

ブランチとは、**並行開発を可能にする枝分かれのこと**を言います。

![e](https://backlog.com/ja/git-tutorial/assets/img/stepup/stepup1_1.png)
出典：サル先生のGit入門

上の図のように、本来完成させたい環境を<font color=green>緑のブランチ</font>で置いたとき、複数人で別々の機能を追加したり、修正したりする時に本番環境が壊れてしまってはイヤですよね。

そんな時に<font color=blue>青のブランチ</font>や<font color=purple>紫のブランチ</font>に分けておくと、エラーが見つかった時に、本番環境にすぐ戻せます。

このようにしてバラバラに開発した機能を統合するのが<font color=red>マージ</font>です。マージの際、同じ箇所に違う変更が加えられている場合は<font color=red>競合（コンフリクト）</font>が発生します。

コンフリクトは手動でどちらの変更に合わせるか決めないといけません。

最後にコマンドの紹介です。

### ブランチを分けるコマンド
```bash
git checkout -b ブランチ名
または
git switch ブランチ名
```

### マージするコマンド
```bash
git merge 変更したブランチ名
```

## Gitからコードをもらう
Gitはソースコードを共有できるので、他人のコードを自分の環境に移植して、開発することもできます。それを<font color=red>クローン</font>と言います。クローンするコマンドは
```bash
git clone リポジトリURL
```

他の人がクローンしたリポジトリを更新した場合、その更新を反映するには<font color=red>プル</font>をします。コマンドは
```bash
git pull　リモートユーザ名 ブランチ名
```
です。

# おわりに
最後までご覧いただきありがとうございます！
【Rails】コンソールで中間テーブルにデータ保存する方法について

# 記事概要
Ruby on Railsの中間テーブルに対して、コンソールでデータ保存する方法についてまとめる

# 前提
- Ruby on Railsでアプリケーションを作成している
- 多対多関係のテーブル及び中間テーブルを作成している

# テーブル設計の確認
[![Image from Gyazo](https://i.gyazo.com/5743da975b2fad4ac0b19413ff3be1d6.png)](https://gyazo.com/5743da975b2fad4ac0b19413ff3be1d6)

# 手順
1. コンソールを起動
1. 下記を実行
    ※`モデル名_ids`というキーを使用すると、中間テーブルにデータ保存される
    ```ruby
    [1] irb(main):001> Tweet.create(text: "桜が咲いてた！", tag_ids: [1, 2])
    ```
1. テーブルにデータが作成される
    [![Image from Gyazo](https://i.gyazo.com/ecbca814cd6e5e76afe8e48292ecf2a2.png)](https://gyazo.com/ecbca814cd6e5e76afe8e48292ecf2a2)

# Ruby on Railsまとめ
https://qiita.com/likapantrip/items/46b43c9d1309b6633f0a

# モデル
https://qiita.com/likapantrip/items/8cd3ac1a970b1764b7ee
【自分用】Dockerによるストレージ占有の解放の仕方



こんな方におすすめ

- volume削除などのコマンドが効かなかった
- Docker Desktop for Windowsを使っている
- ストレージを削減したいが方法が分からない


# 概要

Docker Desktop for Windowsを使っていると、WSL2の仮想ディスク（`ext4.vhdx`）が肥大化し，ストレージを圧迫することがある．

以下の手順で，不要な領域を安全に削除して空き容量を回復できる．


# 1.Docker Desktopを終了

タスクトレイ ^ から
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091890/18f500a7-e8c8-4738-87c5-de83d052ad16.png)

Dockerのアイコンを右クリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091890/ebefd17c-b732-4a79-94fc-7c3783cc2c38.png)

Quit Docker Desktopを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091890/b394edbe-af6d-4299-bffb-fbc7b25ccadd.png)


# 2.WSL2をシャットダウン 

PowerShellを管理者権限で開き、以下のコードを実行する．
<pre> wsl --shutdown </pre>


# 3.ext4.vhdの場所を確認

通常だと以下のパスにいる
<pre> C:\Users\<ユーザー名>\AppData\Local\Docker\wsl\data\ext4.vhdx </pre>

いなければ探して，以下のコードの該当部分はそのパスを指定する

ext4.vhdが10GB以上であれば効果が期待できる


# 4.仮想ディスクを圧縮
PowerShellを管理者で起動
以下のコマンドを実行
<pre> diskpart </pre>
`DISKPART>`と表示されたら以下のコマンドを順に実行
<pre> select vdisk file="C:\Users\<ユーザー>\AppData\Local\Docker\wsl\data\ext4.vhdx" </pre>
<pre> attach vdisk readonly </pre>
<pre> compact vdisk </pre>
<pre> detach vdisk </pre>
<pre> exit </pre>


# 5.Dockerを再起動
圧縮が完了後，Dockerを再起動


以上の手順で不要なストレージを削減できる．
【Ankiアドオン】　Ankiのアドオンが1200ダウンロードを突破しました！

![AnkiFarmTycoonLogo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1773080/00747f04-8ec3-4091-a132-78d52014ad63.png)

こんにちは。今回は私が個人で開発したAnkiアドオン「Anki Farm Tycoon」が、**1200ダウンロード**を突破しました！

Ankiのアドオン開発についての記事はあまりないので、せっかくなので、書いてみることにしました！

## 📦 Anki Farm Tycoonとは？
![AnkiFarmTycoonDemo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1773080/d1f6b4cd-0e98-400e-9279-4814688371d3.gif)


「Anki Farm Tycoon」は、世界中で利用されているフラッシュカードアプリ「Anki」の拡張機能として開発した**牧場経営ゲーム型アドオン**です。

ユーザーは小さな牧場の経営者となり、Ankiのカードに正解することで動物を育て、資源（ミルクや卵など）を得て収益化。それを使って土地を広げたり、従業員を雇ったりしながら、大きな牧場を目指します。

つまり、**学習すればするほど牧場が成長する！**  
学習の成果がゲーム内に反映されるので、継続のモチベーションがグッと高まります。

🎮 アドオンページ：[AnkiWebで公開中](https://ankiweb.net/shared/mine)  
💻 ソースコード：[GitHubリポジトリ](https://github.com/omuomuMG/Anki-Farm-Tycoon)

---

## 🎯 開発の背景

Ankiは語学学習をはじめ、さまざまな知識の定着に最適なツールです。しかし、長期間使っているとどうしても「飽き」や「単調さ」を感じることも。

そんなときふと思ったのが、

> 「学習そのものをもっと楽しくできないか？」  
> 「“義務感”ではなく“楽しさ”で学習が続く仕組みを作りたい！」

ということでした。  
そこで、**ゲーミフィケーション**を取り入れた学習体験を実現すべく、「Anki Farm Tycoon」を開発しました。

---

## 🔧 使用技術と工夫したポイント

AnkiアドオンはPythonとQt（PyQt）ベースで開発することが推奨されています。そのため、本アドオンも以下の技術で構成されています。

- **言語**: Python  
- **UI**: PyQt5（Ankiが提供するアドオン環境に対応）  
- **データ保存**: AnkiのデータベースとJSONによる補助管理  


UIはAnkiのレイアウトに自然に溶け込むよう意識しながらも、「ゲームっぽさ」を感じられるようカスタマイズしました。

---

## 📊 ダウンロード数とユーザーの声

現在、**ダウンロード数は1200を突破**しました！  
特に海外の英語学習者を中心に好評をいただいており、GitHubのIssueやAnkiWebのレビューを通じて多くのフィードバックを頂戴しています。

ユーザーからは以下のような声も届いています：

> *“This add-on made reviewing fun again!”*  
> *“It’s amazing how such a simple idea makes a big difference.”*

---

## 🛠️ 少しだけ技術的な話
「Anki Farm Tycoon」は大きく以下のようなモジュール構成になっています。

- **constants.py**  
  各動物の成長率（`growth_rate`）、生産確率（`production_chance`）、販売価格などの定数を管理。  
- **models/**  
  - `Animal`／`Field`／`Employee` クラス群：  
    - `Animal` は `@dataclass` で定義され、成長度（maturity）や生産タイミングをプロパティで保持。  
    - `Field` はマップ上のセルを表し、動物オブジェクトの配置・解放を担当。  
    - `Employee` は自動売買ロジックを実装し、売上に対して一定比率で給与を差し引く機能を提供。  
- **gui/**  
  - PyQt5ベースのウィンドウ・ウィジェットを定義。  

- **utils/**  
  - JSON の永続化：ユーザー設定やゲーム進捗を `~/AnkiFarmTycoon/config.json` に保存・読込。  
  - AnkiコレクションAPIラッパー：回答イベントをフックし、カードの正誤判定でゲーム内イベントを発火。  

**動作概要**  
1. カードに正解するたび、`models.Animal.grow()` が呼ばれ、定数 `GROWTH_RATE` に従って成熟度を加算。  
2. 一定成熟度（50%以上）で `models.Field.sell_animal()` により収益化。  
3. `utils.Timer` を使った定期チェックで、生産確率に応じてアイテム（卵・ミルクなど）を生成。  
4. GUI上では PyQt のアニメーションを組み合わせ、成長エフェクトやショップ画面のレベルアップ演出を実現。  

詳しいクラス設計やメソッドの挙動はGitHubリポジトリをご覧ください：  
→ https://github.com/omuomuMG/Anki-Farm-Tycoon

---

## 🚀 今後の展望

今後も以下のようなアップデートを予定しています：

- UIの改善（よりポップで可視化重視のデザインへ）  
- 動物や建物の種類の追加  
- 実績システムの導入（例：連続学習ボーナス）  

また、ユーザーの声を第一に考え、**「継続できる学習体験」**をさらに追求していく予定です。

---

## 👋 最後に

学習を「楽しい体験」に変えたい。  
そんな思いで開発した「Anki Farm Tycoon」ですが、思った以上に多くの方に使っていただけて本当に嬉しいです。

Ankiユーザーの皆さん、ぜひ一度試してみてください。  
学習がゲームに、ゲームが習慣に変わるかもしれません！

→ [Anki Farm Tycoonをダウンロードする](https://ankiweb.net/shared/mine)
→ [GitHubリポジトリ⭐️](https://github.com/omuomuMG/Anki-Farm-Tycoon)

---

ご質問・改善提案などあればお気軽にGitHubでIssueやPRをお寄せください！
Rails学習メモ（初学者向け）②


# Rails学習メモ（初学者向け）

どうも、nus4です。

Rails講座の学習メモ2回目です。
複雑な内容になってくるのを感じていますが、
そういうときこそ、この学習メモ（アウトプット）が理解に役立っています。

お付き合いいただけますと幸いです。

## 学習方法

- Progate Ruby on Rails5コース
　（Ruby学習に引き続き、愛用させてもらってます！）


## 📝 目次

- [Viewファイル(HTMLファイル)内の変数の書き方](#viewファイルhtmlファイル内の変数の書き方)  
- [Viewファイル(HTMLファイル)内の配列の書き方](#viewファイルhtmlファイル内の配列の書き方)  
- [アクション内での変数の定義](#アクション内での変数の定義)  
- [テーブル（マイグレーションファイル、モデルファイル）の作成](#テーブルマイグレーションファイルモデルファイルの作成)  
- [Rails環境でRubyコンソールを起動](#rails環境でrubyコンソールを起動)  
- [テーブルにデータ（レコード）を保存](#テーブルにデータレコードを保存)  
- [テーブルからデータを取り出し（Railsコンソール）](#テーブルからデータを取り出しrailsコンソール)  
- [テーブルからデータを取り出し（アクション）](#テーブルからデータを取り出しアクション)  
- [共通のレイアウトをまとめる](#共通のレイアウトをまとめる)  
- [HTMLにリンクを追加](#htmlにリンクを追加)


## Viewファイル(HTMLファイル)内の変数の書き方
```erb
# 変数の定義
<% 変数名 = "値" %>

# 変数の表示
<%= 変数名 %>
```

## Viewファイル(HTMLファイル)内の配列の書き方
```erb
# 配列の定義
<%
    配列名 = [
        値1,
        値2
    ]
%>

# 配列の表示（each do）
<% 配列名.each do |変数名| %>
    <%= 変数名 %>
<% end %>
```
each doのはじめと終わりは表示用ではないので「<%= %>」ではなく「<% %>」で囲むことに注意。

## アクション内での変数の定義
```ruby
def アクション名
    @変数名 = 値
end
```
ビュー内で宣言することもできますが、なるべくアクション内で宣言するようにしましょう。
変数名を「@」から始めることでビューファイルでも使用することができますので、つけ忘れないように注意しましょう。

## テーブル（マイグレーションファイル、モデルファイル）の作成
```bash
# ターミナルコマンド
$ rails g model モデル名 カラム名:データ型
$ rails db:migrate

# 作成されるファイル
# db/
# └── migrate/
#     └── YYYYMMDDhhmmss_create_データベース名.rb      # マイグレーションファイル
#
# app/
# └── models/
#     └── モデル名.rb      # モデルファイル

```
マイグレーションファイルとは、データベースに変更を指示するファイルです。
データベース名は基本的に複数形で命名されるので、モデル名はデータベース名の単数形にします。（頭文字は大文字）

モデルファイルとは、テーブルを操作するファイルです。
ApplicationRecordクラスを自動的に継承しており、それにより、様々なデータベースに関するメソッドが使えます。

2行目のdb:migrateコマンドでマイグレーションファイルをデータベースに反映（作成）させます。
*テーブル作成時は指定したカラム以外にid, created_at, updated_atという3つのカラムも自動で作成されます。*

「rails g」の「g」は「generate」の略称です。
略さず書いても問題なく動作します。

## Rails環境でRubyコンソールを起動
```bash
# ターミナルコマンド
# コンソールの起動
rails console

# コンソールの終了
quit
```

## テーブルにデータ（レコード）を保存
```ruby
# rubyコンソールを起動した状態で
# ①newメソッドでモデルクラスのインスタンスを作成
インスタンス名 = モデル名.new(カラム名: "値")

# ②インスタンスをテーブルに保存
インスタンス名.save
```
.saveメソッドはモデルクラスの継承元であるApplicationRecordクラスが持っているメソッドであり、メソッドの宣言は不要です。

データはデータベースの一番新しいidで保存されます。
*モデル名の頭文字は大文字にすること*

## テーブルからデータを取り出し（Railsコンソール）
```ruby
# テーブルにある最初のデータを取得する
変数名 = モデル名.first

# 取得したデータの特定のカラム値を取得する
変数名.カラム名

# テーブルにある全てのデータを配列として取得する
変数名 = モデル名.all

# 取得した配列からインデックス番号"0"のデータの特定のカラム値を取得する
変数名[0].カラム名
```

## テーブルからデータを取り出し（アクション）
```ruby
def アクション名
    @変数名 = モデル名.first
    @変数名 = モデル名.all
end
```

## 共通のレイアウトをまとめる
Railsでは、「views/layouts/application.html.erb」に共通のHTMLを書いておくことができます。
このファイルには<%= yield %>というコードがあり、各ビューファイルはこの<%= yield %>部分に代入され、application.html.erbの一部としてブラウザに表示されるからです。
ヘッダーなど、使い回すレイアウトはここに集約させましょう。

## HTMLにリンクを追加
```erb
<%= link_to("画面表示名", "/リンク先URL") %>
```

うまくまとめられているでしょうか…
改善や修正があればご指摘ください！
はじめての OpenAI Codex #2 ― VSCodeで“Tab補完”を体験

## 1. GitHub Copilot をインストール
1. VSCode 左の拡張機能アイコンをクリック  
2. **GitHub Copilot** を検索 → **Install**  
3. GitHub アカウントでサインイン（30 日無料トライアル可）

> 💡 Copilot は Codex 系モデルを VSCode に統合した“リアルタイム補完ツール”です。

## 2. 3 行書くだけでアルゴリズム完成?!
```python
# ソートしたいリスト
nums = [5, 3, 8, 1]

# ▼ここで Tab を押す
```
- Copilot が `nums.sort()` を灰色で提案  
- **Tab** で確定 → 一瞬でバブルソート!!

## 3. コメント駆動開発の威力
```python
# 与えられた文字列が回文か判定する関数
```
- コメントを書いた瞬間、10 行ほどの関数を全自動生成  
- テスト入力も提案されることがある

## 4. 補完精度を高めるコツ
| コツ | Why |
|------|-----|
| コメントは英語がベター | 学習データ量が段違い |
| 変数名を具体的に | `data_list` より `age_list` |
| 温度設定は 0〜0.1 | 拡張設定 → `panel` → `Temperature` |

## 5. ショートカット早見表
| 操作          | キー            |
|---------------|-----------------|
| 提案受け入れ   | `Tab`           |
| 次の候補       | `Alt` + `]`     |
| 前の候補       | `Alt` + `[`     |
| 提案を非表示   | `Esc`           |

## 6. よくある疑問
> **Q. 英語コメント必須?**  
> 日本語でも動きますが、専門用語は英語にした方が文脈精度が高いです。  
>
> **Q. オンライン必須?**  
> はい。現状 Copilot はクラウド推論のみです。

## 7. 次回予告
> **Day 3：プロンプトから “丸ごとファイル” を自動生成**  
> CRUD API を 1 プロンプトで量産してみます!
Openshift CLIで確認できる主要なリソース（oc）

`oc get`や`oc describe`などのコマンドを使って表示できるリソースの一部をまとめました。

Kubernetesの`kubectl get`で確認できるリソースは、すべてOpenshiftの`oc get`コマンドでも確認することができます。Openshift特有のリソースはKubernetesでは確認できません。

確認できる全リソースを知りたい場合は`oc api-resources`コマンドを使用します。

* ワークロード

|リソース名|短縮形|K8sにあるか|概要|
|---|---|---|---|
|`pods`|`po`|〇|コンテナの実行単位|
|`podtemplates`||一部〇|Podのテンプレート（単体では非推奨）|
|`nodes`|`no`|〇|ノード情報|
|`jobs`||〇|1回限りのタスクを管理|
|`cronjobs`|`cj`|〇|定期実行ジョブを管理|

* ワークロード管理

|リソース名|短縮形|K8sにあるか|概要|
|---|---|---|---|
|`replicasets`|`rs`|〇|Podのレプリカ数を管理（通常Deploymentが生成）|
|`deployments`|`deploy`|〇|Podのデプロイとスケーリングを管理|
|`deploymentconfigs`|`dc`|✕|Deploymentの管理|
|`confingmaps`|`cm`|〇|設定情報をキー・バリューペアで保存|
|`persistentvolumes `|`pv`|〇|クラスタ全体のストレージリソース|
|`persistentvolumeclaims`|`pvc`|〇|ストレージ要求を管理|
|`podautoscalers`|`kpa,pa`|〇|Podの水平スケーリング（HPA）|
|`clusterautoscalers`|`ca`|〇|クラスタ全体のノードスケーリング|
|`schedulers`||一部〇|Podのスケジューリング設定（現在は非推奨）|

* アクセス制御や認証、ログ

|リソース名|短縮形|K8sにあるか|概要|
|---|---|---|---|
|`namespaces`|`ns`|〇|リソースを分離するための名前空間|
|`projects`||✕|OpenShiftの名前空間の拡張（Namespaceのラッパー）|
|`bindings`||一部〇|ローカルなリソースバインディング（現在は非推奨）|
|`roles`||〇|名前空間内の役割定義|
|`rolebindings`||〇|名前空間内の役割バインディング|
|`clusterroles`||〇|クラスタ全体の役割定義|
|`clusterrolebindings`||〇|クラスタ全体の役割バインディング|
|`secrets`||〇|機密情報を保存（例：パスワード、トークン）|
|`serviceaccounts`|`sa`|〇|Podやプロセスの認証用アカウント|
|`clusterversions`||✕|OpenShiftクラスタのバージョン情報|
|`events`|`ev`|〇|クラスタ内のイベントログ|

* ネットワーク管理

|リソース名|短縮形|K8sにあるか|概要|
|---|---|---|---|
|`endpoints`|`ep`|〇|サービスのエンドポイント情報を管理|
|`services`|`svc`|〇|Podへのネットワークアクセスを提供|
|`ingresses`||〇|外部トラフィックを管理（Ingressリソース）|
|`networks`||✕|OpenShiftのネットワーク設定（SDNなど）|
|`routes`||✕|外部トラフィックをサービスにルーティング|

* イメージ管理

|リソース名|短縮形|K8sにあるか|概要|
|---|---|---|---|
|`images`||✕|コンテナイメージのメタデータ|
|`imagestreams`|`is`|✕|コンテナイメージの各種バージョンなどを追跡するリソース|
|`builds`||✕|ビルドの実行履歴|
|`buildconfigs`|`bc`|✕|ビルドプロセスの設定（例：ソースからイメージ生成）|
|`templates`||✕|リソース作成のテンプレート|
|`pipelines`||✕|CI/CDパイプライン（Tektonベース、OpenShift Pipelines）|
rex0220 関連テーブルプラグイン テーブル表示

[関連テーブルプラグイン](https://qiita.com/rex0220/items/973da400b31137f22d98)で、テーブルを表示してみます。

# 概要

関連テーブルプラグインには、もともとテーブル表示の機能がありませんが、
HTMLを組み立てて表示することが出来ます。

![2025-05-19_19h14_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/d258601e-0385-41f2-86ba-3fc984ebecd3.png)


# 関連テーブルプラグイン設定

対象アプリのテーブル内項目（オプションT, オプション費用T）をTAGS_HTML関数で、HTML 形式に変換して表示します。

![2025-05-19_19h18_46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/84c3f63d-8554-4a5b-9c6e-6e3aabc4d70a.png)

![2025-05-19_19h19_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/b11e1cc9-fbaf-42ba-b349-68ff4770330e.png)

```JavaScript:
// オプション詳細の計算式
LET(
  table, TARRAY(オプションT),
  IF(ARRAY_COUNT(table) = 0, "",
    TAGS_HTML(
      TAG("style", JOIN(ARRAY(
        ".custom-table { width: auto; table-layout: auto; border-collapse: collapse; }",
        ".custom-table th { background-color: #c0eefe; }",
        ".custom-table th, .custom-table td { white-space: nowrap; border: 1px solid darkgray; padding: 4px 6px; }",
        ".custom-table td:last-child {  white-space: initial; }",
        ".value-right { text-align: right; }"
      ), NEWLINE(), 1)),
      TABLE_HTML(table, OPT("pref", "custom-"),
        オプションT, オプション費用T
      )
    )
  )
)
```
UnityプロジェクトがInitialize package managerで止まって開けない問題の対応方法

MacでUnityプロジェクトを開こうとすると、initialize package manager で表示が止まってしまって、そこから進まなくなる現象に遭遇しました。その対応方法です。

# 前提
* Mac Sequoia 15.2 (M4)
* Unity Hub 3.11.1（ARM版から、ARM版でない方に変更）
* Unity 2022.3.18

# 対応方法
1. Unity Hub をアンインストールします。
1. Unity Hubの `ARM64版ではない方` をダウンロードします。
1. ロゼッタをインストールする必要がある旨のポップアップが表示されるので、はいを押してインストールします。
1. 再びUnity Hubを起動して、Unityプロジェクトを起動すると、止まることなく正常に起動できます。

# 参考
* [My unity project is stuck at initialize package manager](https://www.reddit.com/r/unity/comments/1k7lq40/my_unity_project_is_stuck_at_initialize_package/)
Docker SwarmのOverlayネットワークを使ったWebサービス構築＋NginxでIPが取れない話

この記事では、Docker Swarmの**Overlayネットワーク**の仕組みを、**Nginx・Webアプリ・DB構成の実例を通してわかりやすく解説**します。

さらに、実際に構築してみると気づくのが...

> **「Nginxでクライアントの本当のIPが取れない問題」**

その原因と対策までカバーします！

---

## 🛠️ システム構成

今回は以下のような3サービス構成をSwarm上に構築します：

| サービス    | 説明                            |
| ------- | ----------------------------- |
| `nginx` | 外部からのHTTPリクエストを受けるリバースプロキシ    |
| `web`   | Webアプリケーション（例：Flask, Node.js） |
| `db`    | データベース（MySQLなど）               |

### 🖼️ ネットワーク構成（Mermaid）

```mermaid
flowchart LR
    Client[クライアント]
    NGINX[Nginxコンテナ@Node1]
    WEB[Webアプリ@Node2]
    DB[MySQL@Node2]

    Client -->|HTTPリクエスト| NGINX
    NGINX -->|proxy_pass| WEB
    WEB -->|SQL接続| DB
```

3つのサービスは `overlay` ドライバを使用した仮想ネットワーク `app_net` に接続されています。

---

## 📦 `docker-compose.yml`（Swarm用）

```yaml
version: "3.9"

services:
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    networks:
      - app_net

  web:
    image: my-web-app
    networks:
      - app_net

  db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: example
    networks:
      - app_net

networks:
  app_net:
    driver: overlay
```

---

## ⚠️ NginxではクライアントIPが取得できない理由

Swarmでは、\*\*Ingressネットワーク（IPVS経由）\*\*を介してサービスへリクエストがルーティングされます。このとき、クライアントの元IPは、**SwarmのルーティングノードのIPに上書き**されてしまいます。

つまり、`$remote_addr` はこんな感じになります：

```
SwarmのノードIP（例：10.0.0.x） → ❌ クライアントのグローバルIPではない
```

### Nginxログの例：

```
10.0.0.2 - - [19/May/2025:15:00:00 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.79.1"
```

> **本当のIP（例：203.0.113.25）ではない！**

---

## 💡 解決策1：Swarmの外にNginxを出す

Swarmの外部でNginxをホストして、**Swarm内のWebアプリにプロキシする構成**にすることで、真のIPが取得できます。

### ステップ：

1. NginxはSwarmの外で動かす（ホスト上や別VM）
2. Swarm内のWebサービスを `mode: host` でポート公開
3. NginxはSwarmノードのIPとポートへ `proxy_pass`

```nginx
location / {
    proxy_pass http://192.168.1.101:8080;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
```

---

## 💡 解決策2：PROXY protocolを使う（中級者向け）

* `Traefik` や `HAProxy` を使い、`PROXY protocol` を通して本当のIPを転送
* Nginx側でも `proxy_protocol` を有効にする必要あり
* 手間はかかるが、Swarm内部でもクライアントIPを維持できる

---

## 📌 Overlayネットワークのまとめ

| 特徴         | 内容                         |
| ---------- | -------------------------- |
| 分散仮想ネットワーク | ノード間をまたいだ通信を仮想化            |
| 自動名前解決     | サービス名でコンテナにアクセスできる         |
| 暗号化可能      | VXLANベースのトンネル通信（希望すればTLS可） |
| スケーリング対応   | Webアプリを拡張してもネットワーク構成を維持    |

---

## 🧪 おすすめの構成

| 構成                                       | メリット           |
| ---------------------------------------- | -------------- |
| 外部Nginx + Swarm Webサービス直アクセス（mode: host） | 最も簡単に本当のIPが取れる |
| Traefik or HAProxy + PROXY Protocol      | 内部完結できるが設定は複雑  |

---

## 📘 まとめ

* Docker SwarmではOverlayネットワークで分散コンテナがつながる
* NginxをSwarm内に置くと、クライアントIPが取得できない
* 対策は「外に出す」or「PROXY protocol」

---

## 🙋‍♂️ 補足

* SSL終端を外部Nginxでやる構成も一般的です
* Overlayネットワーク内でも `service_name:port` で簡単に接続できます
* SwarmのIngressバランサは便利だが「IP透過性」がない点は注意！