OmniAICreator/Qiita-1.07M huggingface dataset:
Macにsymfonyをインストールする

# 概要
これまでnode.jsでガリガリ書いていたところ、新年度から配属される部署ではPHP+symfonyを使った開発をすることになったため、勉強がてらsymfonyで開発できる環境を準備する。
（PHP久しぶり・・・）

この記事では、symfonyインストールからサーバを立ち上げてlocalhostで表示確認するところまでをスコープとする。

# 前提
今回の手順ではhomebrewを使うため、homebrewがインストールされている前提です。

# 手順
## 1. composerインストール
phpのパッケージ依存管理ツールであるcomposerをインストール。

```
# とりあえずアップデート
$ brew update

# composerインストール
$ brew install composer
```

## 2. symfonyをインストール
[公式](https://symfony.com/download)で書いてある通り、curlを使ってインストールする。

```
$ curl -sS https://get.symfony.com/cli/installer | bash
・
・
・
The Symfony CLI v4.23.2 was installed successfully!

Use it as a local file:
  /Users/xxxxxxx/.symfony/bin/symfony

Or add the following line to your shell configuration file:
  export PATH="$HOME/.symfony/bin:$PATH"

Or install it globally on your system:
  mv /Users/xxxxxxx/.symfony/bin/symfony /usr/local/bin/symfony

Then start a new shell and run 'symfony'
```

インストールしただけだとパスが通ってないのでフルパスでないとsymfonyコマンドが打てない。
ログに出ている通り3つの対応方法があるが（１個目はフルパスで頑張れですが）、シンプルにbin以下にコマンドを移すことにする。

```
$ mv /Users/xxxxxxx/.symfony/bin/symfony /usr/local/bin/symfony
```

## 3. プロジェクトを作る
versionでlts指定すれば安定板が入るので、lts指定で作る。

```
$ symfony new <project name> --version lts
```

## 4. ローカルサーバを立ち上げて表示させる
composerを使ってserver入れて立ち上げてる人と、phpコマンドで立ち上げてる人がいる。
とりあえず表示させるだけなので、どちらでもおk。

### serverで立ち上げるパターン

```
# serverをインストール
$ composer req server

# 起動
$ bin/console server:run
```

### phpコマンドで立ち上げるパターン

```
$ php -S localhost:8000 -t public
```

## 5. localhostにアクセスして表示確認
以下にアクセスしてこんなページができたら成功！
アクセスするたびに色が変わる！
http://localhost:8000/
![スクリーンショット 2021-03-12 0.45.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630783/6e682b77-493f-f4a1-d529-6d00d130ce5a.png)


# まとめ
というわけで、導入はとても簡単に表示までできました。
ここからお作法やらプラクティスを学んでいくわけですが、また別の機会にノシ
カラムの追加方法

####DBにカラムの追加の仕方####

#####マイグレーションファイルの作成#####
空のマイグレーションファイルの作成する
```rails g migration file_name```

作成されたファイルに変更内容を書く
カラムの追加

```
def change
 # add_column :テーブル名, :カラム名, :型
　add_column :users, :image_name, :string 
end
```
#####コンソールで実行#####

```rails db:migrate```
PHP5上級試験/準上級試験の上級合格に挑戦(11)　中間振り返り

# はじめに

+ ひとまず10記事、オブジェクトの章まで完了した
+ ここまでのわからなかったところはつぶせてよかった
+ だけど、テストは実は9日後、やばい
+ 仕方がないので21章の総まとめ問題をまずは解いてみた

# 21章総まとめ問題

できてなかったところ　主に真ん中から終わりがほぼできてない感。

・Webテクニック　ini設定、Basic認証（スーバークローバル関数）、セッション
・データベース　特にMDB2とPDOの違いや executeとexecをどういうときに使うかとか
・GD(いわゆる図形クラス）
・XML
・セキュリティ
・出力バッファリング
・エラーハンドラ
・PHP拡張モジュール
・SPL
・日付・時刻クラス
・クロージャ
・名前空間・遅延静的束縛（SELFとか）
・JSON
・mysqlnd
・正規表現
・フィルタ

ひとまず総まとめ問題を理解してできてなかったテーマの章に戻ってがんばることにする
各テーマでこれ出てきそうだなという問題はテスト後にまたまとめてアップしたいと思う
ひとまずテスト後までおやすみ
Laravel　Intervention Imageを使って画像ファイルを小さくする方法

画像を投稿するWEBアプリを作ってみました。

タイトル：俺が飲んだもの
https://oreno-drink.com/

俺が飲んだものを俺がアップする自分の記録用に作ったアプリです。
なぜ作ったか？なんとなく楽しそうだし自分が飲んだ珍しいものを記録したいじゃないですか。日々いろんな飲み物を飲むわけだし。

サーバーはさくらインターネットのレンタルサーバを使っています。画像を保存することは問題なくできるのですが、画像のファイルが大きく画像の読み込みに時間がかかることに悩んでいました。
画像ありきなアプリだけに画像の読み込みが遅いのは致命的。イライラします。

PageSpeed Insightsで調べるとカメラで撮った画像は一枚当たり2,500 ~ 3,500KiBありかなり重い状態。


なんとか画像を圧縮できる方法はないかと調べ、一度試したのが画像を一度LINEで送信してから保存して再度サイトにアップするというやり方です。これだと確かに画像サイズ100 ~ 180KiBと小さくなり、読み込みも早くなるのですが、、、なんといっても手間だし自分以外の人がアップロードした画像は小さくできません。

何かいい方法はないのか、、調べてみるとIntervention Imageというライブラリが良さそう。試そう。

Intervention Image公式ページ
http://image.intervention.io/

詳しい使い方はこちらの方が紹介してくれてます。
https://blog.capilano-fw.com/?p=1574


が、いくつかのサイトで保存方法を調べても画像単体でだけの説明しかされておらず、文字や説明までも含んだ保存方法の説明は見つけられませんでした。


↓ 通常の保存方法。保存はされるが、画像サイズが大きすぎる。

```php
    if($request->hasFile('image')){
    $filenameWithExt = $request->file('image')->getClientOriginalName();
    $filename = pathinfo($filenameWithExt ,PATHINFO_FILENAME);
    $extension = $request->file('image')->getClientOriginalExtension();
    $fileNameToStore = $filename . '_'. time(). '.'.$extension;
    $path = $request->file('image')->storeAs('public/image',  $fileNameToStore);

    } else {
        $fileNameToStore = null;
        }

    $request->user()->drinks()->create([
    'name' => $request->name,
    'body' => $request->body,
    'score' => $request->score,
    'place' => $request->place,
    'image' =>  $fileNameToStore,

    ]);
```

Intervention Imageを使って画像サイズを指定。

```php
    //追加
    use Intervention\Image\ImageManagerStatic as InterventionImage;


    if($request->hasFile('image')){
    $filenameWithExt = $request->file('image')->getClientOriginalName();
    $filename = pathinfo($filenameWithExt ,PATHINFO_FILENAME);
    $extension = $request->file('image')->getClientOriginalExtension();
    $fileNameToStore = $filename . '_'. time(). '.'.$extension;
    $path = $request->file('image')->storeAs('public/image',  $fileNameToStore);

    //追加
　　$image = InterventionImage::make(public_path("storage/image/{$fileNameToStore}"))->fit(1200, 1200);
    $image->save();

    } else {
        $fileNameToStore = null;
        }

    $request->user()->drinks()->create([
    'name' => $request->name,
    'body' => $request->body,
    'score' => $request->score,
    'place' => $request->place,
    'image' =>  $fileNameToStore,

    ]);
```

Copmoserでインストールしたりconfig/app.phpをいじったりはしましたが追加したのは基本的に↓のコードだけ。

```php

　　$image = InterventionImage::make(public_path("storage/image/{$fileNameToStore}"))->fit(1200, 1200);
    $image->save();
```

これだけで、同じ画像、同じアップロード方法で3,500.5 KiB　→　200.1 KiB　とファイルサイズを小さくできました。読み込みも早くなり解決。
備忘録を書く時に使うヤツ 保存用


```
<details><summary></summary><div>

---
</div></details>

```

```
└─
  ├─
  ├─
  ├─
  ├─
  │ ├─
  │ ├─
  │ ├─
  │ ├─
  │ └─
  └─


  ├─
  │ ├─
  │ │ ├─
  │ │ │ ├─
  │ │ │ │ ├─
  │ │ │ │ │ ├─
  │ │ │ │ │ │ └─


#Django

└─project
   ├─api
   │ ├─migrations
   │ │ └─..
   │ ├─__init__.py
   │ ├─apps.py
   │ ├─models.py
   │ ├─serializer.py
   │ ├─urls.py
   │ └─views.py
   ├─project
   │ ├─__init__.py
   │ ├─asgi.py
   │ ├─settings.py
   │ ├─urls.py
   │ └─wsgi.py
   ├─db.sqlite3
   └─manage.py

#Atcoder

└─atcoder
  ├─abc
  ├─arc
  ├─agc
  ├─coppy
  │ ├─a.cpp
  │ ├─b.cpp
  │ ├─c.cpp
  │ ├─d.cpp
  │ └─script.sh
  └─coppy.sh

```
Dockerとimagemagickを使って画像比較してみた

## 初めに

- 最近Dockerを勉強し始めた
- なんか最近先輩が話してた
- 手を動かしながら何かやってみたい

そんなところからメモがてら投稿

imagemagickはいろんなファイルフォーマットの画像を操作したり表示したりするためのソフトウェアらしい
（例えば、画像比較やらresizeやらができるっぽい）

## 今回やることをざっくりと

1. Dockerfileを作成し、ubuntuにimagemagickをインストールしたimage（ubuntu/imagemagick）を作成
3. 適当なディレクトリに画像を２つ置いて、マウントしてコンテナ内で画像比較→結果をホストのディレクトリに保存

今回の状況はこんな感じ
![IMG_0032.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/712635/85769807-380e-61ae-49e3-5313e4dad52b.png)



## ハンズオン

前提として、今回の作業はhoge-dockerディレクトリで行う
各自試すときは自分が作ったディレクトリに適宜置き換えながら進めてほしい
hoge-dockerディレクトリには比較したい画像test1.png、test2.pngのみが入っているものとする

test1.png
![test1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/712635/3f268ffe-b786-dc23-c3d1-d34d250f1835.png)

test2.png
![test2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/712635/0339c15b-7347-8ad3-083d-7a573fc58373.png)


1. Dockerfileの作成

Dockerfileはイメージを作るときの手順書みたいなもの。次のように書く

```Dockerfile
FROM ubuntu

RUN apt-get  update

RUN apt-get -y install imagemagick
```

FROMでベースとなるイメージを指定して
RUNでOSのコマンドを実行し新しいイメージに追加する。
今回はパッケージのアップデートとimagemagickをインストールを記載

2.Dockerfileを実行

次のコマンドでDockerfileを実行し、imageを作成する
-t オプションで新たに作成されるimage名を指定
. は実行するDockerfileの相対パス

```
docker build -t ubuntu/imagemagick .
```
なんやかんやインストールとかがわーッと始まるので終わるまで待機

3.作業ディレクトリをマウントしてコンテナに入る

マウントとは、ざっくりいうとディレクトリ同期
本来コンテナを停止すると中に置いてあるファイルなどももちろん消えてしまうが、
ローカルのディレクトリの一部をコンテナ内にボリュームとして読み込んでしまうことにより
コンテナ内で作ったファイルなどもローカルに共有できるようになる

-v ホスト側のディレクトリパス:コンテナ側のディレクトリパス
で指定する。今回は現在の作業フォルダをコンテナ内の/tmpに同期する

```
docker run -it -v $(PWD):/tmp ubuntu/imagemagick
```

4.imagemagickを用いて画像比較を行う

無事コンテナ内に入れたら

```
which compare
```
などでimagemagickがちゃんとインストールされているかを念のため確認しておく
今回は/tmpを同期先に指定したので、移動してちゃんとhoge-dockerディレクトリが同期されているか確認する

```
cd tmp/
ls
```

これでDockerfile,test1.png,test2.pngがあればOK！
画像比較は次のようにかく
比較したい２つの画像名と、それらの差分を表現してくれる出力ファイルのファイル名をかく
今回はresult.pngとして出力

```
compare test1.png  test2.png result.png
```

終わったら

```
ls
```

でresult.pngができていることを確認
ここまでできればexitしてコンテナから抜ける。
ローカルでもう一度lsしてresult.pngができていれば成功！
![result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/712635/7bc3d8e7-417e-3042-9262-cad47f83ecef.png)

今回はブロックを一個おいたことによる画像の差分をとってこれた
（比較して違う部分が赤くなる）

## 最後に

とりあえず色々基礎を理解するために手を動かしてみたけどもっと改善の余地がありそう
自動テストに組み込むとか色々できるようになりたいなあ。

ここまで読んでいただきありがとうございました。
この記事が何かのお役に立てたなら幸いです。
【Flutter】pub.devに公開したパッケージを複数人でpublish出来るようにする

タイトル通りですが、最近[tapioca](https://pub.dev/packages/tapioca)という動画編集のパッケージのCollaboratorとして運営のお手伝いを行っているのですが、
pub.devに公開したパッケージやプラグインを複数人でpublishしたい場合、以下のよう
な手順を行う必要がありましたので共有します。

# 方法
初回アップロードを行った人が追加でアップロードできる人のアカウントを以下のコマンドで追加する

```bash:
dart pub uploader add hoge@gmail.com
```

参考：
[pub uploader - pub.dev](https://dart.dev/tools/pub/cmd/pub-uploader)

そうすると招待メールが来るので、リンクを踏むと以下のような画面に飛びます。
![invitation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/d3b2de0e-6290-669d-7ae5-d24494e3e32b.png)
ここで`ACCEPT`をクリックして何回か確認ダイアログが出るので許可すると、追加されます。

パッケージのtop画面のuploaderに追加されているのが分かります。
![tuikasareta.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/a57fbdad-5eb3-5240-27b5-0e6dc21b1755.png)

# ブラウザからも行えるようです
`Admin`のタブから`INVITE UPLOADER`をクリックしてgmailのアドレスを追加します。
![burauzakara.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/244c20a1-62b2-b000-a4d6-baa1f51b0177.png)


# おまけ
今までは出てこなかったエラーだが、今回のpublishでハマってしまったのでメモ
`dart pub publish --dry-run`を実行すると以下のようなエラーが発生しました

```bash:
$ pub publish --dry-run
Publishing tapioca 1.0.2 to https://pub.dartlang.org:
|-- .gitignore
|-- .metadata
|-- CHANGELOG.md
|-- LICENSE
|-- README.md
・・・

Package validation found the following error:
* pubspec.yaml allows Flutter SDK version 1.9.x, which does not support the flutter.plugin.platforms key.
  Please consider increasing the Flutter SDK requirement to ^1.10.0 (environment.sdk.flutter)

  See https://flutter.dev/docs/development/packages-and-plugins/developing-packages#plugin
Sorry, your package is missing a requirement and can't be published yet.
For more information, see: https://dart.dev/tools/pub/cmd/pub-lish.
pub finished with exit code 65
```

ネットで調べると以下のように`environment`にFlutter SDKの制約を追加する必要があるみたいでした。

```yaml:pubspec.yaml
environment:
  sdk: ">=2.1.0 <3.0.0"
  flutter: ">=1.12.0 <2.0.0"
```

今回の対応では2.0.0未満としたので、今後はFlutter 2.0対応も行いたいところです
【Unity】スクリプトの変数を変更してもインスペクターに反映されない時

##①変数がpublicだとインスペクター上の値が優先されてしまう
<参考>
https://kan-kikuchi.hatenablog.com/entry/Inspector_Trap

変数をPublicにしてしまうと、スクリプトから変数の値を変更してもインスペクターの値が優先されてしまうとのこと。
上記の記事の通り、変数をprivateにするか、[HideInspector]をつけて

```c#
[HideInInspector]
public int num = 0;

```
とすればインスペクターに数字が表示されないのでスクリプトの変更がすぐ反映されるとのこと。
privateの変数でも[Serialized field]をつけているとインスペクターに表示されてしまうので注意。


## ②スクリプト変更時点でエラーがあるとインスペクターが更新されない

実行しなくても、プログラム変更時点の自動コンパイルでエラーがあるとインスペクターに変更は反映されないようなので注意したい。

自分が今回あたったのはこっちでした。
変数の型を変更してもインスペクターに反映されず。


初期設定ではプログラムに何か変更をすると自動でコンパイル(Auto Refresh)が走るらしい。
Unityのエディタに戻った時に一瞬停止するのはそのせい。

https://kan-kikuchi.hatenablog.com/entry/Auto_Refresh


例えばあるスクリプトで何かの変数に変更を加えたけど、別のスクリプトから変更前の変数を参照しようとしているとか。

自分の場合は銃の残弾的な表示をSliderで作っていた部分を、やっぱりImageのFill Amountでやろうと思ってスライダーを変更したところ、
別のスクリプトからそのスライダーを参照していたのでエラーになってた。
該当スクリプトの変数をインスペクターから変更しようとしてもエラーがある段階ではできない。


いつもは実行時にエラーが起きているので、インスペクターに変数の値の変更が更新されないとか、そういうことはあまりなかったのでちょっと悩んだ。

変更が加わると実行しなくても自動でコンパイルされるのを覚えておくようにします。

自動コンパイル(Auto Refresh)を切るには下記の記事を参考に。

https://farcepeace.wixsite.com/game/single-post/2019/02/21/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E7%B7%A8%E9%9B%86%E3%81%97%E3%81%A6unity%E3%81%AB%E6%88%BB%E3%81%A3%E3%81%A6%E3%81%8D%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AE%E3%83%97%E3%83%81%E3%83%95%E3%83%AA%E3%83%BC%E3%82%BA%EF%BC%88%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%E6%99%82%E9%96%93%EF%BC%89%E3%81%8C%E3%82%82%E3%81%A3%E3%81%9F%E3%81%84%E3%81%AA%E3%81%84
railsコンソールでモデルのカラムとデータ型を確認する

モデルのカラムやデータ型を確認するとき、わざわざデータベースにまで入らず、``rails c``コマンドのコンソールから確認する方法。

```
[User.column_names,User.column_names.map{|x|User.columns_hash[x].type}].transpose
```
もっと単純な描き方はありそうだがとりあえずメモ的に。

``[["id","integer"],["name","text"],["address","text"]]``などカラム名とデータ型の二次元配列が確認できる。
Amazon EFS とは

## 勉強前イメージ

Elastic File System？って感じがする

## 調査

### Amazon EFS とは

Amazon Elastic File System の略で
フルマネージドNFSサービスになります。
また、自動でスケーラブルされるので拡張するために容量の計算などする必要がなくなります。
EFSでは、標準ストレージクラスと低頻度アクセスストレージクラスが提供されており
使用頻度によってより効率的に低価格で利用することが出来ます。

### そもそもNFSってなに？

NFSはNetwork File Systemの略でLinuxなどで利用されるファイル共有システムです。
NFSサーバを立てて、クライアントは公開されたディレクトリをマウントすることで
ネットワーク上のファイルシステムをローカルなファイルシステムと同等に操作することができます

### Amazon EFS の特徴

- スケーラブル

ファイルの追加や削除に合わせてストレージ容量が自動で拡張・縮小されます。
使用分だけの課金になります。

- 高耐久性

複数のAZで冗長化されており、高い耐久性があります。
同一リージョンであれば、異なるAZからでもアクセスは可能です。

- パフォーマンス

複数のサーバに分散しているので、複数のEC2から同時にアクセスがあっても処理できるスケーラビリティがあります。
また要件に合わせてパフォーマンスを設定することが出来ます。

![1Amazon EFS - Google Chrome 2021-03-11 00.36.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/c9e6b142-311b-65ec-68e1-ce5a17b62c5d.png)


- パフォーマンスモード
	- 汎用
		- デフォルトのモード
		- ユースケース : web配信環境やホームディレクトリなど
	- 最大 I/O
		- ファイルのレイテンシーが少し長くなるが、高いレベルの集計スループットと 1 秒あたりの操作にスケールできる
		- ユースケース : ビックデータ解析など

### 他のストレージサービスとの違い

他にもs3やEBSなどありますが、違いを確認します。

#### ストレージタイプ

- EFS : ファイル
- s3 : オブジェクト
- EBS : ブロック

### 耐久性や可用性

- EFS : 複数AZで冗長化
- s3 : 3箇所以上のAZで冗長化
- EBS : 単一AZ

### 費用

デフォルトの設定です。

- EFS : 0.36USD/GB
- s3 : 0.025USD/GB
- EBS : 0.12USD/GB

## 勉強後イメージ

NFSを自分で作ったことないからなんとなくしっくりこない。
調べた内容はなんとなくわかったけど、それ以上のことがわからん。
ただ、ストレージサービスって言ってもいろいろあるんだなぁ...

## 参考

- [◆NFSとは](http://atnetwork.info/tcpip1/tcpip195.html)
- [Amazon Elastic File Systemについて調べてみました。](https://recipe.kc-cloud.jp/archives/11974)
- [AWS再入門 Amazon Elastic File System編](https://dev.classmethod.jp/articles/relay-re-introduction-2019-efs/)
- [Amazon EFSとAmazon S3の違い](https://www.acrovision.jp/service/aws/?p=2630)
S3をWebサーバーにしてコンテンツを公開する⑤（CloudFront署名付きCookie編）

S3をWebサーバーにして静的コンテンツを公開する方法を紹介します。

1. [S3パブリック編](https://qiita.com/morikaz/items/8d196844aed38d0d8d0b)
2. [S3署名付きURL編](https://qiita.com/morikaz/items/0d9d69e21e0863204b8e)
3. [CloudFrontパブリック編](https://qiita.com/morikaz/items/04c053ead497e2a7c86c)
4. [CloudFront署名付きURL編](https://qiita.com/morikaz/items/f3159562caa133916bce)
5. [CloudFront署名付きCookie編](https://qiita.com/morikaz/items/741fc1073dff746f7089)　←コレ！

# 手順

今回の手順は、[CloudFront署名付きURL編](https://qiita.com/morikaz/items/f3159562caa133916bce)の続きで実施します。

## Cookieの設定

`aws cloudfront sign`コマンドで生成した署名付きURLのパラメーターをCookieに設定します。

| Cookie　Name | Cookie Value |
| --- | ---
| CloudFront-Expires | 署名付きURLのExpires |
| CloudFront-Key-Pair-Id | 署名付きURLのKey-Pair-Id | 
| CloudFront-Signature | 署名付きURLのSignature |

ただ署名付きURLのパラメーターの接頭辞として`CloudFront-`がついてるだけですね。
このCookieが設定されていれば、署名付きURLのクエリパラメーターがなくても、プライベートコンテンツにアクセスできるということです。

■署名付きURLの場合
https://d168j73yp42rht.cloudfront.net/private/index.html?Expires=XXXXXXXXXX&Key-Pair-Id=XXXXXXXXXX&Signature=XXXXXXXXXX

署名付きCookieの場合
https://d168j73yp42rht.cloudfront.net/private/index.html
※CookieでCloudFront-Expires、CloudFront-Key-Pair-Id、CloudFront-Signatureの指定が必要

以上です。
間欠動作でラズベリーパイの消費電力を削減

# はじめに
ラズパイの消費電力を[「slee-Pi3」](https://mechatrax.com/products/slee-pi/)を使った間欠動作でどのくらい削減できるか検証します。

**結論**
1日当たりの消費電力量は、8分待機の間欠動作（1サイクル10分）で約79%削減、58分待機の間欠動作（1サイクル60分）で約97%削減されます。

詳細は、以下参照ください。

slee-Pi3はラズパイ専用の電源管理/死活監視モジュールモジュールで、以下のようにラズパイにスタックして使用します。
![slee-pi3_on_raspberrypi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146895/944fdb2e-8c92-eaa3-564d-9654bf68ddb8.png)

slee-Pi3は搭載RTC（Real Time Clock）によるラズパイの日時指定起動ができるため、**間欠動作（定期的なON/OFF動作）により低消費電力での運用**ができます。

例えば、「1時間に1回のペースでログ収集する」等の定時的な運用の場合には非常に効果があります。

# 計測器

[zmart デジタル電圧電流電力量計](https://amzn.to/3D34C01)のワットチェッカーを使用して計測します。
0.01Whから積算電力値を計測できます。

# 消費電力の計測
消費電力の変化を、以下の簡易的に以下のように切り分けて考えます。

1. 起動時
2. 通常稼働時(電源ONしているだけでアプリ等は起動していない状態)
3. アプリ実行時
4. シャットダウン時

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146895/4ed4510d-7a0c-d442-6731-c1815ac88876.png)




**説明**
・起動からシャットダウンするまでの時系列と消費電力を簡易的に図示しています。
　※実際の消費電力はこんなきれいな長方形にはなりません。
・起動時とシャットダウン時は消費電力は大きいですが、時間が短いため消費電力量（消費電力と時間の積）としては少ないです。
・アプリ実行時はCPU負荷が高くなるので、通常稼働時よりも消費電力量が多くなります。

次章以降で「起動時」「通常稼働時」「シャットダウン時」をもとに間欠動作での消費電力量を概算してみます。
　※アプリ実行時も含めた消費電力については別記事にて紹介予定です！

# 「起動時」「通常稼働時」「シャットダウン時」の消費電力量を測定
ワットチェッカーを使って計測した結果は以下のとおりです。
ラズベリーパイは、RaspberryPi 3B、OSはRaspberryPi OSを使用しています。
また電源は12VのACアダプタを使用しています（slee-Pi3経由でラズパイに供給）

|ラズパイの状況|消費電力量|
| --- | --- | --- |---|
|起動時|0.04Wh|
|通常稼働時（1分あたり）|0.045Wh|
|シャットダウン時|0.01Wh|

# 間欠動作時の消費電力量について

「起動時・通常稼働時・シャットダウン時」とさらにslee-Pi3の機能によって実現できる「待機時（ラズパイスリープ時）」の状態を組み合わせて「1サイクル」とし、1サイクルあたりの消費電力量を計算します。今回、起動時とシャットダウン時の所要時間は合わせて約1分くらいでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146895/ad0a2ab8-a004-2149-595d-e495fd8bc7b5.png)

待機時の電力量ですが、ラズパイ停止状態（電源OFF状態）でslee-Pi3+ラズパイに流れる消費電流は、何と**10μA以下**です。電流が小さすぎてワットチェッカーにて電力量の計測できなかったため便宜的に消費電流を10μAとし、待機時消費電力を120μW（1分あたり消費電力量0.000002Wh）として考えます。

参考：https://github.com/mechatrax/slee-pi3/wiki/ハードウェア#2-仕様


# 間欠動作なしの連続稼働

24時間（1440分）の消費電力量 = 1分あたり消費電力量 × 1440分
　　　　　　　　　　 = 0.045Wh × 1440分 = 64.8Wh

# 1分通常稼働と8分待機での間欠動作

1サイクル（起動 + 1分通常稼働 + シャットダウン + 8分待機）の消費電力量は
消費電力量：0.04Wh + 0.045Wh + 0.01Wh + 0.000002Wh × 8 = 0.0950Wh
※起動時間とシャットダウン時間の合計は1分としてます

24時間（144サイクル）の消費電力量：0.0950Wh × 144 = **13.6802Wh**

# 1分通常稼働と58分待機での間欠動作
1サイクル（起動 + 1分通常稼働 + シャットダウン + 58分待機）の消費電力量は
消費電力量：0.04Wh + 0.045Wh + 0.01Wh + 0.000002Wh × 58 = 0.0951Wh

24時間（24サイクル）の消費電力量：0.0951Wh × 24 = **2.2827Wh**

#間欠動作時の消費電力の効果

間欠動作は待機時間が長ければ長いほど効果が見込めます。ラズパイの連続稼働が不要で、バッテリーなどでの運用が必要な方の参考になれば幸いです。

#変更履歴

間欠動作時における1分あたりの待機時消費電力の計算が間違っておりました。。。
以前は0.0072Whとしておりましたが、現状の0.000002Whが正しい情報です。
誤った情報を発信してしまい大変申し訳ありませんでした。。。
【JDLA E資格】2021#1合格体験記

#はじめに
JDLA E資格試験（JDLA Deep Learning for ENGINEER 2021#1）の合格体験記の記事です。

なお、E資格試験に関する有益な情報、各パートの具体的な解説については、下記記事にまとめました。
そちらをご覧ください。
[E資格試験に関する私の投稿記事リスト][link-1]
[link-1]:https://qiita.com/fridericusgauss/items/5a97f2645cdcefe15ce0


#試験結果
合格でした。
受験した感触は不合格濃厚でしたが、正答率を見る限り、戦略は良かったようです。
Twitter等でお祝いのメッセージをくださった方、ありがとございました。

![_20210311_221154~2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1130003/7ff696d2-ed7c-662a-b2ad-4d88714571eb.jpeg)

下記が合格通知からの抜粋です。
>JDLA E資格2021#1
>■合否
>合格
>
>■分野別の得点率
>応用数学：100 ％
>機械学習：92 ％
>深層学習：66 ％
>開発環境：83 ％

内訳詳細は非公開ですが、__全体の正答率は約8割__と推測しています。

経験的に、出題分量の内訳イメージは下記の通りです。

* 応用数学パート：10%
* 機械学習パート：35%
* 深層学習パート：50%
* 開発・運用環境パート：5%

よって、

```math
\begin{align}
&10\%\times 1.00 + 35\%\times0.92 + 50\%\times0.66 + 5\%\times0.83\\
&=10\%+32\%+33\%+4\%\\
&=79\%
\end{align}
```

となり、想定の合格ラインの7割は越えていると推測しています。

この戦略については、下記記事にて解説しています。
[E資格試験の合格ラインと合格のための戦略][link-2]
[link-2]:https://qiita.com/fridericusgauss/items/98497e96c03d99cba327


#感想
十分に勉強時間が確保できなかったため、深層学習パートが覚えきれていない部分が多すぎて、不合格濃厚だと思っていました。
一方、結果は意外と正答率が高く、しかも戦略通りの正答率配分でした。

また、試験結果通知はこれまでは約1週間で届いていたようですが、今回は「3週間以内に届く」とのことで、__本当に3週間ギリギリに届きました__。
今後の目安にしてください。


#今後
合格ラインを突破することは達成しましたが、本来の目的である深層学習を理解することは道半ばです。
よって、夏に向けて勉強し、受験する予定です。

その勉強過程で整理したことをQiitaに投稿したいと思います。
一部、すでに投稿しているので、ぜひご覧ください。
[E資格試験に関する私の投稿記事リスト][link-1]
[ AWS ] EC2の本番環境で背景画像が表示されない問題

今回、制作したポートフォリオを本番環境で使おうとしたときに `背景画像がまっ白`な事に気づき、おかしいと思い調べを進めていきました。
結果的に表示された方法を備忘録として書いていきたいと思います。
　
　

##本番環境ではコンパイルされるのが原因。
・本番環境では画像は全てpublic配下から読み込まれるようになる。
・コンパイルされないように先に移動させるのがベスト。してしまったら一度iamgesを複製してフォルダの名前のコピーと書かれた部分を消してiamgesという名前にに編集。
・新たにpublic配下に加える。
・コンパイルしてしまったものは過去の遺物として闇に葬りましょう。
(dog.jpg5349535363296969237626.jpgとあられもない姿にされて読み込まなくなる)
自分の場合、コンパイルされたcssは一応別のディレクトリに保管しました。
なのでstylesheet配下のcssをいじっています。(これできちんと読み込んでいますが、これが正解かは分かりません。)
#解決策(例)

本来であれば**asset_path**(アセットパイプラインのヘルパーメソッド)を使いますが、今回は。public/imagesを置いているので、
**image_path** (pathなのでimagesではなく、image)
これはCSSのファイル内で使うことによって、public/imagesにある画像にパスを通すことができる。


まず初めに

```config/environments/production.rb
　　config.assets.compile = trueに変更    #元々はfalse
```
　

次に**Nginx**の中の記述を

```
  location ^~ /images/ {   　　⇦#imagesに変更。元々はassets
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }
```

　　


次に**user.css.erb**を手動で作成。
これを作ることによってRubyの記述ができるようになりviewで見えるようになる。

```user.css.erb
form#new_user.new_user {
  padding: 10%;
  background-image: url("<%= image_path('field.jpg') %>")　 #ここの記述では必ずpathを使って指定してあげます。
}
```

上記の記述では必ず**path**を使って画像を指定してあげます。
　　

こちらのcssは

```user.css
form#new_user.new_user {
  padding: 10%;
  background-image: url("/images/field.jpg")
}
```
こちらも同様に画像の指定をします。
`(publicの記述はいらない。自動で読みこむものなのでその下のファイル名を書く。)`



###まとめ
今回かなり色々調べてトライ＆エラーしまくりましたが、自分はこの解決方法に至りました。
これらの記述を終えると反映されているはずです。
DatadogのAWS Integrationでフィルタリングルールを使った話


# TL;DR
* [DatadogのAWS Integration](https://docs.datadoghq.com/integrations/amazon_web_services/?tab=roledelegation)を利用する際に、AWSのタグを使ってフィルタリングすることが出来る
  * 例えば、`Environment:production` タグを持つAWSリソースだけ監視に追加することが出来ます
* EC2やLambda以外のリソースはDatadogのGUI上からではフィルタリング設定できないので、APIを叩きましょう
  * ref: https://docs.datadoghq.com/ja/api/latest/aws-integration/
* terraformのバージョンを最新(2.21以上)にすればコード管理もできます

# はじめに
DatadogのAWS Integrationを使ってAWS環境を監視する必要が発生しました。
しかし、該当のAWS環境では本番用のリソースとステージング用のリソースが稼働しています。

この状態で以下を達成しようとした結果を記載します。

* DatadogのAWS Integrationだけでどうにか監視したい
* 監視対象は本番用のリソースだけにしたい

2021年の1月末から対応していたのですが、その時はDatadog公式のドキュメントやインターネット上の資料を探しても
GUI上から設定できるEC2やLambdaリソースのフィルタリング方法しか見つけれなかった(そもそも機能としてなかった？)ため、メモとして記載しています。

# やっていく
## 前提
以下を前提としています。

* DatadogのAWS Integrationが有効になっていること
* 各種AWSリソースには事前にタグが付与されていること
  * 例: `Environment: production` 

## curlで実行する場合
全ては[Datadog公式](https://docs.datadoghq.com/ja/api/latest/aws-integration/)に書いてあるとおりですが・・・

```bash
### Environment:productionタグを持つRDSを監視したい場合
$ curl -X POST "https://api.datadoghq.com/api/v1/integration/aws/filtering" \
-H "Content-Type: application/json" \
-H "DD-API-KEY: datadog-api-key" \
-H "DD-APPLICATION-KEY: datadog-application-key" \
-d @- << EOF
{
  "account_id": "YOUR_AWS_ACCOUNT_ID",
  "namespace": "rds",
  "tag_filter_str": "Environment:production"
}
EOF
```

複数のリソースに対して実行したい場合は、それぞれのリソースに対してPOSTしてあげてください。

## Terraformで実行する場合
[Terraformのドキュメント](https://registry.terraform.io/providers/DataDog/datadog/latest/docs/resources/integration_aws_tag_filter
)に書いてあるとおりですが・・・

```bash
###  Environment:productionタグを持つRDSを監視したい場合
resource "datadog_integration_aws_tag_filter" "rds" {
  account_id     = "YOUR_AWS_ACCOUNT_ID"
  namespace      = "rds"
  tag_filter_str = "Environment:production"
}

###  Environment:productionタグを持つALBを監視したい場合
resource "datadog_integration_aws_tag_filter" "alb" {
  account_id     = "YOUR_AWS_ACCOUNT_ID"
  namespace      = "applcation_elb"
  tag_filter_str = "Environment:production"
}
```

フィルタリングしたいAWSリソースの分だけ記載しましょう。

なお、`datadog_integration_aws_tag_filter` は2021/2/10に[リリース](https://github.com/DataDog/terraform-provider-datadog/releases/tag/v2.21.0)されたv2.21から使えるようです。
忘れずに最新のバージョンを使うように指定しておきましょう。

例えば、以下のような感じです。

```bash
### main.tf
provider "datadog" {
  version = "~> 2.21.0"
}
```

# さいごに
`custom` リソースも定義できるよ、とのことですが、こちらはまだ試せていません。
おそらく、 [こちら](https://docs.datadoghq.com/ja/api/latest/aws-integration/)に記載の無い`ecs` や `elasticache` などをフィルタリングできるのかもしれません。

本記事は、自力で見つけたのではなくDatadogのサポートに問い合わせて教えてもらった内容になります。
Datadogのサポートさんにはお世話になりました・・・
AI実務経験者がE資格をとった話

# はじめに
この記事はデータ分析やAIの開発業務経験があるエンジニア（元コンサルタント）がE資格を取るまでに
どのようにして資格をとったのかをまとめた記事になります。

AI実装未経験の方から、実務経験はあるもののE資格をとろうと思っている方はぜひご覧ください。

# 簡単なバックグラウンド
社会人経験がもうすぐ6年になろうとしていて、
Webエンジニア→AIコンサルタント→データサイエンティストというような経歴を持つ人間です。
AI関連は2社目のAIコンサルタントから本格的に携わるようになりました。
資格はIT系だと応用情報、AWSソリューションアーキテクトアソシエイト、G検定を持っています。

# 目的
未経験者がAI開発業務に携わりたいという気持ちで資格をとろうというモチベはわかると思うのですが
ではなぜ今回私のような経験者でもとろうと思ったかを簡単に述べます。

AI業務に携わり、実際に開発経験はありましたが、
今は幸いにもscikit-learn, PyTorch, Tensorflowなど便利なライブラリが用意されていて
細かい中身はなんとなくでそこまで詳しくはわかってないけどなんか予測できちゃったみたいな感じで使っていました。
また、AI業務に携わるものの、まだ狭い領域（教師あり学習、特にその中でも自然言語処理）がメインで、
クラスタリングや強化学習といった分野ももっと知ってアイディアの幅を広げなければと感じていました。

また、自然言語処理は自分の中では強い方かなぁと思いつつも、
最近の技術（LTMS, BERTなど）に追えなくなってきていました。
名前だけ知ってるけど実際なんなんっていうような感じでした。

# 簡単なタイムライン

- 2020年5月: 講座を受け始める。
- 2021年1月: 講座を修了
- 2021年2月: E資格受験

# 講座について
E資格は事前に指定された講座（いくつか選べる）を修了しないと受ける資格はもらえない試験となっています。
私は会社で割引が効くということと合格率94.4%という数字にも信頼しつつ、[AVILEN](https://avilen.co.jp/)さんの講座を受けました。
講座は以下のようなコンテンツがあります。

- Deep Learningの講座: 動画の講座を閲覧して学習する
- コーディング課題: 動画の講座から学んだ知識からコーディングの課題
- プロダクト課題: 課題設定を自由に決めてAIモデルを自身でコーディングして実装
- 修了試験: 講座の内容を総括した試験

勉強はさぼってた時期もありましたが、やる気があるときは平日でも20分〜30分と時間を決めてやっていました。
あまり一日に多く時間を割こうとするとやらなきゃという使命感に追われちゃうのと負担になるかなと思い、
時間をかけてちょっとずつすすめるやり方が自分にはあっていました。

講座自体は資料に記載ミスがあったりと改善点もありましたが個人的にはE資格の内容をよくカバーできていて良い講座だと感じました。
わからないところはSlackでいつでも質問もできますし、なにか困ったことがあればメンターに相談することができます。

# 学習方法
- 講座が提供しているサービスをフル活用
AVILENさんの動画・資料をひたすら見返したり、演習問題を繰り返し実施しました。
分からなかった問題を保存できるシステムになっているので
特に分からなかった問題は資料を見返したりして理解を深めました。
また、公式例題の問題及び解説も掲載させていただいたので
特にこのあたりは解けた問題も繰り返し見直しました。

- 問題集を解く
公式で出ている[問題集](https://book.impress.co.jp/books/1118101176)を解けない問題がなくなるまで繰り返し実施しました。
値段が少し高いのと誤植が多いという問題はありましたが、良い理解の深まりになりました。

- 時には暗記
まだ自分が未熟ということもあるのですがすべてを理論的に理解することができませんでした。
特に強化学習のところは数学的な内容も多く、公式は結構丸暗記してしまいました。
人にもよると思いますがすべて理解するのは難しいということもあるので
まだここは自分には難しいなってところは暗記で割り切るのも一つの手です。

# おわりに
資格は合格するまでが大事ですが、
勉強するだけでもだいぶためになったと思います。（とはいえ落ちてたらもう一度受けてたと思いますが）
AI・データ分析を今後も極めていきたいので
実践の業務に加えなんかやっていきたいなとは思ってます。（Kaggleとか）
Displayプラグインの雛形

【[rviz2プラグインの作り方 トップページへ](https://qiita.com/Kotakku/items/d3510c1ca505b4c0aa1e)】

# トピックなし
AxesやGridのようにトピックの購読なしで動作するプラグイン

```display_template.hpp
#ifndef SAMPLE_RVIZ_PLUGINS_DISPLAY_TEMPLATE_HPP
#define SAMPLE_RVIZ_PLUGINS_DISPLAY_TEMPLATE_HPP

#include <rviz_common/display.hpp>

namespace sample_rviz_plugins
{

class DisplayTemplate : public rviz_common::Display
{
    Q_OBJECT
public:
    DisplayTemplate();

    ~DisplayTemplate() override;

    void onInitialize() override;
    void update(float dt, float ros_dt) override;

protected:
    void onEnable() override;
    void onDisable() override;

private Q_SLOTS:
    // void updateShape();

private:
};

}

#endif // SAMPLE_RVIZ_PLUGINS_DISPLAY_TEMPLATE_HPP
```

```display_template.cpp
#include "display_template.hpp"

#include <rviz_common/display_context.hpp>

namespace rviz_default_plugins
{

DisplayTemplate::DisplayTemplate()
    : Display()
{
}

DisplayTemplate::~DisplayTemplate() = default;

void DisplayTemplate::onInitialize()
{
}

void DisplayTemplate::onEnable()
{
}

void DisplayTemplate::onDisable()
{
}

void DisplayTemplate::update(float dt, float ros_dt)
{
    (void)dt;
    (void)ros_dt;
    
}

}

#include <pluginlib/class_list_macros.hpp>
PLUGINLIB_EXPORT_CLASS(sample_rviz_plugins::DisplayTemplate, rviz_common::Display)
```

# トピックあり
Odometry,Pose,Pathのようにトピックを購読して動作するプラグイン

```topic_display_template.hpp
#ifndef SAMPLE_RVIZ_PLUGINS_TOPIC_DISPLAY_TEMPLATE_HPP
#define SAMPLE_RVIZ_PLUGINS_TOPIC_DISPLAY_TEMPLATE_HPP

#include <std_msgs/msg/float32.hpp>
#include <rviz_common/ros_topic_display.hpp>
#include <mutex>

namespace sample_rviz_plugins
{

class TopicDisplayTemplate
    : public rviz_common::RosTopicDisplay<std_msgs::msg::Float32>
{
    Q_OBJECT
public:
    TopicDisplayTemplate();
    ~TopicDisplayTemplate() override;

protected:
    void onEnable() override;
    void onDisable() override;
    void onInitialize() override;
    void processMessage(std_msgs::msg::Float32::ConstSharedPtr msg) override;
    void update(float wall_dt, float ros_dt) override;
    void reset() override;

    std::mutex mutex_;
private:
};

}

#endif // SAMPLE_RVIZ_PLUGINS_TOPIC_DISPLAY_TEMPLATE_HPP
```

```topic_display_template.cpp
#include "topic_display_template.hpp"

#include <rviz_common/display_context.hpp>

namespace sample_rviz_plugins
{

TopicDisplayTemplate::TopicDisplayTemplate()
{
}

TopicDisplayTemplate::~TopicDisplayTemplate()
{
}

void TopicDisplayTemplate::onInitialize()
{
    RTDClass::onInitialize();
}

void TopicDisplayTemplate::update(float wall_dt, float ros_dt)
{
    (void)dt;
    (void)ros_dt;
    
}

void TopicDisplayTemplate::processMessage(std_msgs::msg::Float32::ConstSharedPtr msg)
{
    std::lock_guard<std::mutex> lock(mutex_);
    
}

void TopicDisplayTemplate::reset()
{
    RTDClass::reset();
}

void TopicDisplayTemplate::onEnable()
{
    subscribe();
}

void TopicDisplayTemplate::onDisable()
{
    unsubscribe();
}

}

#include <pluginlib/class_list_macros.hpp>
PLUGINLIB_EXPORT_CLASS( sample_rviz_plugins::TopicDisplayTemplate, rviz_common::Display )
```
VSCodeを透過させよう+α

# 単色な背景に飽きた！
***そんな貴方に[GlassIt-VSC](https://marketplace.visualstudio.com/items?itemName=s-nlf-fh.glassit)***

この拡張機能はウインドウ本体を半透明にすることができます

### 注意
使用可能な環境がMarketplaceに書かれてるので確認してください

### ショートカットキー
| キー | 効果 |
|:-----------|------------:|
| ctrl + alt + z | 透明度上昇 |
| ctrl + alt + c | 透明度低下 |

# 応用法
* 推しの配信を裏に配置させて見ながらコーディングする
* 好きな画像をスライドショー形式で流しながらコーディングする
* TweetDeckを裏に配置してTLを追いながらコーディングする
[AWS] Lambda + API Gateway でサーバーレスWeb APIを作る ②Amazon API Gateway HTTP API篇

# この記事は

[[AWS] Lambda + API Gateway でサーバーレスWeb APIを作る ①Lambdaファンクション篇](https://qiita.com/akumachan/items/1b6e36ec6dc3a7437934)の続きです。

# HTTP APIとREST API
Amazon API GatewayではHTTP APIとREST APIという2種類のAPIを作成できます。
違いは公式を見てみてください。
[HTTP API と REST API 間で選択する](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/http-api-vs-rest.html) 

- HTTP APIの方が**安価**
- REST APIの方が**現状では機能が多い**
- **OIDC/OAuth 2.0認証**をサポートしているのはHTTP APIだけ

 

今回のゴールはどちらの方法でも達成できそうです。今回はHTTP APIで実装してみます。


# 今回の実装
今回は、API GatewayのHTTP APIを使って前回作成したLambdaファンクション`introduceMyself`へのHTTP経由での入口を作成します。

## HTTP APIを作成
Amazon API Gatewayの画面で`Create API`を押す。
![Create API](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542817/bbacb8f9-6b96-6221-cdfa-e621bbba577a.png)

HTTP APIの`Build`を押します。
![Build](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542817/867f8f67-5833-ca65-e88a-d69c75a3dd18.png)

- `Add integration`ボタンで統合先にLambdaを指定、呼び出したい`Region`と`Lambda Function`を選択します。（複数追加可能）
- API名を決めます。
- `Next`ボタンを押します。

![Configure integrations](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542817/ae8bf223-556d-2ce5-f201-2be2d1e53f99.png)

`Add route`でルートを追加します。メソッド、リソースパス、統合ターゲット（呼び出すファンクション）を指定します。
今回は`introduceMyself`にGETとPOSTメソッドのルートを作成します。
入力したら`Next`を押します。

![Configure routes](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542817/fea908ec-3a23-b1cc-e251-5abce43d713b.png)

次にデプロイするステージを決めます。
本番環境は`prod`、開発環境は`dev`といったようにデプロイする環境を分けることができます。
今回は`dev`という名前のステージを追加してデプロイします。
`Auto-deploy`をオンにしておくとAPIの修正後に手動でデプロイボタンを押さなくてもデプロイされます。

![Define stages](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542817/6bb251b8-ee08-f25f-c684-7ec5e2e42109.png)

内容を確認して`Create`ボタンを押します。

![Create](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542817/18cef670-7228-d6d5-6ae6-600c7b4a0e97.png)

## APIを呼び出してみる
REST APIではコンソール内でAPIのテストが実行できますが、HTTP APIではできないようなのでGETとPOSTでそれぞれAPIを呼び出してみようと思います。

### GET
```
https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/development/introduce/myself?name=Akumachan&age=10031
```
![GET TEST](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542817/faa7ab31-a0ec-4cec-4685-70e38df0f4a4.png)

### POST

```sh
curl -X POST -H "Content-type: application/json" -d '{"name": "Akumachan", "age": "10033"}' https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/development/introduce/myself
```

![Screen Shot 2021-03-11 at 23.37.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542817/fd85fd06-3d71-d175-4480-3ed529e605d1.png)

呼べました！
ESP32にFTPでファイルを渡す

ESP32に大きなファイルを渡したい場合に、ESP32内にFTPサーバとして立ち上げておけば、Windowsのエクスプローラからアップロードやダウンロードが楽になります。

ソースコードをGitHubに上げておきました。

poruruba/SimpleEsp32FtpServer

https://github.com/poruruba/SimpleEsp32FtpServer

#シンプルなESP32用FTPサーバ

ESP32内にFTPサーバを立ち上げますが、非常にシンプルなものにしています。

・1つのファイルしか保持できません。
・フォルダは作れません。
・揮発なので、リブートすると消えます。
・Windowsのエクスプローラしか試していません。

※WinSCPで試してみましたが、ファイルを直接編集しようとしたときだけ、ソケットを多重で開こうとして切断されてしまいました。

以下の方が作られたものをほぼそのまま使っています。（ありがとうございました！）
SDを前提としていましたが、上記の通り非常にシンプルにして、メモリだけで実現するようにしています。

robo8080/ESP32_FTPServer_SD

https://github.com/robo8080/ESP32_FTPServer_SD

#使い方

```cpp:src/main.cpp
#include "ESP32FtpServer.h"
FtpServer ftpSrv;
```

WiFiに接続した後に、

```cpp:src/main.cpp
  configTzTime("JST-9", "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");
  ftpSrv.begin("esp32","esp32", buffer, sizeof(buffer));
```

ポイントは以下のところです。

```cpp:src/main.cpp
void    begin(String uname, String pword, unsigned char *p_buffer, unsigned long length);
```

受け付けるユーザ名、パスワードに加えて、FTPで送受信するデータのバッファと最大サイズを指定しています。

あとは、loop()の中で、

```cpp:src/main.cpp
  FTP_F_STATUS status = ftpSrv.handleFTP();        //make sure in loop you call handleFTP()!!   
  if( status != F_IDLE ){
    Serial.print("status="); Serial.println(status); Serial.println(ftpSrv.file_name); Serial.println((char*)buffer);
  }
```

FTP_F_STATUS は、以下の種類があります。

  ・F_IDLE：特に変化なし
  ・F_RETRIEVED：ファイルが取得された
  ・F_STORED：ファイルの受信完了
  ・F_DELETED：ファイルが削除された
  ・F_RENAMED：ファイル名が変更された

上記の状態となったときに、任意の処理ができるようにしています。

また、FTPクライアント側にファイルを渡したい時には以下を呼び出します。
beginで指定したバッファに、返したいデータを設定した後に呼び出します。

```cpp:src/main.cpp
void setFile(const char *fname, unsigned long size);
```

#Windowsのエクスプローラで開く

Windowsのエクスプローラのアドレスバーに以下を入力すれば、接続できます。

```
ftp://ユーザ名:パスワード@IPアドレス/
```

ユーザ名とパスワードは、ftpSrv.begin()に指定したものです。
IPアドレスは、ESP32のIPアドレスです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/ad0e04c9-8a11-308f-f4f4-21da0c0b3e51.png)

#終わりに

ちょっと不安定かな。。。

以上
【WSL2 Docker】 「docker-compose up」にてPorts are not availableエラーが発生したとき

# 概要
* docker upを実行したときに

```linux
ERROR: for app  Cannot start service app: Ports are not available: listen tcp 0.0.0.0:50080: bind: An attempt was made to access a socket in a way forbidden by its access permissions.
ERROR: Encountered errors while bringing up the project.
```

そのエラーが出たときに調べたことと対応について記録します。

# 本文
## 調べたこと
原因についていくつかの候補が上がりました。

### Portが埋まっている
Portがほかで使われている可能性を考え、`netstat -oa`で確認しましたが、確認ができませんでした。

## 対応
docker-compose.ymlに記載したPort番号を変更しました。50080で最初設定しており、50081に変更しても結果が変わらなかったため、カーネルに占有されていることが候補としてあがりました。
以下に記載した資料によると、49152以降の番号を使うとエフェメラルポートと被りそうです。
なので、初期状態から49152よりも前のPort番号を使えばよさそうです。


# 参考
* [docker-compose up 時にPorts are not available が出る](https://blog.fits-inc.jp/2020/10/17/docker-compose-up-%E6%99%82%E3%81%ABports-are-not-available-%E3%81%8C%E5%87%BA%E3%82%8B%EF%BC%88%E8%A7%A3%E6%B1%BA%E6%B8%88%EF%BC%89/)
「問題解決力を鍛える!アルゴリズムとデータ構造」とLeetCodeで学ぶ再帰と動的計画法(メモ化)

# 再帰とメモ化

[問題解決力を鍛える!アルゴリズムとデータ構造](https://amzn.to/3v9j0A1)
というアルゴリズムとデータ構造を学ぶのに良い本があります。

LeetCodeの問題を解いていた時に、この本の中で解説されていた例とすごく被っている内容があったので、記事にしてみようと思いました。


# 問題

[1137.  N-th Tribonacci Number](https://leetcode.com/problems/n-th-tribonacci-number/)

難易度はEasy。
再帰の入門にうってつけです。

[問題解決力を鍛える!アルゴリズムとデータ構造](https://amzn.to/3v9j0A1)の4章の解説にもある通り、再帰関数のテンプレートは

```
(戻り値の型) func(引数){
	if(ベースケース){
		return ベースケースに対する値;
	}
	func(次の引数)
	return 答え
}
```
> 問題解決力を鍛える!アルゴリズムとデータ構造 第4章 設計技法(2):再帰と分割統治法

といったものです。


今回解く問題は、

トリボナッチ数列Tnは次のように定義される。

T0 = 0, T1 = 1, T2 = 1, そして n >= 0 で Tn+3 = Tn + Tn+1 + Tn+2 となる。

nが与えられたとき、Tnの値を返す。

という内容です。


では、こちらをPythonでかつ再帰で解いてみましょう。

```
class Solution:
    def tribonacci(self, n: int) -> int:
        if n == 0:
            return 0
        elif n == 1 or n == 2:
            return 1
        return self.tribonacci(n-1) + self.tribonacci(n-2) + self.tribonacci(n-3)
# Time Limit Exceeded
```


しかし、これだとnが 30の時に時間切れとなり、正解とは認められません。

これは再帰で同じ処理が重複し、関数の呼び出し回数がとてつもない回数になっているためです。

ではこれを解決してみましょう。

```Python3
class Solution:
    def tribonacci(self, n: int) -> int:
        memo = collections.defaultdict(int)
        memo[0], memo[1], memo[2] = 0,1,1
        for i in range(3,n+1):
            memo[i] = memo[i-1] + memo[i-2] + memo[i-3]
        return memo[n]
# Runtime: 28 ms, faster than 80.87% of Python3 online submissions for N-th Tribonacci Number.
# Memory Usage: 14.3 MB, less than 13.79% of Python3 online submissions for N-th Tribonacci Number.
```

この解法では一度計算したものを`memo`という変数に保存し、仮に計算済みであれば関数を呼び出すのではなく値を直接返すようにしています。これをキャッシュといい、高速化するための手法です。

どうでしょうか。

これ以外にも問題を解決するための思考法などが満載の素晴らしい本なので、[問題解決力を鍛える!アルゴリズムとデータ構造](https://amzn.to/3v9j0A1)を買って実際に勉強されてみるといいかと思います。

今回はここまで。お疲れ様でした。
Windows 圧縮コマンド（Powershell）いろいろ

Windows 圧縮コマンド何通りかやったけど制約が多い。。。
Powershell の標準 `Compress-Archive` だと2GB以上のファイルあるとエラー。。。
いくつか試したけど他プロセスで使ってるファイルは圧縮するとエラー出てしまう。。。
圧縮前にコピーしてそれに対して圧縮すればよいけどサイズ大きいとつらいかも。。。

## Shell. Application 利用
サイズの制約がなく追加もできるので使い勝手はよさそう
ただ非同期実行になるので終了待ち、エラーハンドリングが難しい。。

```PowerShell
$filepath = "C:\aaa\bbb\ccc\ddd";
$zipfilepath = "C:\aaa\bbb\ccc\ddd_" + $(Get-Date -Format "yyyyMMddHHmmss") + ".zip";
$cnt = 0;

set-content $zipfilepath ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18 ));
(dir $zipfilepath).IsReadOnly = $false;

$shellApplication = New-Object -com Shell.Application;
$zipPackage = $shellApplication.NameSpace($zipfilepath);

foreach($file in $(Get-ChildItem $filepath)){
    if ($(Get-ChildItem $file.Fullname).Count -eq 0) {
        # 0件のフォルダはエラー発生するのでスキップ
    } else {
        $zipPackage.CopyHere($file.Fullname)
        while(($cnt + 1) -ne $zipPackage.Items().Count) {
            start-sleep -milliseconds 500
        }
        $cnt ++
    }
}

```

## System.IO.Compression.FileSystem CreateFromDirectory
ディレクトリ圧縮のみ使える、サイズ2GB以上がディレクトリにあっても圧縮できる
終了待ち、エラーハンドリングはやりやすい

```PowerShell
$filepath = "C:\aaa\bbb\ccc\ddd";
$zipfilepath = "C:\aaa\bbb\ccc\ddd_" + $(Get-Date -Format "yyyyMMddHHmmss") + ".zip";

Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::CreateFromDirectory(
    $filepath
    , [System.IO.Compression.CompressionLevel]::Optimal
    , $false);
```

## System.IO.Compression.FileSystem CreateEntryFromFile
ファイル圧縮のみ使える、サイズ2GB以上だと圧縮できない。。。

```PowerShell
$filepath = "C:\aaa\bbb\ccc\ddd.txt";
$zipfilepath = "C:\aaa\bbb\ccc\ddd_" + $(Get-Date -Format "yyyyMMddHHmmss") + ".zip";

Add-Type -AssemblyName System.IO.Compression.FileSystem

$zip = [System.IO.Compression.ZipFile]::Open($zipfilepath, "Update")
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFIle($zip, $filepath, $(Split-Path $filepath -Leaf))
$zip.Dispose();
```
AWS Certified Database - Specialty 受験記

## はじめに
初投稿です。昨年2020年になりますが、AWS Certified Database - Specialty(DBS-C01) を受験しました。ギリギリでしたが合格できましたので受験記を投稿します。

## 試験概要
【試験時間】 
180分 

【問題数】 
65問 

【出題分野】 
[リンク](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-database-specialty/AWS-Certified-Database-Specialty-Exam-Guide_v1.0_08-23-2019_FINAL.pdf "リンク")参照

## 学習前のAWSスキル
* [AWS認定ソリューションアーキテクト – アソシエイト](https://aws.amazon.com/jp/certification/certified-solutions-architect-associate/)を2019年に取得
* 実機は検証で数か月使用したことがある程度(EC2,S3,Redshiftなどを使用)

## 学習前のデータベーススキル
RDB,DWH設計・構築 約1年
 

## 学習期間
約3か月

## 受験結果
756点(750点が合格ライン)


## 学習方法
1. [Blackbeltオンラインセミナー](https://aws.amazon.com/jp/about-aws/events/webinars/)の出題分野に関連した資料を読む<br>特に以下サービスについて熟読し、サービスの仕様について理解する
    * RDS(Aurora含む)
    * DynamoDB
    * DMS,SCT
    * Elasticache
    * DocumentDB 

1. AWS Certified Database - Specialty 模擬試験を受験し、問題の傾向をつかむ
1. [Udemy](https://www.udemy.com/)にあるAWS Certified Database - Specialty用の問題集を購入し、解く<br>※自分が使った問題集”AWS Certified Database - Specialty | Latest Questions 2020”(問題集)は、2021年3月に確認したところ同名の問題集はなくなっていた

## 受験した感想
### 特に頻出したサービス
* RDS(Aurora含む)
    * RDSの可用性担保、オンプレからの移行、クエリ処理の遅延対処など
* DynamoDB
    * GSIの特徴、グローバルテーブルの仕様など
* Elasticache
    * Redisでのクラスター構成についてなど

### 問題の傾向
ただサービス名を問われるというより、「ある要件・状況のなかでどのようにサービスを構成するか」といった問われ方で、DB系のサービスに関する仕様を理解していないと回答できないような問題ばかりでした。かなり難しい印象でした。
ただ、試験時間は180分でかなり余裕があるため、一通り回答した後に見直す時間も充分にありました。

### その他
試験学習を通してAWSのDB系のサービスについて理解を深めることができました。
今後AWS上でのDB設計・構築に役立てられそうです。
Notionでレイアウトするときに必須のテクニック

#はじめに
Notionの使い始めに、一番知りたかった、ブロックを移動させることでレイアウトができるということについて、簡単にまとめました。
##ブロック単位で移動させる

![](https://i.gyazo.com/d04604493c9d2ebb3662ad2b91558255.gif)

左右に並べたいときは、上のような操作をいます。
同様のやり方で、10個以上横並びにできます。
また、
ブロックの間にカーソルを合わせて、ドラックすることで、幅を変更させることができます。ただし、自由に決められるわけではなく、いくつかのポイントでしか、幅を設定することはできません。

![](https://i.gyazo.com/4e88ce375da49765d700cbb9ad9c02b4.gif)


##応用
![](https://i.gyazo.com/e9009bc75a97e8112458624b2d86cac4.png)
何もないブロックを中央に置き、左右の幅を調整することで、画像のようなレイアウトにすることも可能です。
PHPでprettierを有効にしてみた

#はじめに

VSCode上でPHPを使用しているときにprettierを有効にする手順

参考サイト
https://github.com/prettier/plugin-php

#手順
**1.prettier＋＠prettier/plugin-phpインストール**

npmコマンド

```
npm install --save-dev prettier @prettier/plugin-php
# or globally
npm install --global prettier @prettier/plugin-php
```

**2.設定ファイル**

`.prettierrc`をルートディレクトリに作成し次の内容を記述

```
{
  "singleQuote": true,
  "trailingComma": "all"
}
```

singleQuoteをTrueにすることによって、
ダブルクォーテーションの代わりシングルクォーテーションを使用するように設定する。

**3.拡張機能を追加**
VSCodeの拡張機能の`Run on Save`をインストールします。

Setting.jsonに下記の内容を追記

```
  "emeraldwalk.runonsave": {
    "commands": [
      {
        "match": ".php$",
        "cmd": "prettier ${file} --write"
      },
    ]
  }
```

以上がPHPでprettierを有効にする手順です。

matchで様々なファイルを設定することができます。

また現在HTMLとPHPを含んだ、PHPファイルは整形することができません。
https://github.com/prettier/plugin-php/issues/845
Vue.js propsとemitのデータの受け渡し

私自身、データの受け渡しはvuexさえ覚えてしまえば大丈夫だろうと思っていましたが、とんだ勘違いをしていることに気づきました。vuexはグローバル変数なのでどこにでもアクセスできてしまうので、関連する処理を把握しておく必要があります。個人ならまだしも、チーム開発になってエラーが起きてしまったらプロジェクトが偉大な分、解決するのに一苦労です。そこで、確実にここのコンポーネントでしか値を渡さないということであればpropsやemitにしておくべきだと思いました。
propsとemitの勉強を疎かにしていたので、あまりわかってなかったので復習がてら勉強しました。
#props&emitの使い方（例）
```components/LikeNumber.vue
<template>
  <div>
    <p>いいね(例){{ halfNumber }}</p>
    <button @click="increment">+1</button>
  </div>
</template>
<script>
export default {
  //   props: ["totalNumber"],//プロパティ名はなんでもいい
  //propsでオブジェクトと配列を渡すときは参照渡しになる
  props: {
    totalNumber: {
      type: Number, //keyに名前、valueに型の種類
      required: true, //必ずこの属性（totalNumber）が必要かどうか
      //何も指定しないと警告が表示される
    },
  },
  computed: {
    halfNumber() {
      return this.totalNumber / 2;
    },
  },
  methods: {
    increment() {
      //データの送り口
      this.$emit("my-click", this.totalNumber + 1);
      //第１引数はイベントの名前（なんでもいい）、第２引数に渡すデータ自身を入れる

      //       this.totalNumber + 1;
      // これでは親の値は変わらない
    },
  },
};
</script>
```
```pages/board.vue
<template>
  <v-container class="todo">
    <v-form ref="form">
      <v-row>
        <v-col cols="12" md="12">
          <TodoDetail></TodoDetail>
        </v-col>
      </v-row>
    </v-form>
    <h2>{{ number }}</h2>
    <!-- <LikeNumber :total-number="number" @my-click="incrementNumber"></LikeNumber> -->
    <LikeNumber :total-number="number" @my-click="number = $event"></LikeNumber>
    <!-- データの送り口 -->
    <TodoList name="TODO" :todolist="todolist"></TodoList>
    <!-- nameもpropsで渡ってきている　TodoList.vueからpropsで渡ってきたtodolistとboard.vueのtodolistをbindさせる  -->
    <TodoList name="DONE" :todolist="donelist"></TodoList>
    <!-- nameもpropsで渡ってきている　TodoList.vueからpropsで渡ってきたtodolistとboard.vueのdonelistをbindさせる  -->
    <v-btn class="mx-1 my-2 px-3 py-2 red" @click="logout"> LOGOUT </v-btn>
  </v-container>
</template>

<script>
import TodoList from "@/components/TodoList.vue";
import TodoDetail from "@/components/TodoDetail.vue";
import LikeNumber from "@/components/LikeNumber.vue";
export default {
  data() {
    return {
      number: 14, //親コンポーネントのnumber
    };
  },
  components: {
    TodoList,
    TodoDetail,
    LikeNumber,
  },
  computed: {
    todolist() {
      return this.$store.getters["sample/orderdTodos"].filter((el) => {
        return el.done === false;
      }, this);
    },
    donelist() {
      return this.$store.getters["sample/orderdTodos"].filter((el) => {
        return el.done === true;
      }, this);
    },
  },
 
  methods: {
     incrementNumber(value) {
       this.number = value; //このvalueは子コンポーネントのthis.totalNumber + 1 を受け取った
     },
  },
};
</script>

<style scoped>
.status.done {
  text-decoration: line-through;
}
</style>
```
この場合LikeNumber.vueが子コンポーネントにあたり、
board.vueが親コンポーネントにあたります。
###大事なことのまとめ
1.emitは渡しているけど変えてるわけではない
2.親のイベントを発火させる起動スイッチ、子コンポーネントの中で親コンポーネントのメソッドを好きなタイミングで発火できる
3.好きにイベント名を作れる
4.子のコンポーネントに送り口、親に受け口をおく
5.$eventが受け取れるデータを示す
6.親が持ってるnumberは子供から変えてるわけではない、親自身で変えている
7.親は子供のデータに依存して変わるものはない
8.子供は親のデータを勝手に変えれない
9.親が子供のデータに依存して変えれるデータを持っていない
10.**親から子のデータの受け渡しはprops、子供から親へのデータの受け渡しはemitで行う**
11.命名規則
$emitでつけた第一引数はケバブケースで統一
3D


##3D

transform-style: preserve-3d;は子要素を3Dで表現する
perspective: 300px;は奥行きを指定する


##opacity

opacityは透明度を指定
縦Y軸、横X軸、斜めZ軸


##perspective-origin

perspective-originは視点の角度（遠近感）を表現する
perspective-origin: 50% 50%;はデフォルトで正面からの視点
perspective-origin top left;は左上の視点


##translate3d

transform: translate3d(0, 0, 20px);はz軸を指定できる書き方
transform-style,　prespectiveを親要素に付ける（3D）
【jquery,js】ランダムな数字を配列にしてソート/重複行を削除する [Math.random(),push,sort,filter] [js13_20210311]

####  <font color='orange'>処理の概要</font>
ランダムなら数値から成る配列に対して、並べ替え、重複した値の削除を実施します。

##### 処理のフロー：
フローは記述しません。

####  <font color='orange'>画面イメージ</font>

#####画像１
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647299/7a905022-fbee-4298-0ea6-b86e62ce8fcc.png" width="300px">

#####画像２
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647299/f5d46856-6b1b-c111-e01b-0e3597b34835.png" width="300px">


####  <font color='orange'>ソースコード</font>
```html:index.html
一部省略...
        <link rel="stylesheet" href="./css/default.css">
        </script>
    </head>
    <body onload="init()">
        <textarea id="beforeString"></textarea><br>
        <div id="beforeLengthDisp"></div><br>
        <br><input type="button" id="execSortButton" value="ソート実行"><br>
        <textarea id="afterSortString"></textarea><br>
        <br><input type="button" id="execFilterButton" value="フィルタリング実行"><br>
        <textarea id="afterFilterString"></textarea><br>
        <div id="afterLengthDisp"></div><br>
       
    </body>
```

```javascript:main.js
function init(){
    var lobjString = [];
    for (var i=0; i< getRandom(50,80); i++){
         lobjString.push(getRandom(50,70));
    }
    lobjGetLength = lobjString.length;
    $("#beforeLengthDisp").text("初期配列の長さは："+ lobjGetLength);
    $("#beforeString").val(lobjString);
}

//自前乱数発生メソッド作成
function getRandom( min, max ) {
    //random()は、1未満の少数乱数を発生させる
    //max:1、max:5　乱数0.52とすると　0.52*5=2.5....2+1=3となる。便利
    var random = Math.floor( Math.random() * (max + 1 - min) ) + min;
    return random;
}

$(function(){
    $("#execSortButton").click(function(){
        lobjString = $("#beforeString").val();
        //テキストのままだと文字列なので、配列に変換する
        lobjString = lobjString.split(',');
        lobjString = lobjString.sort();
        $("#afterSortString").val(lobjString);
    });

    $("#execFilterButton").click(function(){
        lobjString = $("#beforeString").val();
        //テキストのままだと文字列なので、配列に変換する
        lobjString = lobjString.split(',');
        //重複した行を排除する。
        lfilString = lobjString.filter(function (x, i, self) {
            return self.indexOf(x) === i;
        });
        lfilString = lfilString.sort();
        $("#afterFilterString").val(lfilString);

        lobjGetLength = lfilString.length;
        $("#afterLengthDisp").text("フィルター後の配列の長さは："+ lobjGetLength);
    });
})
```

####  <font color='orange'>ポイント</font>
html：
(1)特になし
js：
(1)init処理
ここで、getRandom()メソッドを使って、作成する配列の数と、配列に入れる数に対して乱数を発生させる。乱数は、1未満の小数点で発生するので、Math.floorを利用する。
(2)execSortButtonボタンを押下したとき、テキストエリアから得られたのは文字列なので、配列にするためにsplitを利用する。

(3)execFilterButtonボタン押下時も同様にsplitにて配列に変換。今回、filter()メソッドは重複した値のみを排除する。このほかにも、重複している値のみを重複せずに表示したり、重複していない値のみを取り出す事もできる。

####  <font color='orange'>参考資料</font>
今回は自作でーす。現場でSQLチューニングをしているのですが、冗長的な結合を排除するにあたり、重複した値の排除をjsでしなければならなくなったため（OracleのLISTAGG関数は、12cでは出来ないことが判明した）
dockerでAmazon linux2を使う

#### コンテナ作成・初回起動
```bash
docker run -td --name sv1 amazonlinux:2
```
1. `-t` は仮想端末の割当
2. `-d` はバックグラウンド実行に必要

#### 起動したコンテナのコマンドラインシェルにつなぐ
```bash
docker exec -it sv1 /bin/bash
```
1. `-i` はインタラクティブ モード
2. `-t` は仮想端末の割当

#### コンテナ停止

```bash
docker stop sv1
```
バックグラウンド実行中のコンテナを停止する

#### コンテナ起動

```bash
docker start sv1
```
停止中のコンテナを起動する

#### コンテナ削除

```bash
docker rm sv1
```
停止中のコンテナを削除する