OmniAICreator/Qiita-1.07M huggingface dataset:
WSL で terraform が遅かった問題を解決

# 概要
WSL で terraform の実行が著しく遅かったため、/etc/resolv.conf に記載されているネームサーバを変更して解決しました。解決に至る経緯、対処方法についてご紹介します。

# 環境
* Windows 11
* WSL2
* Ubuntu-20.04

# 原因究明へのヒント
terraform plan を実行したところ、以下のようなエラーが出ました。これが terraform が遅い問題の本質的原因でした。

> Error: retrieving Subscription (Subscription: "abcde012-1234-5678-abcd-0123456789ab"): subscriptions.Client#Get: Failure sending request: StatusCode=0 -- Original Error: Get "https://management.azure.com/subscriptions/abcde012-1234-5678-abcd-0123456789ab?api-version=2021-01-01": dial tcp: lookup management.azure.com on 172.17.64.1:53: cannot unmarshal DNS message

IPアドレス 172.17.64.1 は /etc/resolv.conf に記載されているネームサーバのものですが、ここからの返答が適切に処理できない感じです。ちなみに Ubuntu からインターネットへの接続に問題はなく、たとえば www.google.com に対して ping の応答は返ってきていました。

とはいえ、ネームサーバを 8.8.8.8 に変更してみたところ、上記エラーは出なくなり、また terraform plan も想定通りの速度で実行完了するようになりました。

# WSL で /etc/resolv.conf の永続化
WSL の起動設定を何もしていなければ、**イーサネット アダプター vEthernet (WSL)** のIPv4アドレスの値になるはずです。起動時に自動生成してくれます。これは、上記のように手動でネームサーバを変更したとしても、WSL を再起動したら変更されてしまうということを意味します。そこで自動生成を止めます。

```bash
sudo vi /etc/wsl.conf
```

```:/etc/wsl.conf
[network]
generateResolvConf = false
```

これで自動生成しなくなったので万事めでたしかと思い WSL を再起動してみます。

```PowerShell
wsl --shutdown
wsl
```

```bash
cat /etc/resolv.conf
```

```:実行結果
cat: /etc/resolv.conf: そのようなファイルやディレクトリはありません
```

おや？ファイルが消されてしまいました。おそらく内部的には

1. イーサネット アダプター vEthernet (WSL) の IPv4アドレスを取得
1. /run/resolvconf/resolv.conf に上記アドレスを nameserver の値として設定
1. /run/resolvconf/resolv.conf /etc/resolv.conf にシンボリックリンクを張る

を起動時に行い、終了時に

1. /etc/resolv.conf を unlink する
1. /run/resolvconf/resolv.conf を削除

を行っているのではないかと思います。そして、generateResolvConf を false に設定したことで起動時の処理は行われなくなったけど、終了時の処理は実施されてるのではないかと推察されます。そこで起動時に /etc/resolv.conf を欲しい状態で作成するように設定します。

```bash
sudo vi /etc/resolv.conf.dist
```

```:/etc/resolv.conf.dist
nameserver 8.8.8.8
```

※ 8.8.8.8 の値はお好きなものにしてください。

```bash
sudo vi /etc/wsl.conf
```

```:/etc/wsl.conf
[boot]
command = "cp -rup /etc/resolv.conf.dist /etc/resolv.conf"

[network]
generateResolvConf = false
```

起動時の処理は [boot] ブロックの command の値に実行したいコマンドを記載することで実現できます (複数のコマンドを実行したい場合には ; (セミコロン) 区切りで記載します)。これで /etc/resolv.conf を固定化することに成功しました。

# おわりに
ちなみに Google 先生に "wsl terraform slow" で問い合わせると、[Very slow on Ubuntu/WSL2 due to PATH containing entries from Windows](https://github.com/warrensbox/terraform-switcher/issues/158) という Github issue に辿り着きます。WSL では何も設定していないと、Windows コマンドも実行できるように環境変数 PATH が長大になります。これに起因しているということでしたが、PATH の値を手動で設定し直して文字数を小さくしても、事態はなにも改善しませんでした。
AZ-104 Microsoft Azure Administrator Associate 認定資格 を取得しました

# はじめに
Azureに触れる機会が増えるため学習をしていますが、アウトプットの一つとして、Microsoft Azure Administrator Associateを取得してみました。

# Microsoft Azure Administrator Associate(AZ-104) とは
[この辺](https://docs.microsoft.com/ja-jp/learn/certifications/exams/az-104)を参照ください。
[AWS Certified Solutions Architect – Associate](https://aws.amazon.com/jp/certification/certified-solutions-architect-associate/)に近いものかと思います。 

# 教材
利用した順番に記載しています。

1. オンライントレーニング：[Microsoft Learn (AZ-104向け)](https://docs.microsoft.com/ja-jp/learn/certifications/exams/az-104)
    - 量は多いですが、Azureの基礎を学ぶことができます。演習も用意されているため、触りながら覚えることができます。
    - これだけで試験に挑むのは厳しいため、別途模擬試験を行う必要があると思います。
    - なお、[AZ-104:Azure リソースの監視とバックアップ](https://docs.microsoft.com/ja-jp/learn/paths/az-104-monitor-backup-resources/)の[Log Analytics の構成](https://docs.microsoft.com/ja-jp/learn/modules/configure-log-analytics/)に不具合があり完了することができません。Microsoftへ報告済みですが、未だ改善されず。
1. 問題集：[これだけで合格！AZ-104 Microsoft Azure Administrator模擬試験問題（4回分260問）](https://www.udemy.com/course/az-104-microsoft-azure-administrator4260/)
    - 260問(65x4セット)の問題集です。
    - 他者の受験記で紹介されていないのですが、「これだけで合格！」の言葉に魅かれて購入しました。
    - 初回の正答率は平均65%で、試験前には100%にして挑んでいます。
    - 実際に合格できましたので効果はあったと思います。

# 試験について
- 学習期間として、2週間強(Microsoft Learn:約1週間、問題集:1週間強)となります。
- 試験会場で受験しました。
- 問題数は、60問強(受験時に変動するそうです)でした。
- 最初にシナリオ問題(2題x4-5問)、通常の選択問題(40問強)、再度に2択問題(10問弱)という流れです。
- シナリオ問題は、長文の問題(ユーザの概要、システム構成、今後の計画、要件)を読み、それを踏まえて選択問題を解きます。
- 2択問題は、問題分に記載されてることが正しいか・間違っているか選択します。
- シナリオ問題と2択問題は、一度進めると戻って見直すことができないため、慎重に進める必要があります。
- 試験時間は100分で、私は約80分要しています。
- 全問解くと最後に合否(得点有)が表示されます。
- 出題範囲/傾向は、問題集と近いと思います。サクッと解けたものは約60%ぐらいでした。悩む問題・覚えていないとどうしようもない問題もそれなりにあり、苦戦しました。

# 感想
- 問題集を100%の状態にしていましたので余裕をもって受けました。が、試験中は、だめかなと思う時もありましたが、結果合格できて安心しました。
- 上位試験([AZ-305](https://docs.microsoft.com/ja-jp/learn/certifications/exams/az-305))の取得も都合が合えば挑みたいと思います。
Next.js/Firebaseを使って旅行記を載せるサイトを作った【初】

## はじめに
今日から大学３回生になる者ですが、コロナ禍もあってかあまり学校での勉強が捗らなかったので勉強してみました。その際に、自分の兄がエンジニアとして仕事をしているので協力を仰ぎました。優しい兄でよかったです。
サイトはこちら→[My Travel Note](https://my-travel-note.vercel.app/)
自分のツイッターはこちら→[小橋亮介](https://twitter.com/ryooosk_2143)
兄のツイッターはこちら→[こばしゅん](https://twitter.com/ksyunnnn?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor)
## コード
https://github.com/Ryooosk/my-travel-note
## なにができるのか
各都道府県ごとのページ閲覧
Firebaseを使用し、画像含む各ページのテキストも管理している。そしてページごとにデータを取得し表示させている。加えて、ライブラリとしてchakra-uiのモーダルウィンドウを使用して表示の幅を広げている。
## まだできないこと
サイトからの画像やテキストの投稿、削除、変更
# だいたいの流れ
### サイトの構想
サイトを作るうえで、何が難しくて何なら手を付けやすいのかがわからなかったので、しっかりと自分の作りたい最大のサイトを構想した。
### ライブラリの選択
モーダル表示を利用したかったので、いろいろと調べたうえで一番しっくりときた、chakra-uiのものを選んだ。
### データベースの利用
たくさんの写真、それに付随するデータを利用するので、どう管理すべきかと考えたときに兄が提案してくれたサービスがFirebaseです。その中で、Cloud Firestoreを利用しています。合わせて、画像を管理するためにCloud Storage for Firebaseも利用しています。
### ウェブデザインの変更
なにを使うかが決まると、それに合わせてデザインの変更をしました。より見やすく使いやすいものを目指すため、ツイッターを参考にしました。
### データの取得
ここが一番時間がかかったのですが、Firebaseからのデータの取得です。Firestoreのドキュメントを見つつだが、自分のしたい場所や自分のしたいタイミングでの取得が難しかった。
### コードの整理
コンポーネントを作ってレイアウトの部分ごとにレンダリングするようにし、加えてファイルも分けてコードも見やすいものへと変更した。
### レスポンシブ対応
どのサイトを見てもレスポンシブ対応がされており、いくつかのサイズに合わせて対応させた。
### ロード画面の追加
データの取得中のアンバランスなページを訂正すべく、実装した。
### ページの公開
Vercelを利用してページを公開しました。
### apiキーをenvファイルで管理
githubを公開するうえで、Firebaseのapiキーをenvファイルで管理した。また、Vercelの環境変数機能も使用した。
# 使ったサービス
### [chakra-ui](https://chakra-ui.com/)
これは兄からの提案で利用することを決めました。とてもよいモーダルで自分の考えていたそのものでした。
### [Firebase](https://firebase.google.com/?hl=ja)
これも兄からの提案です。理想的なサービスだった。
### [Google fonts](https://fonts.google.com/)
フォントについて調べていた際、出てきたので利用した。
### [Github](https://github.com/)
兄とのデータの共有、いずれ使うこと多くなるよと言われたので練習も兼ねて利用しました。
# 使ったサイト
### [原色大辞典](https://www.colordic.org/)
### [MDN Web docs](https://developer.mozilla.org/ja/)
- CSS レイアウト入門
- details
- :hover
- list-style
- border
### [サルワカ](https://saruwakakun.com/)
ul ol liタグの使い方まとめ
### [Faviconジェネレーター](https://favicon-generator.mintsu-dev.com/)
# 感想
とにかく初めてのことだらけで、かなり時間がかかって難しかった。けど、それ以上に自分で自分の作りたいものを作ることがこれからできるようになるワクワクが同時に生まれた。もっと頑張る。
Node.js v12 -> v16にyumでアップデートしてみた。(CentOS 7)

# Node.js v18がリリース
node.jsのv18（LTS予定)が、リリースされました。

前回インストールしたv12のサポートが2022-04-30で終了するということで、v18にアップデートしようと思ったのですが、ちょっと旨くいかなかったので、取りあえずv16(LTS)にアップデートしてみたいと思います。

以前、v12をインストールした記事は以下。

https://qiita.com/daichi_pd/items/239a7e3eea74c5be6dc9

## セットアップ用スクリプトを利用する

今回は、nodesourceで準備されているシェルスクリプトを利用してアップデートします。
（アップデートでは無く、新規インストールも以下の方法でインストールできると思います。）

curlがインストールされてない場合はcurlをインストールしておきます。
（すでにインストールされている人は飛ばしてください）

```sh
yum -y install curl
```

CURLを利用して、スクリプトをダウンロードして、実行します。
```sh
curl -sL https://rpm.nodesource.com/setup_16.x | sudo bash -
```

yumのキャッシュが邪魔をすることがあるようなので、一端クリアしておきます。
```sh
yum clean all
```

yumを使ってnodejsをアップデートします。
（始めてnodejsをインストールする場合は、"update"を"install"にして実行します）
```sh
yum -y update nodejs
```

バージョンを確認して終了です
```sh
node --version
v16.14.2
```

~~いずれv18用のセットアップスクリプトが公開されると思いますので、急いでない人は、v18に直接アップデートしてもよいでしょう。~~

enjoy!


## 追記 (v18のセットアップを使ってみる。)

v18のセットアップ用スクリプトも公開されたようなので、16->18 にアップデートしようとしたところ、何やらライブラリーが対応してないと怒られた…

```sh
curl -sL https://rpm.nodesource.com/setup_18.x | sudo bash -
yum clean all
yum -y update nodejs
:
:
Error: Package: 2:nodejs-18.0.0-1nodesource.x86_64 (nodesource)
           Requires: libc.so.6(GLIBC_2.28)(64bit)
Error: Package: 2:nodejs-18.0.0-1nodesource.x86_64 (nodesource)
           Requires: libstdc++.so.6(CXXABI_1.3.9)(64bit)
Error: Package: 2:nodejs-18.0.0-1nodesource.x86_64 (nodesource)
           Requires: libstdc++.so.6(GLIBCXX_3.4.21)(64bit)
Error: Package: 2:nodejs-18.0.0-1nodesource.x86_64 (nodesource)
           Requires: libstdc++.so.6(GLIBCXX_3.4.20)(64bit)
Error: Package: 2:nodejs-18.0.0-1nodesource.x86_64 (nodesource)
           Requires: libm.so.6(GLIBC_2.27)(64bit)
```

色んなライブラリーが、未対応っぽい。他への影響を鑑みて、取りあえず Node.jsは、v16を使おうと思います(^^;

追記の追記…
v18失敗したので、再度v16のセットアップファイルを実行して、v16で運用できることは確認しました。
Flutter　公開済みAndroidアプリの更新時テストで、署名が異なるエラーが出たとき

## アプリのアップデートでエラー
Flutterで作成し、既にPlayStoreで公開済みのAndroidアプリを更新する際のテストで、
アプリの更新ができなかった事象について、備忘録として記載します。


## 前提条件
・バージョン1.0.0を新規アプリとしてPlayStore公開済み
・上記公開時はapkファイルではなく、aabファイルで申請を行った
・バージョン1.1.0をapkファイルとして作成
・アプリはFlutterで作成

## 更新できなかった事象
PlayStoreより、既に公開されている1.0.0をダウンロードし、そのあとローカルで作成した1.1.0の新バージョンapkファイルを
ファイルシステムより、インストールしようとしたところ、８割ほどインストールが進んだのちに、「アプリはインストールされていません。」と表示され、正常にインストールができなかった。

## 試してみたこと
1.0.0アプリがインストールされた状態で、1.1.0バージョンの実行をflutter run --release コマンドで行った。
すると、署名が異なるのでエラーする旨のメッセージが表示された。

```
Flutter signatures do not match  previously installed version
```

実際に署名が異なるのか、1.0.0バージョンのapkファイルを取っておいたので、1.0.0と1.1.0のapkファイル、aabファイルそれぞれの署名を確認してみた。  
キーストアファイルのフィンガープリントを出力する
```
keytool -v -list -keystore myKeystore.keystore
```
APKの署名のフィンガープリントを出力する
```
keytool -printcert -jarfile myApp.apk
```

署名に用いるキーストアファイル、apk、aabのフィンガープリントについて、全て同一であったため、署名に差異が無いように思われた。

## 内部テストを利用して解決
Google play consoleでは、内部テストとよばれるioSのTestFlightのようなシステムがある。
それを用いると、実際にPlayStoreからダウンロードすることができる。

aabファイルをアップロードし、内部テストを行うと、正常にアップデートができた。
どうやら、aabファイルからapkに変換する際に、Google側で何かしらの情報が付与されており、
同じ署名を付与したapkファイルでも、異なると判断されてしまうようだった。
dumpファイルの取り込み（MySQL）

## 概要
現場に入場してすぐの環境構築のときに上長からdumpファイルと取り込み用のコマンドが送られてきたが、dumpファイルの取り込み方が分からない、若しくはなんだか警告が気になる人向け。（mysqlコマンドの復習）

## コマンド
筆者が上長から受け取ったコマンド

```
mysql -h(ホスト名) -P（ポート番号） -u（ユーザ名） -p（パスワード） （DB名） < （ファイル名）
```
なお、基本はユーザ名、パスワード、DB名でいける。他は開発環境による。
取り込み自体はできたが以下の警告文が気になる。。

```
mysql: [Warning] Using a password on the command line interface can be insecure.
```

簡単なことだが、こんな時はパスワードをコマンドに放り込んでいるのが良くない（らしい）。
```
mysql -h(ホスト名) -P（ポート番号） -u（ユーザ名） -p （DB名） < （ファイル名）
```
この後にパスワードを聞かれて、その後は警告なく実行された。

## まとめ
なんてことはないが、筆者は警告文が気になるお年頃。
自分的シェルスクリプトガイド

bashの前提

## 開発環境
- vscodeで開発する
- シェルのlinter ShellCheckの拡張機能を導入する

https://marketplace.visualstudio.com/items?itemName=timonwong.shellcheck



## シェバング

```sh
#!/bin/bash -eu
```

### オプション説明
#### e
コマンドに失敗(戻り値が0以外)した場合、エラーになって止まる。
予想外のコマンド失敗が発生したまま後続処理が進行し、取り返しのつかない事態となる事を防いでくれる。

##### 一時解除
なんらかの理由により、コマンド失敗を許容しなければならない場合は、前後に`set +e` `set -e`を記載すると、一時的に制限解除と出来る。
```sh
set +e
command
set -e
```

ちなみに下記のようなコーディングをすれば、一時解除は不要で`command1`が失敗した場合も終了せずに`command2`が実行される。
※もしかしたら環境によって異なるかも。
```sh
command1 || command2
```
```sh
if ! command1; then
  command2
fi
```

#### u
宣言されていない変数を使おうとすると、エラーになって止まる。
```sh
remove_dir="hoge"
rm -rf "/directory/$remove_dire" # タイポ
```
みたいにタイポした場合、上位ディレクトリからごっそり消える事故から守ってくれるので安心。

## 全体構成
原則、下記の構成をとる。
関数が無いような、単純なシェルの場合はmain関数を定義せずに書く場合もあり。

```sh
#!/bin/bash -eu

# 定数

# 関数

# メイン
main() {
  # メインの処理
}

main "$@"
```


## 変数
### 定数
アッパースネークケース
`readonly`とする
```sh
readonly SAMPLE_CONSTANT="hoge"
```

### 変数
スネークケース
```sh
sample_variable="hoge"
```

### ローカル変数
関数内でしか使わない変数は`local`を付与しローカル変数とする。
変数名は先頭に`l_`を付与する。

```sh
local l_variable="hoge"
```
3D空間で紙飛行機を回転（オイラー角）


# 紙飛行機をモデルにしてオイラー角で回転する様子をpython matplotlibで見てみます

https://github.com/OkitaSystemDesign/python3d

オイラー角を使って紙飛行機を回転
PaperAirplaneEuler.py
![Euler400.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2489321/f7a52772-3df5-ae06-74db-3983e613e637.gif)
## 環境
Windows10
python3.9
numpy
Matplotlib


## 使い方
#### 紙飛行機を回転させる関数
```python
PaperAirplaneEuler(angle, order)
```
angleに目標とする姿勢のオイラー角[x,y,z]をセットて渡します
orderは回転順でXYZ,XZY,YXZ,YZX,ZXY,ZYXの種類の中から選択します
#### 例
```python
angle = [20.0, 30.0, 40.0]
order = EulerOrder.XYZ
PaperAirplaneEuler(angle, order)
```
オイラー角（angle）にX=20度、Y=30度、Z=40度回転するようにセットします  
回転順（order）にXYZ順を指定します 回転順はEulerOrder列挙型で指定します  
PaperAirplaneQuaternionを実行すると3次元のグラフが表示されて[F1]キーで回転順に回転が始まります

## 説明
紙飛行機は各頂点の点を結んでポリゴンで表示しています
回転順に回転軸を中心に回転する様子を確認できます

## オイラー角の計算
計算はこちらを参考にしました
[回転行列、クォータニオン(四元数)、オイラー角の相互変換](https://qiita.com/aa_debdeb/items/3d02e28fb9ebfa357eaf)
Conoha VPSの使用感


# はじめに

ASJのレンタルサーバからconoha vpsにサーバを移行して3年経過しました。

移行してよかったこと、悪かったこといろいろありますが、とりあえず3年経ったのでconoha vpsの使用感をざっくりと振り返ってみました。VPSの乗り換えを検討している方が参考になればと思います。

# 背景

以前は主にレンタルサーバを利用してきました。2015年ぐらいまでにロリポップ、さくら、コアサーバ、エックスサーバなどで70～80ぐらいのサイトを構築・運営してきました。個人サイトや店舗などのサイトであればこれで十分なのですが、運用しているサービスの一つが会員制サイトで月間平均20万PVぐらいあり、かつデータベースがそこそこ大きいのでCPU・メモリのスペックと、OSの設定をいじれるVPSに乗り換えることにしました。

2017年頃から検討して最終的にさくらVPSとConoha vps、あとAWSが候補に上がり、敷居の低さ、コンパネの見易さ、それとマニュアルが充実してそうなconoha vpsに決めました。


# 良かったこと

### ・コンパネが見やすい

　直感的にわかりやすく、プラン変更もシンプルでした。マニュアルもそこそこ揃っているので、初期の移行時はそれほど困ることはありませんでした。

### ・安定して稼働している

　サーバなので、安定稼働は絶対条件ですが、この点については問題はありませんでした。たまにCPUが暴走することはありましたが、再起動で直りました。

# 悪かったこと

### ・メールサーバが不安定

　メールサーバにはIMAPでつないでいますが、同期速度が異常に遅いため困りました。メーラーをいろいろ変えましたがどれも遅かったのでサーバ側の問題だと思います。ただ2022年にメールサーバが新しくなったのでそちらで試したところ、かなり速くなりました。

### ・サポート対応

　移行当初からサポートの回答がおそいな～とは思っていましたが、そもそも問い合わせをすることがほとんどないのであまり気にしていませんでした。それが、2022年になってメールサーバが新しくなるという通知があり、移行マニュアルに沿ってを移行していましたが、マニュアルに無いエラーが出たため問い合わせフォームから問い合わせをしたところ、最初は回答があったのですが、回答内容通りでは解消されなかったため、再度問い合わせしたところ、その後返信がありませんでした。以降、何度か問い合わせをしましたが結局一週間回答がなく、しびれをきらして電話サポートをしましたが、初日は1時間待って電話がつながらず、2日目は2時間待ってもつながらなかったので諦めました。


# 総評

サーバ自体の安定稼働、操作感などは良かったです。大きな障害もなかったのでそこは大手だなと思いました。

ただ、2022年になってサポートに電話が全くつながらない、お問い合わせフォーム・メールも途中から一切返信がない、状況確認のお願いをしても返信がないという点については、運営会社としては致命的だと感じました。

VPSのサポートに問い合わせする場合を想定すると、初期の移行時かトラブル発生時に限られると思うので、特に後者でサポートがつながらないと不具合が数日～数週間解消されないリスクがあり、それは私たちにとってはちょっと許容できないリスクだなと感じました。



そのため、利用してから3年経った今、別サービスへの乗り換えを検討するつもりです。
Chocolatey のアンインストール

# 環境
* Chocolatey
* Windows

# 手順
:::note alert
「環境変数？」「PATH？」な方は触らないほうがいいです。
:::

## 1. Chocolatey のインスールフォルダを削除する

`C:\ProgramData\chocolatey`をフォルダ毎削除する。見つから無い場合は、Windows PowerShellで以下のコマンドを実行すると分かる。
```ps1:Windows PowerShell
PS C:\Users\[user]> echo $env:ChocolateyInstall
C:\ProgramData\chocolatey
```

## 2. 環境変数の削除
### 2-1. ユーザー環境変数を削除。
* ChocolateyLastPathUpdate
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682590/47a2ba3d-b91b-40dd-70cf-769f100fd894.png)
### 2-2. 以下のシステム環境変数を削除
* ChocolateyInstall
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682590/0746862d-3bbb-bdc2-5d87-d5f681d363a2.png)
* ChocolateyToolsLocation
こちらは見当たらないので無視。あれば削除

### 2-3. PATH の更新
システム環境変数に`C:\ProgramData\chocolatey`があるので削除する。
* システム環境変数のPATH
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682590/0a0813d4-4ec2-4d30-a097-317073c73d26.png)
* 「環境変数名の編集」ダイアログ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682590/7a968800-cfd4-4358-8c53-32aab4c6ffe4.png)

了

# 参考

https://docs.chocolatey.org/en-us/choco/uninstallation
Chocolateyのインストール

# 環境
* Windows

# 手順

## 1. Windows PowerShell でインストール
管理者として実行された Windows PowerShell で以下のコマンドを実行
```ps1:Windows PowerShell
PS C:\Users\[user]> Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
```

## 2. インストールされたか確認
```ps1:Windows PowerShell
PS C:\Users\[user]> choco -v
1.1.0
```


了

# 参考

https://docs.chocolatey.org/en-us/choco/setup
海外FXのランキングの点数制の導入

当社が運営する海外FX比較ナビで、この度、業者ランキングを点数化して根拠や情報の引用元を掲載するようにした。

[海外FX比較ナビ](https://nagoweb.co.jp/kaigaifx/)

ここ最近のGoogleはレビューアップデートを数回行っており、口コミの引用元情報やランキングなどの根拠などを根拠のあるものに対して評価をアップさせるアップデートを行っている。

海外FX比較ナビでは私の海外FXの経験に基づいてランキング化していたが、公平性が求められるようになったため、各情報の引用元や点数の根拠を入れるようにしている。

このように今のGoogleではE-A-TだけでなくGoogle全体をWikipedia化して、情報の根拠や情報元を明らかにする動きが出ている。

SEOを行なう者としてはGoogleの動きに追従して行く必要があるが、なかなか大変ではある。

今後も厳しい戦いが続くと思うが、頑張ってSEOについて行きたいと思う。
Ansibleを用いたOpsRamp - OneView連携

# やりたいこと
新規デバイス検出時にOneViewでサーバプロファイルをそのデバイスに割り当てる。

![OneView_Integration_for_Qiita.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/d56af6e1-afd4-6085-c5f4-76f5697885fd.gif)

# 構成
![Diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/3bf0f74f-6f80-ff39-756b-623040f992dd.png)

1. OpsRamp Gatewayによるデバイス検出
2. デバイス検出イベントをトリガにProcess Definitions(workflow)を実行
    1. OpsRamp AgentからAnsible Playbookを実行
    2. Ansible Playbookにより、OnveViewで以下を実行
        a) Server Profile TemplateからServer Profileを作成
        b) Server Profileに検出したデバイスを割り当てる

:::note info
AnsibleでOneViewを操作するために「oneview-ansible-collection」を使用
https://github.com/HewlettPackard/oneview-ansible-collection
:::

# OpsRamp設定
## デバイス検出設定
「Setup」->「Resources」->「検出(ディスカバリ)と配置」から検出プロファイルを作成
![DiscoveryProfile1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/3f4a9e39-e977-cfbe-5dc2-d09300170f3d.png)

各項目を適宜設定
![DiscoveryProfile2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/7f2d2f51-e636-a97c-38b0-72de1491d21f.png)

:::note warn
「検出プロファイルのタイプ」に「SNMP」を選択
「認証情報」に予め作成したSNMPの認証方法を選択 (「資格情報の作成」から新規作成することも可能)
:::

## Ansible Integration
「Setup」->「インテグレーション」->「インテグレーション」からAnsibleインテグレーションをインストール
![AnsibleIntegration1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/9887fb64-7720-bcd0-cfb1-9d796295b67f.png)

Ansibleデバイスを選択
![AnsibleIntegration2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/c8101d34-58a4-38b9-5b09-f45c7a983784.png)

:::note warn
予めAnsibleデバイスにOpsRamp Agentのインストールが必要
:::

Ansible Playbookを登録
![AnsibleIntegration3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/02206be8-17e5-d450-65e4-82da7fa072a2.png)

## Process Definition (Workflow)
「Automatin」->「Process Definitions」からWorkflowを作成
![ProcessDefinitions1_.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/0ac57134-1bb7-bafe-0a97-147956b80a5f.png)

「StartEvent」、「Script Task」、「EndEvent」を配置し、「Script Task」を下記のように設定
- Configuration: 「Agentless」を選択
- Integration: インストールしたAnsible Integrationを選択
- Playbook: 登録したAnsible Playbookを選択
- Inputs: デバイス情報をAnsible Playbookの引数として渡すパラメータを入力 (「Process Definition」では、変数としてデバイス情報を持つ)
![ProcessDefinitions2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/dfc30ee5-f369-0458-854a-15257a89dd07.png)


---------------------------------------
[<img width = 250 height = 200 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/111de30a-4d33-aa33-5c7d-83d9015093e6.png">](https://www.vistanet.jp/knowledge-base/)
【AWS】MacからAmazonLinuxにSSH接続する方法(備忘録)

# はじめに
MacからAmazonLinuxにSSH接続する方法を備忘録として残しておきます。

# 前提
- AmazonLinux2は既に作成済み
- 秘密鍵ファイル(cerファイル)は既に取得済み(Downloadsフォルダに配置済み)
- クライアント端末(Mac)からAmazonLinux2にSSH接続するためのSG設定等は設定済み
- Mac端末を利用

# 手順

以下の流れでやっていきます。

**1.秘密鍵ファイルの移動と権限設定**
**2.TerminalからSSH接続を実施**

## 1.秘密鍵ファイルの移動と権限設定

- 秘密鍵ファイルの移動

`~/.ssh`ディレクトリに秘密鍵ファイルを移動

```bash:コマンド
mv /Users/ma-sato/Downloads/tmp-tastylog-dev-keypair.cer  ~/.ssh/.
```

- 権限設定

```bash:コマンド
chmod 400 ~/.ssh/tmp-tastylog-dev-keypair.cer
```

権限変更前)
```bash:実行例(権限変更前)
ma-sato@satsuton Downloads % ls -l ~/.ssh/tmp-tastylog-dev-keypair.cer
-rwx------@ 1 ma-sato  staff  1674  4 20 14:42 tmp-tastylog-dev-keypair.cer
ma-sato@satsuton Downloads %
```

権限変更後)
```bash:実行例(権限変更後)
ma-sato@satsuton Downloads % ls -l ~/.ssh/tmp-tastylog-dev-keypair.cer
-r--------@ 1 ma-sato  staff  1674  4 20 14:42 tmp-tastylog-dev-keypair.cer
ma-sato@satsuton Downloads %
```

:::note warn
秘密鍵ファイルはその他の全てのユーザーの読み取り及び書き込み操作から保護されている必要があります。
(保護されていなければ、警告メッセージが表示されSSHログイン不可)
:::

## 2.TerminalからSSH接続を実施
以下コマンドを実行し、SSH接続を実施する。

```bash:コマンド
ssh -i <秘密鍵のファイルパス> ec2-user@<パブリックIPアドレス>
```

```bash:実行例
ma-sato@satsuton Downloads % ssh -i ~/.ssh/tmp-tastylog-dev-keypair.cer ec2-user@13.231.234.138
Last login: Wed Apr 20 06:18:40 2022 from flh2-133-200-145-161.tky.mesh.ad.jp

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
1 package(s) needed for security, out of 8 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-192-168-1-105 ~]$
```

### フル権限の場合(備考)

以下の権限の場合、SSH接続を実施すると警告が表示される。

- 権限変更・確認

```bash:権限変更
chmod 777 ~/.ssh/tmp-tastylog-dev-keypair.cer
```

```bash:権限確認
ma-sato@satsuton Downloads % ls -l ~/.ssh/tmp-tastylog-dev-keypair.cer
-rwxrwxrwx@ 1 ma-sato  staff  1674  4 20 14:42 /Users/ma-sato/.ssh/tmp-tastylog-dev-keypair.cer
ma-sato@satsuton Downloads %
```

- SSH接続

以下のようにWARNINGが表示される。

```bash:SSH接続確認
ma-sato@satsuton Downloads % ssh -i ~/.ssh/tmp-tastylog-dev-keypair.cer ec2-user@13.231.234.138
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0777 for '/Users/ma-sato/.ssh/tmp-tastylog-dev-keypair.cer' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/Users/ma-sato/.ssh/tmp-tastylog-dev-keypair.cer": bad permissions
ec2-user@13.231.234.138: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
ma-sato@satsuton Downloads %
```

※詳しくは、以下のAWS公式ドキュメントをご確認下さい。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/TroubleshootingInstancesConnecting.html#troubleshoot-unprotected-key

# さいごに
これからは仕事でWindowsではなくMacを使用するようになるため、覚えることが多いですが今回のように気になったことは記事にしていきたいと思います。

# 参考記事
https://qiita.com/nakm/items/695e41d8e71d0d281ac4
データ型の覚えやすい暗記法を思いついた

# 背景
プログラミング初学者からPythonの場合strが「文字列」でintが「数字(整数)」だと全く覚えられず混乱するから良い覚え方はないかと打診を受け、「なるほど、、、」と思い考案。

# 覚え方
## str(String)
**st**o**r**yは**文字**で書く。
## int(Int)
**int**elliは**数字**で語る。
## bool(boolean)
正解(true)かな？いいえ、不正解(false)です！ブーー(**boo**l)

## 所感
もはやギャグですが、「いい国作ろう鎌倉幕府」みたいなノリで初学者には理解してもらえるようです。
需要があれば随時更新していきます。
Ruby Hashオブジェクト ハッシュの基礎知識

# ハッシュとは
Key(キー)とValue(バリュー)の組み合わせで関連付けを行うことができるオブジェクトです。

```ruby
user1 = {id: 1, name: 'Tom'} => { :id => 1, :name => "Tom" }
user2 = {id: 1, name: 'Bob'} => { :id => 1, :name => "Bob" }

user1[:name] => "Tom"
user2[:name] => "Bob"
```

`Key`をシンボル`:`で定義した場合・・・`変数 = { key: value, key: value, ... }`

```ruby
user1 = {id: 1, name: 'Tom'} => { :id => 1, :name => "Tom" }
# シンボルで定義した Key を String で指定した場合、値を参照することはできない。
user1['name'] => nil

user3 = { 'id' => 3, 'name' => 'Jon' } => {"id"=>3, "name"=>"Jon"}
user3['name'] => "Jon"
```
上記のように、`key`を 文字列で表す場合、`key`を `String`で定義する必要があります。

# 多次元ハッシュ
ハッシュの`value`にさらにネストされたハッシュが格納されている階層構造のハッシュを指します。

```ruby
user4 = {
  id: 4,
  name: 'Smith',
  test_results: {
    math: 70,
    science: 80
  }  
} => {:id=>4, :name=>"Smith", :test_results=>{:math=>70, :science=>80}}

user4[:test_results][:math] => 70
user4[:test_results][:math] = 100
user4 => {:id=>4, :name=>"Smith", :test_results=>{:math=>100, :science=>80}}
```

## `Key`の配列を取得する場合

```ruby
# 該当要素のみ取得する場合
user4.key("Smith")
=> name

# 全て取得する場合
user4.keys
=> [:id, :name, :test_results]
```

## `value`の配列を取得する場合

```ruby
# 該当要素のみ取得する場合
user4["name"]
=> ["Smith"]

# 全て取得する場合
user4.values
=> [4, "Smith", {:math=>100, :science=>80}]
```

## `eachメソッド` で `hashメソッド`を繰り返し処理する場合

```ruby
user4 => {:id=>4, :name=>"Smith", :test_results=>{:math=>100, :science=>80}}

user4.each do |k, v|
  puts "#{k} = #{v}"
end

# 出力結果
# id = 4
# name = Smith
# test_results = {:math=>100, :science=>80}
```
`|k, v|` は `|key, value|`を省略した記述です。

## `key` と `value`を削除する場合
`deleteメソッド`の第一引数に削除対象の`key`を渡すことで削除できます。

```ruby
user4.delete(:test_results) => {:math=>100, :science=>80}

user4 => {:id=>4, :name=>"Smith"}
```

## 参考教材

https://www.udemy.com/course/rails-kj/
docker-composeでコンテナ生成時にMYSQLにテーブルを追加

# 引用記事
https://scrapbox.io/gyarasu/docker-compose%E3%81%A7MySQL%E3%81%AB%E5%88%9D%E6%9C%9F%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95

```docker-compose.yaml
version: '3'
services:
  app:
    build: ./docker
    ports:
      - 80:80
    volumes:
      - ./app:/var/www/app
    working_dir: /var/www/app
  db:
    image: mysql:8.0
    volumes:
      - ./initdb.d:/docker-entrypoint-initdb.d # コンテナ作成時に実行されるsqlファイルを格納するパスをdocker-entrypoint-initdb.dにマウント
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    restart: always
    ports:
      - 3306:3306
    environment:
      MYSQL_DATABASE: image_database
      MYSQL_USER: user
      MYSQL_PASSWORD: pass
      MYSQL_ROOT_PASSWORD: pass
```
Docker側にマウントしたinitdb.dディレクトリ直下のcreate_table.sqlがコンテナ生成時に実行される。
`.sql`のほか、`.sh`も自動的に実行される
C＃を使用してWord文書から画像を抽出する方法

画像とテキストはWord文書で最も一般的な2つの要素です。Microsoft Wordを使用する際、文書内の画像を抽出する場合は、画像で右クリックして「名前を付けて保存」を選択し、画像の名前を編集してから保存すると解決できです。そして今日の記事は、主にC＃および無料で使える.NET用のWordコンポーネント[Spire.Doc for .NET]()を使用して、Word文書から画像を抽出する方法をシェアします。
こちらはテキストと画像を含むWordドキュメントです
 
## 詳細な手順および使用するコード
ステップ1：引用を追加します。
新しいVisualC＃コンソールプロジェクトを作成し、参照を追加して、次の名前空間を使用します。
```
using System;
using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;
```
ステップ2：新しいWordドキュメントオブジェクトを作成し、画像を抽出したい Wordドキュメントをロードします。
```
Document document = new Document("sample.docx");
```
ステップ3：ドキュメント内のすべてのセクションをトラバースし、画像を見つけて抽出し、保存します。
```
int index = 0;

foreach (Section section in document.Sections)
{
    foreach (Paragraph paragraph in section.Paragraphs)
    {
        foreach (DocumentObject docObject in paragraph.ChildObjects)
        {
            if (docObject.DocumentObjectType == DocumentObjectType.Picture)
            {
                DocPicture picture = docObject as DocPicture;

                String imageName = String.Format(@"images\画像-{0}.png", index);

                picture.Image.Save(imageName, System.Drawing.Imaging.ImageFormat.Png);
                index++;
            }
        }
    }
}
```
## 完全なるコード
```
using System;
using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;
using System.Drawing;

namespace Extract_image_from_word
{
    class Program
    {
        static void Main(string[] args)
        {
            Document document = new Document("C:\\Users\\Administrator\\Desktop\\sample.docx");
            int index = 0;

            foreach (Section section in document.Sections)
            {
                foreach (Paragraph paragraph in section.Paragraphs)
                {
                    foreach (DocumentObject docObject in paragraph.ChildObjects)
                    {
                        if (docObject.DocumentObjectType == DocumentObjectType.Picture)
                        {
                            DocPicture picture = docObject as DocPicture;

                            String imageName = String.Format(@"images\画像-{0}.png", index);

                            picture.Image.Save(imageName, System.Drawing.Imaging.ImageFormat.Png);
                            index++;
                        }
                    }
                }
            }
        }
    }
}
```
抽出された画像は以下のように
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/7a10ba4d-4ef0-4768-78b0-0f396aa5d434.png)

## 結語
今回のWord文書から画像を抽出する方法は以上でした、最後まで読んでいただきありがとうございました。
【８日目】メモ帳アプリの作成 [supabaseを活用]

前回まではメモ帳のアプリを作ったが、localStrageを利用してメモの履歴を保存して表示させるプログラムを作りました。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="vYpaqME" data-user="mizmizsan2" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/mizmizsan2/pen/vYpaqME">
  Memo5</a> by mizmizsan2 (<a href="https://codepen.io/mizmizsan2">@mizmizsan2</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

上が完成させたプログラムです。入力フォームに何かを入力してsaveボタンを押すとlocalStrageにメモの内容と入力した日時が保存され、「メモ保存領域」に表示されます。deleteボタンを押すとlocalStrageに保存されている内容が削除されて「メモ保存領域」からなくなります。

localStrageを活用しているところを今回は「supabase」を使って保存をしていきます。

---

まず最初の準備としてテーブルを準備します。
今回はメモ内容の「contents」と日付の「date」を使用します。
![memoStrage1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2584729/1a6c46a4-97c3-daf6-64b6-a8620a2d1f85.png)
今回はエラーを防ぐためにあらかじめダミーのデータを入れておきます。

- プログラム
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="zYpejaP" data-user="mizmizsan2" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/mizmizsan2/pen/zYpejaP">
  Memo10</a> by mizmizsan2 (<a href="https://codepen.io/mizmizsan2">@mizmizsan2</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

データを扱うinsert,select,deleteはsupabaseのページに乗っている例をそのまま引用しました。

配列の最後の値をとるカウントの値は配列の最後のidを取ってきて使うので`data.slice(-1)[0].id`を使いsupabaseに保存されている一番大きいidの値を取りカウントをします。

データを取り出して表示をする際、dataそのものを文字列化して表示するとこのようになります
`[{"id":24,"date":"2022/4/20 14:15:43","contents":"aaa"}]`

かっこを見て分かる通り配列と連想配列が組み合わさって表されているので、表示をするときはこのような表現方法になります。
`data[0].contents` `data[0].date`
「data配列の0番目にある連想配列の"contents"を表示」という命令になります。


＊このようにデータが追加されたり削除されたりします
![memoStrage2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2584729/5559922b-424d-d061-c24a-22e98d49917f.png)
Ricty Diminished のバッククォートが被る問題

## はじめに

バックエンドメインのエンジニアなんですが、今年の2月からiOSもちょこちょこ担当することになりました。
ただとにかくIntel Macでアプリのビルドに時間がかかるので、M1 Macを支給してもらいました。(ありがたい:laughing:)

で、M1 Macのセットアップをイチから行いましたが、だいぶ地味にハマったところをメモしておきます。

## VSCode でバッククォートが被る！

Markdownでコードブロックにするときバッククォート3つ打ちますが、うまく表示されない...。
![ScreenShot 2022-04-20 2.09.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245142/c9827ced-3e89-54c2-8832-72ee67382c41.png)

### 環境

- M1 MacBook Air
- VSCode で表示確認


## 結論

フォントの問題でした。(だいぶ遠回りしました...)
私はプログラミング用のエディタでは [Ricty Diminished](https://rictyfonts.github.io/diminished) というフォントを愛用してるんですが、これのバージョンを下げたら直りました。

- 4.1.0 NG
  ![ScreenShot 2022-04-20 2.15.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245142/870e90cc-6396-d61a-10e0-7b7263d4937c.png)
- 4.0.1 OK
  ![ScreenShot 2022-04-20 2.48.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245142/65bc267b-3868-f05b-cf1f-d50d3de5f70e.png)

## 参考

https://zenn.dev/konboi/articles/6dcd22f4e77c175653ed


## おわりに

プログラミング用のフォント選びでは、

- 日本語文字と英数字の幅が2:1になっている
- フリー
- 見た目ダサく感じない(自分が)

を重視してるんですが、 Ricty Diminished はそう思ってた時に見つけてその後ずっと使い続けてます。

みなさんもおすすめのフォントがあったら教えていただけると嬉しいです！
[OCI]Autonomous Database : Bastion経由でPrivate Endpointを持つADBのDatabase Actionsに接続してみた時のメモ

# はじめに

Private Endpointを持つAutonomous DatabaseのDatabase Actionsに、インターネットからBastion経由でアクセスできるか試してみた時のメモです。


# 1.Autonomous Databaseの作成
Private Endpointを持つADBを作成します。
![スクリーンショット 2022-04-20 13.30.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/2b779715-fb64-588b-06c3-ab2b1e90091a.png)

# 2.Bastionの作成
Bastionを作成します。
![スクリーンショット 2022-04-20 14.08.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/40958ccb-d9de-f596-dae9-7e2145ed348b.png)

![スクリーンショット 2022-04-20 14.11.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/2b4fe3cc-4800-e07d-b5bd-783834bbcfb6.png)

# 3.セッションの作成
セッションを作成します。
![スクリーンショット 2022-04-20 14.14.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/dfd005a0-9a4d-1a38-7220-ecb213f4e5c8.png)

![スクリーンショット 2022-04-20 14.14.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/59dd656b-bdeb-4fcb-dc8b-fec933b000bf.png)

# 4.SSHコマンドの取得
セッションに接続するためのSSHコマンドを表示してコピーします。
![スクリーンショット 2022-04-20 14.15.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/ee27c359-29bd-0a2a-e007-b92a7459d256.png)

![スクリーンショット 2022-04-20 14.16.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/3e695702-7e71-ad7a-5886-2898e6d3eec0.png)

```
ssh -i <privateKey> -N -L <localPort>:10.0.2.254:443 -p 22 ocid1.bastionsession.oc1.ap-tokyo-1.amaaaaaangvnfviasdkioarsvofuidreakiq2j5lzres7cssar55djdgvv7q@host.bastion.ap-tokyo-1.oci.oraclecloud.com
```

# 5.セッションへの接続
コピーしたSSHコマンドを編集して、クライアントPC（今回はMacのターミナルを使用）から実行します。
ここでは、
プライベートキー：/Users/hoge/privateKey
ローカルポート：443
を使用しています。
```
sudo ssh -i /Users/hoge/privateKey -N -L 443:10.0.2.254:443 -p 22 ocid1.bastionsession.oc1.ap-tokyo-1.amaaaaaangvnfviasdkioarsvofuidreakiq2j5lzres7cssar55djdgvv7q@host.bastion.ap-tokyo-1.oci.oraclecloud.com
```
# 6. Database Actionsへのアクセス
ブラウザからDatabase Actionsにアクセスします。
```
https://localhost/ords/sql-developer
```
証明書のサーバ名と一致しないため警告が表示されますが、無視してアクセスします。
![スクリーンショット 2022-04-20 14.21.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/44702cc1-7468-3c57-b066-af3de9349a12.png)
※2020/6/9追記
クライアントPCの/etc/hostsに
127.0.0.1    ＜ADBのプライベート・エンドポイントのURL＞
を追加することで、セキュリティ警告が出ないようにすることが可能です。

ユーザ名adminを入力して「次」をクリックします。
![スクリーンショット 2022-04-20 14.23.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/eb71451f-8a66-a481-3549-6a24c908bad8.png)
adminのパスワードを入力して「サインインをクリックします。
![スクリーンショット 2022-04-20 14.24.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/469f7c8c-cf65-c280-8e8f-a99ddc999955.png)
Bastion経由でDatabase Actionsに接続できました。
![スクリーンショット 2022-04-20 14.32.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/136b8bb8-fadf-432d-bebe-d4695c91bddf.png)
Laravel9のマイグレーションの外部制約について

# エラーが起きた背景
外部キーの制約をし、マイグレーションを実行しました。

```php
Schema::create('folders', function (Blueprint $table){
    $table->increments('id');
    $table->foreign('user_id')->references('id')->on('users');
    $table->string('title');
    $table->timestamps();
    });
```

すると

```
 Illuminate\Database\QueryException 

  SQLSTATE[42000]: Syntax error or access violation: 1072 Key column 'user_id' doesn't exist in table (SQL: alter table `folders` add constraint `folders_user_id_foreign` foreign key (`user_id`) references `users` (`id`))

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:745
    741▕         // If an exception occurs when attempting to run a query, we'll format the error
    742▕         // message to include the bindings with SQL, which will make this exception a
    743▕         // lot more helpful to the developer instead of just the database's errors.
    744▕         catch (Exception $e) {
  ➜ 745▕             throw new QueryException(
    746▕                 $query, $this->prepareBindings($bindings), $e
    747▕             );
    748▕         }
    749▕     }

      +9 vendor frames 
  10  database/migrations/2022_04_19_024851_create.folders.php:22
      Illuminate\Support\Facades\Facade::__callStatic("create")

      +33 vendor frames 
  44  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
```
のようなエラーが出ました。



# 解決した方法
```php
Schema::create('folders', function (Blueprint $table){
    $table->increments('id');
    $table->foreignId('user_id'); //外部キー制約 
    $table->string('title');
    $table->timestamps();
    });
```

```php
 $table->foreign('user_id')->references('id')->on('users');
```
をこちらに変更しました。

```php
$table->foreignId('user_id');
```
先輩エンジニアに聞いてみたらLaravelのバージョン９からできた書き方みたいです。

# 最後に
エラーが出てる状況は人それぞれ違うので上記のやり方で解消されない場合もあるのでご了承ください。

https://readouble.com/laravel/9.x/ja/migrations.html#column-method-foreignId



# 参考資料

https://qiita.com/rokumura7/items/867cde3ec42b24825d32
[JPX Tokyo Stock Exchange Prediction]ロングショート戦略について

こんにちは、tmrtjと申します。

私は現在株式会社音圧爆上げくんという会社に所属しており、プロKagglerとして活動しています。


私は現在プロKagglerとして、業務の一環で、現在Kaggleで行われているコンペの一つである[JPX Tokyo Stock Exchange Prediction](https://www.kaggle.com/competitions/jpx-tokyo-stock-exchange-prediction)に参加しています。

また、今回の記事は、Kaggle上にNotebookとして同じ内容の記事を英語で投稿しています。
リンクは[こちら](https://www.kaggle.com/competitions/jpx-tokyo-stock-exchange-prediction/discussion/320886)です。



# はじめに

JPX Tokyo Stock Exchange Prediction は株式投資のコンペです。

1営業日ごとに買い持ちする銘柄を200個選びランク付けし、また売り持ちする銘柄も同様に200個選びランク付けし、そのランクに応じた重みを仮想のポートフォリオとし、パフォーマンスを競います。

これは、実際の資産運用ビジネスにおける、株式のロングショート戦略に相当します。

そこで、今回はこのロングショート戦略について論文などをサーベイするなかで、興味深い論文を見つけたのでシェアします。


その論文は、[Evaporating Liquidity](https://academic.oup.com/rfs/article/25/7/2005/1602153)という論文です。


この論文は、平均回帰戦略について解説したものです。
論文では、ロング・ショートの株式ポートフォリオで平均回帰戦略をシミュレーションしてそのパフォーマンスについて分析しています。
平均回帰戦略とはその言葉どおり、株価が元に戻ることを期待する戦略です。
つまり、直近で下がった銘柄を買い、上がった銘柄を売るというものです。

平均回帰戦略は、クオンツの株式のロングショート戦略で多く使われているため、この論文は、今回のコンペティティションに取り組むにあたっても参考になると思います。


今回の記事では、この論文のポイントに絞って紹介します。

もし、より詳しく知りたい方はリンク先から読んでみてください。

<br>
<br>

# 論文のポイント

・短期の平均回帰戦略は流動性供給の一形態とみなせる。

・そのため、短期の平均回帰戦略のリターンは流動性供給に対するプレミアムである。

・ボラティリティと流動性には負の相関がある。

・短期の平均回帰戦略は相対的に低いボラティリティで非常に高いリターンを得る。

・平均回帰戦略は、平時には良好なパフォーマンスを示す。

・暴落時には酷いパフォーマンスを示す。

<br>
<br>

# コンペティティションに対する示唆

JPX Tokyo Stock Exchange Predictionは、1日ごとに、株式のロングショート戦略でポートフォリオを組み、シャープレシオの最大化を目指すコンペです。

論文でも指摘されているように、平均回帰の戦略は平時の相場では良好なパフォーマンスを示します。
そのため、シャープレシオを最大化するような戦略を一つ選ぶならば、平均回帰戦略になると思われます。

しかし、平均回帰戦略は、相場全体が暴落し、ボラティリティが急上昇するときにはパフォーマンスが悪化します。
なぜなら、平均回帰戦略は流動性供給の一形態であり、ボラティリティが急上昇する際には流動性が枯渇し、リスクが高まるからです。

以上を踏まえると、より良いシャープレシオを達成するためには、通常の相場と、株式市場全体がクラッシュしているときとでは、銘柄の選び方を変えるというのがアイデアとして浮かびます。



<br>
<br>

今回の記事がコンペティションに取り組むにあたり、何かの参考になれば幸いです。

<br>
<br>


# お知らせ
株式会社音圧爆上げくんではプロKagglerを募集しています。
ご興味のある方はぜひ以下のリンクをご覧ください。
[Wantedlyリンク](https://www.wantedly.com/projects/748285)
jQuery　ajaxの書き方　基本

## 用途
JavaScriptの値をPHPに渡して、PHPで処理をしてからJavaScriptに返し、返り値をJavaScriptで使用したい時に使う。
jQueryでajaxを使用したい時に使う。

## 使用方法
### ajaxでの渡し方とPHPでの受け取り方
**①PHPに渡したいデータが1つの時**
```js:ajax　渡したいデータが1つ
$.ajax({
  type: "POST", // GET,POSTを指定。この場合はPOST。GETにしたいならPOSTをGETに変えるだけ。
  url: "◯◯◯◯◯◯◯", // 使用したいPHPファイルを指定。hoge.phpを使用したいなら、hoge.phpと入力。
  data: {key:value} // PHPの処理で使う渡したいデータ。keyは自分で命名、valueは渡したい値。
}).done(function (PHPでの処理の結果) {
  // 通信成功時の処理
}).fail(function () {
  // 通信失敗時の処理
}).always(function () {
  // 成功や失敗にかかわらず常に実行する処理
});
```
```php:PHPでの受け取り方
<?php
  // 受け取り方
  $_POST['key'] // ajaxのdataで指定したkeyをtypeで指定した形で受け取る
  
  // 処理を書く
```

**②PHPに渡したいデータが複数の時**
```js:ajax 渡したいデータが複数
var data = {key1:value1, key2:value2, key3:value3, key4:value4}; // keyは自分で命名、valueは渡したい値。
$.ajax({
  type: "POST", // GET,POSTを指定。この場合はPOST。GETにしたいならPOSTをGETに変えるだけ。
  url: "◯◯◯◯◯◯◯", // 使用したいPHPファイルを指定。hoge.phpを使用したいなら、hoge.phpと入力。
  data: data // PHPの処理で使う渡したいデータ
}).done(function (PHPでの処理の結果) {
  // 通信成功時の処理
}).fail(function () {
  // 通信失敗時の処理
}).always(function () {
  // 成功や失敗にかかわらず常に実行する処理
});
```
または
```js:ajax 渡したいデータが複数
$.ajax({
  type: "POST", // GET,POSTを指定。この場合はPOST。GETにしたいならPOSTをGETに変えるだけ。
  url: "◯◯◯◯◯◯◯", // 使用したいPHPファイルを指定。hoge.phpを使用したいなら、hoge.phpと入力。
  data: {  // PHPの処理で使う渡したいデータ。keyは自分で命名、valueは渡したい値。
    key1:value1,
    key2:value2,
    key3:value3,
    key4:value4
  }
}).done(function (PHPでの処理の結果) {
  // 通信成功時の処理
}).fail(function () {
  // 通信失敗時の処理
}).always(function () {
  // 成功や失敗にかかわらず常に実行する処理
});
```
```php:PHPでの受け取り方
<?php
  // 受け取り方
  $_POST['key1'] // jsのvalue1が渡される。typeで指定した形で受け取る。
  $_POST['key2'] // jsのvalue2が渡される。typeで指定した形で受け取る。
  $_POST['key3'] // jsのvalue3が渡される。typeで指定した形で受け取る。
  $_POST['key4'] // jsのvalue4が渡される。typeで指定した形で受け取る。  

  // 処理を書く
```

### PHPでの返し方
**①echo　json_encode**
※配列またはオブジェクトをそのまま返すとエラーになる。
```php:echo　json_encode
  // ajaxからのデータを受け取る
  // 処理を書く

  //javascriptに受け渡すため配列をJSON形式に変換
  echo json_encode($hoge); // hogeはajaxに返したい値
  exit;
```
**②return**
```php:return
  // ajaxからのデータを受け取る
  // 処理を書く

  if (条件) {
    return true;
  } else {
    return false;
  }
```
【入門】TypeScriptの概要をまとめてみた

# はじめに
現在、独学でプログラミングを学習している
「駆け出してもいなエンジニア」です！:bicyclist:

Reactを学習する中で、TypeScriptも触れた方がいいということを聞き、アウトプットと備忘録として、
今回この記事を投稿しました。

訂正が必要な個所などあれば、お知らせいただけると大変助かります:bow:

本編はここから！↓

# Typescriptとは
TypeScriptはJavaScriptの上位互換でJavaScriptに型が追加されているもので、TypeScriptはJavaScriptにコンパイルされます。

JavaScriptだとデータなどに明確な型がなく、チーム開発の際はうまく機能しない場合がありますが、TypeScriptは型が追加されているので、開発の規模が増えた際でも管理しやすいのです！

逆に言うと、**TypeScriptで拡張されたのは、主に型に関する部分**で、**それ以外のほとんどはJavaScriptそのまんま**ってことです!:baby:

**超ざっくり言うと、TypeScriptとは型の定義ができるJavaScriptなのです**:bangbang:
（厳密にはJavaScriptとは別言語です）

# TypeScriptを使うべき理由
TypeScriptを使うべき理由を4つに分けて説明します！！

## 1,大規模開発に最適
通常**JavaScript**は、**実行してみないと**型にエラーがあるかないかが分かりません。

ですが**TypeScript**では、型が追加されていることにより、**静的チェック**が可能になっているので、**実行する前に**型にエラーがあるか検出できます！

この**静的チェック**が**バグ早期発見によって修正コストも抑える**ことができ、大規模開発において最適なのです！:family_mmbb:

## 2,JavaScriptの知識があれば使える
TypeScriptはJavaScriptの**仕様はそのまま**に、**新しい機能や利点を追加したもの**なので、JavaScriptの知識があれば使い始めることができます。

これにより**学習コストを格段に抑えられます**:bangbang:
(裏を返せば、JavaScriptが分からなければ全く分かりません)

## 3,古いJS環境での開発でも、最新の構文が使える
プロジェクトによっては、**古いJavaScript**(ES5など)しかサポートされていないブラウザでも動作するように実装す場合もありますが、TypeScriptはそれにも対応できます:bangbang:

## 4,利用者人口が多い
利用者人口が多い利点として、次のものが挙げられます。

・**情報が豊富**に出回っている

・エコシステム（**他のIDEやフレームワークが、TypeScriptをサポートする機能**）が**充実**している

**・採用や就職の面でも有利**（企業側にとってプログラマが探しやすく、求職者にとってはプロジェクトを探しやすい）

# まとめ
大規模開発に不向きだったJavaScriptに、**大規模開発向きの機能（型の追加など）を付けてパワーアップ**させたのが**TypeScript**ということです！

どんなに小規模な開発でも、複数人が関わるプロジェクトがほとんどかと思いますので、JavaScriptを使って仕事をしたいと考えている人は、TypeScriptを導入したほうがよいかと思います！
Ruby Arrayオブジェクト 配列の基礎知識

# `push`, `<<` 
配列に要素を追加することができる。

```ruby
arr = []
arr.push('りんご') => ["りんご"]
arr << 'みかん' => ["りんご", "みかん"]
```
# %記法（パーセント記法）
`'`や`"`を別の文字に置き換えて書くことができます。

```ruby
arr = %w[りんご みかん] => ["りんご", "みかん"]
arr2 = %w! りんご みかん! => ["りんご", "みかん"]
arr3 = %w(りんご みかん) => ["りんご", "みかん"]
```
`%w`の場合、シングルクォート`''`で囲ったのと同じ動作になります。

```ruby
a = 'んご' => "んご"
b = 'かん' => "かん"
arr = %W[り#{a} み#{b}] => ["りんご", "みかん"]
```
`%W`の場合、ダブルクォート`""`で囲ったのと同じ動作になるため、式展開やバックスラッシュ記法を使用することができます。

# 繰り返し処理

## `eachメソッド`
配列の要素の数だけブロック内で処理を繰り返します。

```ruby
arr = %w[ りんご みかん ぶどう] => ["りんご", "みかん", "ぶどう"]

arr.each do |fruit| 
  break if fruit == 'ぶどう'  
  puts fruit  
end

# 出力結果
# りんご
# みかん
=> nil
```

`break`を使用することで繰り返し処理を終了することができます。
上記の場合、`後置if文`を使用して`fruit`が**ぶどう**の場合に繰り返し処理が終了します。

```ruby
arr = %w[ りんご みかん ぶどう]
=> ["りんご", "みかん", "ぶどう"]

arr.each do |fruit| 
  next if fruit == 'ぶどう'
  puts fruit
end

# 出力結果
# りんご
# みかん
=> ["りんご", "みかん", "ぶどう"]
```
また、上記のように `next`を使用することで一部の繰り返し処理をスキップさせることができます。

## `mapメソッド`
配列の要素の数だけブロック内で処理を繰り返し、**新しい配列**を返します。

```ruby
arr = ["りんご", "みかん", "ぶどう"]

arr.map { |fruit| "(#{fruit})" }
=> ["(りんご)", "(みかん)", "(ぶどう)"]
```

一部要素のみ取得したい場合

```ruby
arr = [{id: 1, name: 'りんご'}, {id: 2, name: 'みかん'}, {id: 3, name: 'ぶどう'}]

arr.pluck(:name)
=> ["りんご", "みかん", "ぶどう", "りんご"]
```

## 多重代入
左辺に変数をカンマ区切りで記述し、右辺には左辺に記述した変数に代入するオブジェクトや式などをカンマ区切りで記述することで、複数の変数にまとめてオブジェクトを代入することができます。


```ruby
foo, bar = [1, 2]
foo => 1
bar => 2

# []は省略可
foo, bar = 1, 2
foo => 1
bar => 2

foo, bar  = 1
foo => 1
bar => nil
```

:::note alert
右辺の要素に対して左辺の変数が多い場合は無視され、
左辺の変数が右辺の要素より多い場合、代入される要素がない変数には「nil」が代入されます。
:::

## 参考教材

https://www.udemy.com/course/rails-kj/
CSSの適用方法

## CSSとは
HTMLのみでCSSがないWebサイトは白い背景と黒い文字だけのシンプルな表示です。CSSはWebサイトの土台であるHTMLの見た目を調整できる言語です。CSSを使えば華やかに装飾できてます。

### CSSを適用させる方法
#### CSSファイルを読み込んで適用させる

　１つ目は「.css」の拡張がついたCSSファイルを作成し、それをHTMLファイルに読み込ませて適用させる方法があります。Webサイトを制作するときは、この方法が最も一般的です。１つのCSSファイルを複数のHTMLファイルに読み込まぜられるので、一括管理できます。修正が入った場合も1つのCSSファイルを変更するだけなので簡単です。
###### 適用方法
HTMLファイルの`<head>`内に`<link>`タグを使ってCSSファイルに指定します。rel属性に「stylesheet」、href属性にCSSファイルを指定すれば、CSSファイルに書かれた装飾を適用させます。
```html:適用方法
<!doctype html>
<html lang="ja">
 <head>
  <meta charset="UTF-8">
   <title>タイトル</title>
   <meta name="description" content="サイトの説明文">
   <link rel="stylesheet" href="style.css">
 </head>

  <body>
    Webサイトの内容
  </body>

</html>
```
#### HTMLファイルの`<head>`内に`<style>`タグで指定する
２つ目はHTMLファイルの`<head>`内にCSSを書き込む方法です。CSSを記述したHTMLファイルでのみ適用されます。前の適用方法とはちがい他のHTMLファイルには反映されないので注意が必要です。特定のページのみ、デザインを変えたいと時に使えます。
##### 適用方法
タグの中にCSSを書くときは、各タグの中にstyle属性を使って指定します。
```html:適用方法
<!doctype html>
<html lang="ja">
 <head>
  <meta charset="UTF-8">
   <title>タイトル</title>
   <meta name="description" content="サイトの説明文">
   <style>
     h1{color:#f00;}
     p{font-size:18px;}
 </head>

  <body>
    Webサイトの内容
  </body>

</html>
```
#### HTMLタグの中にstyle属性を指定する
３つ目はHTMLタグに直接CSSを書き込む方法です。直接書かれたタグにのみ適用されます。１つひとつのタグに指定するので手間がかかり、メンテナンスも難しいです。ただ、ほかの方法で指定するよりCSSを適用させる優先順位が高く、CSSを上書きしたいときや一部のデザインだけ変更したいときに使えます。
##### 適用方法
```html:適用方法
<!doctype html>
<html lang="ja">
 <head>
  <meta charset="UTF-8">
   <title>タイトル</title>
   <meta name="description" content="サイトの説明文">
 </head>

  <body>
    <h1 style="color:#f00;">Webサイトの内容</h1>
    <p style="font-size:18px;">テキスト</p>
  </body>

</html>
```
上記のとおり、「HTMLファイルの`<head>`内に`<style>`タグに指定する」や「HTMLタグの中にstyle属性を指定する」のやり方だとCSSをまとめて管理することが難しく、メンテナンスに時間がかかってしまいます。特別な理由がない限りは「CSSファイルを読み込んで適用させる」方法で適用させましょう。

## 終わりに
今回はCSSの適用方法を解説しました。次回はCSSコードを解説したいと思います。

エンジニアファーストの会社　[株式会社CRE-CO](https://www.cre-co.jp/) 吉川　真史
【shopify】受注から納品までの流れ

# はじめに
私が初めてshopifyの案件を受注した時、どんな流れで進めていけばわからなかったので、備忘録として記録しています

# 受注から納品まで流れ

　打ち合わせ
　↓
　デザイン作成ー側だけ作る
　↓
　見積もり
　↓
　コンテンツ受領
　↓
　構築　
　↓　
　テスト
　↓　
　レビュー
　↓
　修正
　↓
　リリース


# 打ち合わせ項目 一覧

## 用件定義
　・事業内容
　・ターゲット層
　・競合
　・コンセプト
　・ドメインはどうするのか？

## 用意頂くもの
　・商品の画像
　・サイトに使用する写真ーデザインを決める段階でどうするか決める
　・コンテンツの文章
　・ストア名
　・パスワード
　・ストア住所

## テスト
　ログインの動線の確認や誤字などの確認

## レビュー
　修正回数をあらかじめお客様と決めておく
　日程も決めておく

## リリース
　リリース日を決め、納期をきめる
Docker-compose.ymlの中身の詳細

# Docker-compose.ymlの中身の詳細
```Docker-compose.yml
version: '3'
#dbとwebのサービスを定義
services:
  db:  #msql
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password #認証形式の設定８.０から
    volumes:
      - ./src/db/mysql_data:/var/lib/mysql  #./src/db/mysql_data(ローカル)を/var/lib/mysql（docker）側に共有する設定（コンテナを作り直すたびにデータが消えてしまうが、これを設定しておけばローカルのデータを持ってこれる）
    environment:
      MYSQL_ROOT_PASSWORD: password #(環境変数でパスワードを指定)
  web: #rails
    build: . #ベースのイメージとしてDocker fileを参照する設定
    command: bundle exec rails s -p 3000 -b '0.0.0.0' #rails サーバーを起動
    volumes:
      - ./src:/app #./src(ローカル)内を/app（Docker）側に共有する
    ports:
      - "3000:3000" #ローカルの3000ポートをDockerの3000ポートに接続
    depends_on: #webはdbサービスに依存しているという設定
      - db
```

Docker-compose.ymlを作成したのでその中身の説明をメモしておく
```Docker-compose.yml
services:
  db: 
  web:
```
services:は今回のDocker-compose.ymlの大枠として
今回は　db:とweb:　の二つのサービスを入れた。
このdb:とweb:に設定を入れていく

# db:
```
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password
```
```
    volumes:
      - ./src/db/mysql_data:/var/lib/mysql 
```
./src/db/mysql_data(ローカル)　を　/var/lib/mysql（docker）側に共有する設定（コンテナを作り直すたびにデータが消えてしまうが、これを設定しておけばローカルのデータを持ってこれる）
```
    environment:
      MYSQL_ROOT_PASSWORD: password 
```
環境変数でパスワードを指定
# web:
```
    build: . 
```
ベースのイメージとしてDockerfileを参照する設定
```
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
```
 rails サーバーを起動
```
    volumes:
      - ./src:/app 
```
./src(ローカル)内を/app（Docker）側に共有する
```
    ports:
      - "3000:3000" 
```
ローカルの3000ポートをDockerの3000ポートに接続
```
    depends_on: 
      - db
```
webはdbサービスに依存しているという設定
Dockerファイル変更時に変更が反映されないことを防ぐために

開発中にDockerfileを更新したらdocker-compose buildしてもcacheが有効になっていて設定変更が反映されないことがある
`docker-compose build --no-cache`
しておくのが安全

そのあと、念の為`docker-compose up --force-recreate`しておくとコンテナを再作成して起動できる。
なので変更が反映されていないという問題が減るはず。

# 参考記事
https://codenote.net/vm/docker/3756.html
https://codenote.net/vm/docker/3781.html
상품추가 함수

상품추가하는 부분때문에 개고생함
filter() 함수가 작동되지 않고
splice(index, 1)은 되는데 filter()안돼서 개고생함

```javascript:store.js

   addItem(state, item) {
      const resultItems = state.items.filter((cartItem) => {
//cartItem.id = item.id; 이렇게 해서 개고생
        cartItem.id === item.id;
      });

      if (resultItems.length === 0) {
        state.items.push({
          ...item,
          qty: 1,
        });
      } else {
        resultItems[0].qty++;
      }
    },
```

```javascript:CartList.vue
<template>
  <div>
    <!-- Cart -->
    <section class="cart bgwhite p-t-70 p-b-100">
      <template v-for="(item, index) in items">
        <tr :key="index" class="table-row">
          <td class="column-1">
            <div
              class="cart-img-product b-rad-4 o-f-hidden"
              @click="delItem(item.id)"
            >
              {{ item.id }}
              <img :src="item.image" alt="IMG-PRODUCT" />
            </div>
          </td>
        </tr>
      </template>
    </section>
  </div>
</template>

<script>
import { mapState, mapGetters } from "vuex";

export default {
  computed: {
    ...mapState(["items"]),
    ...mapGetters(["totalPrice"]),
  },
  methods: {
    delItem(id) {
      this.$store.dispatch("delItem", id);
    },
  },
};
</script>

<style></style>

```