OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerコンテナ間通信 php <-> myql

# 概要
dockerでコンテナ間(php <->mysql)の環境を構築したく、実現方法を調べたので、
メモとしてまとめておく。

コンテナ間通信には2つの方法があるようだが、
1. docker networkを作成して、コンテナ名でアクセスできるようにする
2. linkオプションを使う
 →方法2はレガシーとのことで、1の方法で実行する。
（参考） https://knowledge.sakura.ad.jp/16082/


#docker ネットワークの作成
```
docker network create myapp_network
```

#ディレクトリ構成
```
php
 docker
   --php
    ┗--dockerfile
   --www
    ┗--index.php
 docker-compose.yml
```

#dockerfile
```
FROM php:7.2.11-apache

RUN docker-php-ext-install pdo_mysql
```

#docker-compose.yml
```
version: '3'
services:
  app:
    build: ./docker/php
　　 #永続化データ(phpのファイルの配置場所）
    volumes:
      - ./www:/var/www/html
    ports:
      - 80:80
    networks:
      - myapp_network

  mysql:
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=pass
      - MYSQL_DATABASE=php
    ports:
      - 3306:3306
    # 永続化データ
    volumes:
      - ./dbdata:/var/lib/mysql
    networks:
      - myapp_network

networks:
    myapp_network:
      external: true

```

#php->mysqlへのアクセス確認コード
```
<?php

define('DB_DATABASE', 'php');
define('DB_USERNAME', 'root');
define('DB_PASSWORD', 'pass');
define('PDO_DSN', 'mysql:host=mysql;dbname=' . DB_DATABASE);
try {
  // connect
  $db = new PDO(PDO_DSN, DB_USERNAME, DB_PASSWORD);
  $db->exec("insert into user (name) values ('test')");
  echo "enrolled";
} catch (PDOException $e) {
  echo $e->getMessage();
  exit;
}
?>
```

#コンテナの起動
phpコンテナからmysqlコンテナにアクセスする。

```
docker-compose up -d
```

以下のURLを実行する。
http://localhost/index.php

#DBレコードの確認
```
#mysqlのコンテナに入る
docker exec -it php_mysql_1 bash

#myqlのコンテナに入る
$ mysql -u root -p php
Enter password:
mysql> select * from user;

+----+--------+
| id | name   |
+----+--------+
|  1 | docker |
|  2 | php    |
|  3 | aaa    |
|  4 | aaa    |
|  5 | aaa    |
|  6 | test   |
+----+--------+
```

Done!
YouTube Data API試してみた。



##YouTube Data API v3試して見た

いろんなAPIが世の中にはあるのを知り、手軽に試せそうなものを試してみました。


```javascript

//リクエストパラメーターのセット
const KEY = '******************************' ;// APIKEY
let url = 'https://www.googleapis.com/youtube/v3/search?'; // APIURL
url += 'type=video'; //動画を検索する
url += '&part=snippet';//検索結果にすべてのプロパティを含む
url += '&q=music';//検索ワードの指定
url += '&videoEmbeddable=true';//WEBページに埋め込み可能な動画のみ検索
url += '&videoSyndicated=true';//youtube.com以外で再生できる動画飲みに限定
url += '&maxResults=10';//動画の最大取得件数
url += '&key=' + KEY;//APIKEY


//ここでconsole.log(url)をして、urlが作成されているか確認
//コンソールに出てきたurlをブラウザに貼り付け正常に動作するか確認する
//APIからのレスポンスでJSONが返ってきていればOK


function setData(data){
  let result = '';
  let video = '';
  //動画を表示するHTMLを作る
  for (let i = 0; i < data.items.length; i++){
    video = '<iframe src="https://www.youtube.com/embed/';
    video += data.items[i].id.videoId;
    video += '" allowfullscreen></iframe>';
    result += '<div class="video">' + video + '</div>'
  }
  $('#videoList').html(result);
}

//Ajax通信をする
$(function(){
  $.ajax({
    url: url,
    dataType : 'jsonp'
  }).done(function(data){
    if(data.items){
      setData(data);
    } else{
      console.log(data);
      alert('該当するデーターが見つかりませんでした。')
    }
  }).fail(function(data){
    alert('通信に失敗しました。');
  });
});

function setData(data){
  let result = '';
  let video = '';
  //動画を表示するHTMLを作る
  for (let i = 0; i < data.items.length; i++){
    video = '<iframe src="https://www.youtube.com/embed/';
    video += data.items[i].id.videoId;
    video += '" allowfullscreen></iframe>';
    result += '<div class="video">' + video + '</div>'
  }
  $('#videoList').html(result);
}

```

上記にHTMLやCSSにてVIEWも少しいじってみました。
一部写真で記載してみます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383398/10c0d048-97d7-da30-6933-c0cadc1c08af.png)


以上です！
plyvelをmacにインストールしようとしたらエラーが出た話

5/7追記
pipにあるplyvelのversionが1.1.0に更新されていました。
現在は```pip install plyvel```でエラー無しでインストールできるようになっています。

#はじめに
LevelDBをpythonから叩くためのパッケージ"plyvel"をpipでmacにインストールしようとしたところ、エラーが発生しました。
どうやらLevelDBのバージョンをを1.2.1に上げたのが原因のようです。plyvel1.0.6で修正されるようですが...。

#環境
- macOS Mojave
- Python 3.7.3
- LevelDB 1.2.1
- plyvel 1.0.5

#インストール手順
ということで、ソースコードからコンパイル。

```
git clone https://github.com/wbolster/plyvel.git
```
としてgitからコードをcloneしたあと、中にあるsetup.pyを開き、16行目に```'-stdlib=libc++'```を追記します。

```setup.py
#16行目にフラグを追記
extra_compile_args = ['-Wall', '-g', '-x', 'c++', '-std=c++11', '-stdlib=libc++']
```

あとは

```
make
python setup.py install
```
でインストール完了です。お疲れ様でした。

#参考文献
https://github.com/wbolster/plyvel/issues/95
DeepLearningを使った画像処理のために知っとくとよい単語あれこれ

#きっかけ
DeepLearningを使った画像分類や画像認識が盛んですが、関連の単語でわからないものもたくさんあってなかなか理解が進まないと思います。そこで簡単にですが、まとめてみました。

実際には何かしらの本を一冊読んで、ChainerやらDeepLearningデモを動かしたりコードを読んだりするのが一番だと思うので、そこ前段階の 「へー」 くらいを目指そうかと思います。厳密に間違っているものもあるかもしれませんが、**私は直感的にこう理解しています**という内容を綴っていきたいです。

なお、コードを読める人はGithubにも目を通すと良いかと思います。自分はChainerが好きなので、Chainerを貼って起きます。

[Chainerの実装](https://github.com/chainer)
[ChainerCVの実装](https://github.com/chainer/chainercv)

#知っとくと良い単語
##機械学習全般編
###教師あり学習
入力するデータに対して、出力がこうあるべき！！といった関連付けられたワンセットを入力して学習していく方式。

###教師なし学習
データを座標空間にプロットしてみて、数学的手法でグループ分けをしたり、将来の値を予想したりするもの。入力データに対して出力が定まったデータを用意するのは容易ではない場合は教師なし学習となる。外れ値などの検出も教師なし学習といえる。

###関数
y=f(x)の形で表せるような、入力xに対してyを求めるための計算式

###ニューラルネットワーク
脳を模擬した、関数のつらなり。ただ、ニューラルネットワークの場合にはベクトルを扱うため、ベクトルの次元数分の関数が縦にならび、その関数の縦列のことを**層**と呼ぶ。

###DeepLearning(DL)
ニューラルネットワークででてきた層を何重にも重ねたもの。つまり関数の縦方向の連なりである層をさらに横方向に何重にもたくさん並べたもの。

###学習
これらの関数は前述の教師あり学習では入力するデータに対して、出力がこうあるべき！！といった関連付けられたワンセットを入力するたびに、現在の関数の出力と理想出力を比較して関数式を修正していく。この過程を学習といいます。


##実装編


###　モデル(Model)
まずDeepLearning(DL)の**モデル**という言い方をよくします。DeepLeaningには数多くの実装があり、それぞれ得意不得意が違います。そもそも、作られた時代も違います。インプットは何か、各層(まあ実装のようなもの)は何か、アウトプットは何か、その具体的な構成をモデルといいます。別の言い方で**アーキテクチャ**や**ネットワーク**なんて言い方もします。何がしたいかが異なればモデルも異なるということです。
例えば画像検出などに使われる*Single Shot Multibox Detector(SSD)*なる仕組みがありますが、それにもさらにSSD300とSSD500というモデルが存在します。

大体のDLの実装例(examplesってフォルダがあると思います。)には必ずモデルを選択できるようになっています。大きく大別されたモデルの中から、さらにコード中で細かくモデルを選択するものもあります。

また、モデルの中には学習で説明した関数の修正方法についても定義されています。

###データセット
モデルのインプットに突っ込むデータ集合です。当然ながら何がしたいかによってデータセットは異なります。画像関連だったらデータセットは画像になります。また教師あり学習では、つまりデータに対して出力はこうあるべき！！というのが結び付けられている必要があります。

###初期化(Initialize)
DLは関数のつらなりである層が、横方向にもつらなっているということを説明しましたが、関数の学習の前にすでにある程度の関数に仕上げておいてほしいものです。なぜなら1を入れて100を出力してほしい関数を作るときに、1を入れて1000000を出力される初期関数と1を入れて1000を出力する初期関数では、同じテストデータがあっても最終的な関数の仕上がりに違いがあるからです。

そのため、DeepLeaningではモデル、データセットと匹敵するほどの大事な要素としてこの初期化があげられます。

###グレースケール
RGBで表現された画像を無色にすること。つまり、モノクロ画像にすること。

###Meanファイル(中間画像)
画像系ではたびたび計算途中でMeanファイルを求められることがあります。この中間ファイルというのはつまり、各画像のピクセル単位の値(画素)を平均した値のことです。例えば真っ白な画像であれば画素平均は RGB=(255,255,255)となります。グレースケールに変換する場合には真っ白な画像はG=255となります。
計算式は全ピクセルの画素の和をピクセル数で割ればいいです。これをデータセット全体で計算し、平均をとります。

###ハイパーパラメーター(バッチサイズ、イテレーション、エポック)
データセットが1000こあった場合、これらを一度に入力して学習しようとすると、そのデータ内部のとっても平均的な値に関数が訓練されます。これをさけて、ど平均の関数よりも、汎用的な関数に仕上げたいです。
そこでデータセットをN等分してN回学習を行います。**このNをイテレーション回数といいます。**
**N等分されたデータサイズをバッチサイズといいます。**

このバッチサイズに分けたデータをN回学習することで各データセットは一度は使われることになります。
ですが、一度では足りないです。それをさらにEpoch回数繰り返します。この繰り返す回数のことをエポック数とよびます。**エポック数はデータセットを関数の更新に何回用いるか**を表します。


#おわりに
次は具体的な実装や、実装内部で出てくる関数について触れます。
Node.js,Expressメモ⑤の5

ここのところ寒いですね。GWも明日からは雨が続くようです。こんにちは。

今回はPart5のサブページ5番目です。
https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data/Book_list_page

こっからは同じようなものがつづくようなのでまとめてやってしまうかも？です。

#bookページのリスト表示

完成品はコチラ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199642/ad94a225-6cd7-ba45-2056-864521dd4680.png)

ここでは本のリストと著者のリストを表示させればよさそうです。

mongoDBのBooksをみると著者は当然別のテーブルのidが書かれています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199642/3afa8ad6-93f4-69d3-4bbc-426576af4b74.png)

なのでbooksのリストの各要素のauthor.idをauthorテーブルから置き換えればOKですね。

# bookControllerのbook_list
前回と同じように関数を作ってpugファイルを作成します。

```
exports.book_list = function(req, res, next){
    Book.find({}, "title author").populate("author").exec(function(err, list_books){
        if(err){return next(err);}
        res.render("book_list", {title: "Book List", book_list: list_books});
    });
};

```

ここでまたちょっとわからないところがあります。
findは検索だと思いますが第一引数はフィルターだったかと思います。
第二引数の"title author"とは？

ちょっとmongooseのModel.find()をみてみます
https://mongoosejs.com/docs/api.html#model_Model.find

`Model.find(conditions<object>, projection<object|string>, options<object>, callback<function>)`
だそうです。
・conditions
  {}にフィルタをいれるようです。{name: "john"}など
・projection
　そうか、selectっぽいですね。sqlでいうところの`SELECT title, athour FROM books`ってことですね！
・option
　条件みたいです。
・callback
　ここはfunctionを入れるようですが、まだピンときません。。

#populate
うーん。。これはまたわからない！

とりあえずドキュメントを張ります。
https://mongoosejs.com/docs/populate.html

説明によると他のコレクションを参照できる代替手段になると。
例をみるとモデルのスキーマに設定されているようなのでbookのmodelをみてみます。

`author: {type: Schema.Types.ObjectId, ref: "Author", required: true}`

ここのrefというのがそれっぽいです。
設定するのは文字列なのでここと一致させているということだと思います。

```
models/author.js
//一番最後のマッピング部分
module.exports = mongoose.model("Author", AuthorSchema);
```

```
var AuthorSchema = new Schema(
    {
	first_name: {type: String, required: true, max: 100},
	family_name: {type: String, required: true, max: 100},
	date_of_birth: {type: Date, default: Date.now},
	date_of_death: {type: Date, default: Date.now},
    }
);
```

authorの定義がこれなので、books.author.first_nameとかも可能なのかな？と思います。

execの中のfunctionこれもよくわからない。。

# res.render
何はともあれfunctionの第2引数のlist_booksにbookのモデルとそれに付随したauthorのモデルが入っているとします。
はいっているのでしょう。

だとしたらbook_list.pugで使えるアトリビュートは
`book.title`
`book.summary`
`book.isbn`
`book.genre`
`book.url` < 関数
`book.author.first_name`
`book.author.family_name`
`book.author.date_of_birth`
`book.author.date_of_death`
になります。

genreもリファレンスされていますがこれはどういう扱いでしょう。2つとも欲しい場合は？
一応2つ繋げて書くこともできるようです。
`Book.find({}, "title author").populate("author").populate("genre").exec(function(err, list_books))`

pugにbook.genreといれたらオブジェクトが表示されました。
が、欲しい感じでは受け取れていません。authorと比べてgenreは配列だから？という気もしますが
そちらはおいおい見ていけたらと思います。


#book_list.pug
さて今度はこれをレンダリングするためのpugファイルを作成します。

```
extends layout

block content
  h1= title

  ul
    each book in book_list
      li
        a(href=book.url) #{book.title} 
        | (#{book.author.name})
        

    else
      li There are no books.
```

上部は定型文でlayoutを継承してblockのcontentを置き換えますよという記述。
今回はfor 分が入っています。each文っていうんですかね。

\#{}は#{アトリビュート(virtual関数?)}という用途もあるようです。

さてPart5はこの後12まで続きますが大体ここまで書いたことの繰り返しなので
割愛します！
だんだんページができてくるのは嬉しいものです。

つづく
WebRTC関連記事まとめ

## JavaScript API

[developer.mozilla.org - WebRTC API](https://developer.mozilla.org/ja/docs/Web/API/WebRTC_API)
[lealog.hateblo.jp - WebRTCやるのに最低限必要なJavaScriptのAPIについて](https://lealog.hateblo.jp/entry/2019/04/22/095422)

## SDP

[slideshare.net - SDP for WebRTC](https://www.slideshare.net/iwashi86/webrtc-for-sdp)
AWSでWindowsServerを使用する際の注意点 ~.NetFramework~

# 初めに
本記事はmakutariがAWSを使用するうえでポイントとして押さえていることを記載しています。
動作を保証しているものではないのでご注意ください。

# 背景
オンプレミスからAWSへの移行に限らず、以下のような要件はお客様からの要望として結構リクエストされるかなと思います。

- VSSスナップショットの取得

- サーバのマスタイメージ化

AWSで上記の要件を実現しようとすると、 *SystemsManager* や *EC2Config* を使用する必要があります。
マーケットプレイスのAMIでも、オンプレミスから *SMS* などで持ってきたAMIでも注意が必要です。

なぜかというと、
**SystemsManager や EC2Config は特定バージョンの .NetFramework と相性が悪い**
ということなんです。

# 対応策

**.NetFramework 4.5** は上記のサービスとの相性が悪いようです。
**.NetFramework 4.6** 以降へのバージョンアップをお勧めします。

# あとがき

既存システムを移行している場合様々なしがらみでバージョンアップが実施できないこともあるかと思います。
バージョンアップが実施できないことでどんな影響があるか理解しておくといいかもしれません。
Jenkins シェルコマンド バッドプラクティス 環境移行関連

# Jenkins shell command bad practice related to change running env

## Background

In my project, there's a task to change jenkins' running env from Device-A to Device-B; A and B use same OS.

And found troublesome problems `(0)` and `(1)`.

## (0) `source ~/.bash_profile`

ex. in jenkins shell command

```
echo "START SCRIPT"

source ~/.bash_profile
FUNC_IN_BASH_PROFILE
echo $VAR_IN_BASH_PROFILE

echo "END SCRIPT"
```

### What is PROBLEM

**`~/.bash_profile` is binded to env, it's hard to transfer**

it's ideal just send only Device-A's jenkins backup file(`*.xml`, etc) to Device-B.

But in this case, you should copy Device-A's `~/.bash_profile` to Devic-B's one.

### What should it be

My opinion

* (0-1) Write all script to jenkins shell command
* (0-2) Or write script to file, not to `~/.bash_profile` but env file which can pull from VCS(Version Controle System)
  * pull it and set script where jenkins can execute

## (1) `/home/hardcoded-username`

ex. in jenkins shell command

```
echo "START_SCRIPT"

bash /home/hardcoded-username/blahblah_script
bash /home/hardcoded-username/foobar_script

echo "END_SCRIPT"
```

### What is PROBLEM

**It's not flexible, `hardcoded-username` forces username**

As well as `(0)` case, username links to device's env.

When restored env does not use the name, you should modify jenkins shell command manually.

### What should it be

My opinion

```
echo "START_SCRIPT"

MY_NAME=`whoami`
bash /home/$MY_NAME/blahblah_script
bash /home/$MY_NAME/foobar_script

echo "END_SCRIPT"
```
RedHat Enterprise Linux 7でRHSCL PHP 7.2を使う

# 前置き
WordPressの次期バージョンからはPHP 5.4で動作しなくなり、PHP 5.6以上が要求される。試しにRedHat Enterprise Linux 7 (RHEL7)の環境でWordPress 5.2 beta3をインストールしようとすると以下のようなメッセージが表示されるだけでインストール画面すら表示されない。

```
Your server is running PHP version 5.4.16 but WordPress 5.2-beta3 requires at least 5.6.20.
```

CentOSであれば[Remiリポジトリ](https://rpms.remirepo.net/)を使って新しいPHPを利用することが一般的だと思われる。しかしRHEL7で同様にするとRedHatのサポートが得られなくなってしまうため、サポートを得られる方法で新しいバージョンのPHPを使う方法を考える。

# 対策方法
RedHat Software Collections (RHSCL)を利用する方法があり、期間の制限はあるがRedHatのサポートが得られる。[PHP 7.2であれば2020/11までサポートされる](https://access.redhat.com/support/policy/updates/rhscl)。2019年12月に追加されたPHP 7.3は2021/12までとなっている。
既にPHP 5.6は2018/4でサポートが終了しているため、今回は検討しない。

# インストールする環境について
PHP 7.2を導入する際にはいくつかの方法が考えられるが、RHSCL版PHPとApache httpdをセットでインストールする方法は他の人が書いていると思われる。
そのため、以下のような環境を想定してみる。

- 同一サーバで他にもPHPアプリが動作している
- 他のPHPアプリはPHP 7.2で動作するか検証できてない
- 既存のPHPアプリへの影響が無いように設定する
- そのため指定したPHPアプリでだけPHP 7.2を利用する
- httpdを2つ動作させて80と81ポートで待ち受けのようなことはしたくない

というケースを想定して導入してみる。
両方でDSO(mod_php)を利用しようとすると条件を満たせないため、少なくともPHP 7.2ではphp-fpmを利用する必要がある（リバースプロキシの導入は今回は考えない）。

# インストールと設定
httpdとPHP 5.4、PHP7.2をインストールする。

```
# yum install httpd php

# yum-config-manager --enable rhel-server-rhscl-7-rpms
# yum install rh-php72 rh-php72-php-fpm
```

php-fpm を起動する。必要に応じて事前にポート番号を変えたりUNIXソケットを利用するよう設定を変えておく。

```
# systemctl start rh-php72-php-fpm
# systemctl enable rh-php72-php-fpm
```

テスト用のディレクトリとファイルを作成する。

```
# mkdir -p /var/www/html/php56
# echo '<?php phpinfo();' > /var/www/html/php56/phpinfo.php

# mkdir -p /var/www/html/php72
# echo '<?php phpinfo();' > /var/www/html/php72/phpinfo.php
```

テスト用のhttpdの設定を行う。

```conf:/etc/httpd/conf.d/test.conf
<Directory /var/www/html/php56>
</Directory>

<Directory /var/www/html/php72>
  <FilesMatch "\.php$">
    SetHandler application/x-httpd-php
    SetHandler proxy:fcgi://127.0.0.1:9000
  </FilesMatch>
</Directory>
```

httpdをリロードする

```
# systemctl reload httpd
```

ウェブブラウザで両方のディレクトリにアクセスして表示されるPHPのバージョンを確認する。
[Linux] Yarn 使ったらあった問題解決。

>error An unexpected error occurred: "EACCES: permission denied, scandir '/home/ubuntu/.config/yarn/link'".
info If you think this is a bug, please open a bug report with the information provided in "/home/ubuntu/research/react_blog/blog-backend/yarn-error.log".
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.



```terminal

sudo chown -R $USER:$GROUP ~/.npm
sudo chown -R $USER:$GROUP ~/.config

```
Nuxt.jsでbodyにclassを設定する3つの方法

Nuxt.jsでページを作っていくと、最終的に出力されるHTMLは

```html
<html>
 <body>
  <div id="__nuxt">
   <div id="__layout">
    <div class="container"> <!-- layouts ファイル の１行目 -->
```

のような構造になります。

このhtmlやbodyにidやclass、dataなどを設定するにはどうすればいいのかを調べるのにちょっとだけ時間がかかりました。

時間がかかった代わりに、3種類やり方が見つかったのでまとめておきます。



# app.htmlをルートディレクトリに作成

[ビュー - Nuxt.js](https://ja.nuxtjs.org/guide/views)に書いてあったので、一番基本的な方法だと思われます。

> スクリプトまたは条件付きの CSS クラスを含めるために Nuxt.js で使われる HTML アプリテンプレートをカスタマイズできます。
> 
> テンプレートを変更するために、プロジェクトのルートフォルダに app.html ファイルを作成します。

ルートディレクトリ（`nuxt.config.js`と同じフォルダ）に`app.html`を作成し、

```html:app.html
<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
  <head {{ HEAD_ATTRS }}>
    {{ HEAD }}
  </head>
  <body {{ BODY_ATTRS }} class="body-class">
    {{ APP }}
  </body>
</html>
```

のように書けばクラスが追加されます。

この方法はわかりやすいですが、ルートディレクトリにわざわざ新しいファイルを作るのがちょっと大袈裟に感じますし、余計なところを弄ってしまいそうで怖いです。


# layoutまたはpagesに追記

layoutフォルダに追記する場合。

[tag BODY modification · Issue #188 · nuxt/nuxt.js](https://github.com/nuxt/nuxt.js/issues/188)

このページにやり方が載っていました。

```layout/default.vue
<script>
export default {
  head: {
    bodyAttrs: {
      class: 'body-class'
    }
  }
}
</script>
```

この方法はわかりやすくてミスも少ないですが、layoutやpageが複数ある時に一括設定するのが面倒です。

# nuxt.config.jsで設定

```JavaScript:nuxt.config.js
  /*
   ** Headers of the page
   */
  head: {
    title: pkg.name,
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: pkg.description }
    ],
    bodyAttrs: {
      class: 'body-class'
    },
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },
```

nuxt.jsに慣れている方は、2番目の方法を見た時点でわかるかもしれませんが、このようにすれば全ページ共通で設定することができます。

※ `nuxt.config.js`の設定変更はホットリロードされないことがあるので、反映されない場合は一度停止してから再度`npm run dev`してください。



# いつ使うのか？

Bulmaで固定ヘッダーを設定する際に、`has-navbar-fixed-top`をbodyに付けるために使いました。

[Navbar | Bulma: Free, open source, & modern CSS framework based on Flexbox](https://bulma.io/documentation/components/navbar/#fixed-navbar)

CSSフレームワークを使う場合に必要になることは多いのではないでしょうか。
有効なcredentialを設定していても"The security token is invalid"？

DynamoDBの操作を効率的にコーディングする方法を調べていたら、突然以下のエラーに襲われました。

```console
botocore.exceptions.ClientError: An error occurred (UnrecognizedClientException) when calling the ListTables operation: The security token included in the request is invalid.
```

このエラー自体は何度か見たことがあり、credentialに問題があると思ったのですが、~/.aws/credentialsを見ても特におかしなところは無く、IAMでも有効となっていました。何かの有効期限に引っ掛かったのかと思い、新しいアクセスキーを作成して設定しても状況は変わらず。

```python
import os
os.environ['AWS_DEFAULT_PROFILE'] = 'ttkiida'
```

コードの最初でプロファイルを指定してもダメでした。ここまで来たらどこかで謎のcredentialが指定されているとしか思えないので、エラーの出る直前で環境変数を表示してみたところ…。

```console
'AWS_ACCESS_KEY_ID': 'foobar_key', 'AWS_SECRET_ACCESS_KEY': 'foobar_secret'
```

何だこの値は？！　変なパッケージを読み込んでいたのか？　ネットで調べてみると…。

```python
from moto import mock_dynamodb2
```

このインポート文を残していたことが原因だと判りました。これはBoto3のモックライブラリであるMotoというもので、色々試しているうちに削除やコメントアウトされず残ってしまっていたのです。

```python
os.environ.setdefault("AWS_ACCESS_KEY_ID", "foobar_key")
os.environ.setdefault("AWS_SECRET_ACCESS_KEY", "foobar_secret")
```

こんなコードがMotoに含まれており、このせいでcredentialが上書きされてしまってたんですね。ユニットテストの時にcredentialをダミーの値にしておくというのは私もよくやっているので、Motoにこのコードがあるのは納得なのですが、PyCharmで「未使用のimport文」としてグレーアウトされていてので気付けませんでした。ということで、不要なimport文には要注意！
edgeテンプレートエンジンをつかってみた  #GWアドベントカレンダー4日目


 #GWアドベントカレンダー[「使いたかったもの使ってみたカレンダー（1人アドベントカレンダー）」](https://gw-advent.9wick.com/calendars/1)の4日目、30日記事です。


# edgeテンプレートエンジンをつかってみた 

[adonis.js](https://adonisjs.com/)を使っているときに、[edgeテンプレートエンジン](https://edge.adonisjs.com/)を使ってみました。
HPのドメイン的に、adonisの子分というか、adonis内プロジェクトの１つのようです。でも独立して使えるようです


# Edgeテンプレートって何？

node.jsでテンプレートエンジンといえばejsとかJade/Pugとかがあります。
ejsはよく使ってるのですが、`include header.ejs`とか`include footer.ejs`とかを書くのが普通になってしまいます。

edgeの場合、レイアウトという概念があってheaderとfooterを分けなくてよいのが最大の特徴になりそうです。

```html:layout.edge
<html>
 <head>
  <title>title</title>
 </head>
 <body>
  @!section('content')
 </body>
</html>

```

```html:sample.edge
@layout('layout.app')

@section('content')

hello world

@endsection
```

ただの文字連結するためにファイルを作る　ではなくて、意味を持ったまとまりのファイルをつくるという考えに変わります。


同じように、コンポーネントも作ることができて、例えばinputフォームコンポーネントを作ってそれを再利用するとか、意味を持ったパーツとしてのファイルがたくさんできる、という概念でした。

C言語で`#include`を使って頑張るんじゃなくて、意味をちゃんと持たせてクラス化しようよ！と言われたときのことを思い出しました。
また、どことなくVue.jsと似てそうです。

## 良さそうなところ/面白かったところ

- レイアウトやコンポーネントの概念がいい
- 自然と再利用が進んで見通しが良くなる
- ejsだと`<% var %>`のところ、`{{var}}`と書くので書きやすい。（%が意外と打ちにくい）


## あんまりイケてないところ

- ドキュメントが見にくい／動画でしか説明してない内容がある
- マイナーすぎて（？）エディタ側がファイルに対応していない。補間が聞かない。ハイライトしてくれない
- テンプレート内で変数の定義や代入ができない（？）


## 総合評価

概念がすごくいいし、書きやすいテンプレートエンジンでした。
でも正直、似たようなことできるvue.jsのほうがドキュメントも作例もたくさんあっていいかな。
macにminishiftをインストールする

# はじめに

macOSにminishiftをインストールするには2つ方法があります。
公式サイトでも紹介されていますが、今回はお手軽にmacOS + Virtualboxによるインストールを紹介します。

# 検証環境
- macOS Mojave (10.14.4)
- Virtualbox 6.0.4
- minishift v1.33.0

# インストール手順

基本的なインストール手順は公式サイトにもあります。
[Preparing to Install Minishift](https://docs.okd.io/latest/minishift/getting-started/preparing-to-install.html)

Linux、Windows、macOSといろんなプラットフォームでのインストール方法が記載されていますが、読むのは"All Platforms"のところです。

## インストールバイナリのダウンロード
バイナリを公式サイトの[Minishift Releases](https://github.com/minishift/minishift/releases)からダウンロードします。

## バイナリを解凍し、任意の場所に配置
私は分かりやすくホームディレクトリにある"Applications"フォルダに"minishift"フォルダを作成して、その中に解凍したバイナリ一式を配置しました。

## minishiftの起動
起動コマンドはこちら。

```
$ cd /Users/[自分のユーザ名]/minishift
$ ./minishift start --vm-driver virtualbox
```

デフォルトではCPUは2個、メモリ4GBで起動するそうですが、変更したい場合は起動時にオプション指定することで変更可能です。

```
$ ./minishift start --vm-driver virtualbox --cpus=4 --memory=8GB
```

一度起動に失敗してタイムアウトエラーとなりましたが、メモリサイズを8GBに変更したら問題なく起動しました。メモリサイズ不足か、はたまた純粋にタイムアウトしたのかは不明ですが、何度か試してみたら良いかもしれません。

```
Error: timed out waiting for the condition
```

## web consoleにアクセス

起動に成功するとこんな感じのログが表示されます。
web consoleのURLが表示されていますので、アクセスしてください。
OpenShiftのログイン画面が表示されます。

```
...
Login to server ...
Creating initial project "myproject" ...
Server Information ...
OpenShift server started.

The server is accessible via web console at:
    https://192.168.99.100:8443/console

You are logged in as:
    User:     developer
    Password: <any value>

To login as administrator:
    oc login -u system:admin
```

## トラブルシューティング

minishiftの起動時にこんなメッセージが表示されることがあります。

```
Could not set oc CLI context for 'minishift' profile: Error during setting 'minishift' as active profile: The specified path to the kube config '/Users/xxxxx/.minishift/machines/minishift_kubeconfig' does not exist
```

その際は、下記のようなワークアラウンドで回避可能です。

```
$ minishift delete -f
$ minishift start --profile minishift
```

以上。
Laravel+Dockerで「Migration table not found.」を解決する

LaravelとDocker(nginx, phpfpm, mysql)で開発をしていると、`Migration table not found.`という未知のエラーに遭遇してびっくりしたというお話をします。


# エラーが出た経緯

急にエラーが発生しました。僕はびっくりしました。

Dockerコンテナの中でmigrateするため、こんなコマンドを打ちました

```
$  docker-compose exec phpfpm sh -c 'cd ../ && php artisan migrate
Migration table not found. 
```

まさかの`Migration Table not found`

初めてのエラーに驚きを隠せません。

そして、調べても日本語の資料が全くありません。。。


```
$  docker-compose exec phpfpm sh -c 'cd ../ && php artisan migrate:status
Migration table not found. 
```

```
$  docker-compose exec phpfpm sh -c 'cd ../ && php artisan migrate:install
Migration table not found. 
```

何をしてもエラーが出ます。

# 解決策

`php artisan migrate:refresh`をすると、なぜかエラーがなくなりました！

```
$  docker-compose exec phpfpm sh -c 'cd ../ && php artisan migrate:refresh
Migration table not found.                                                                                                             
Migration table created successfully.                                                                                                  
Migrating: 2014_10_12_000000_create_users_table
```


原因もなぜ治ったのかも全くわかりませんが、治って万々歳です！！

同じ境遇の方がいましたら、ぜひやってみてください！！
GitHubで毎回ユーザ名とパスワードを入れたくない

以下を書いておけばOK？

```~/.netrc
machine github.com
login kph7m
password xxxxxxx
```

git push -u origin --all

```
$ git add -A
$ git commit -m "Finish static pages"
$ git checkout master
$ git merge static-pages
$ git push
```
Blazorのリンク集「Awesome Blazor」

# 「Awesome Blazor」とは？

以下、[Awsome Blazor](https://github.com/AdrienTorris/awesome-blazor)より。

> A collection of awesome Blazor resources.

「[Awsome Blazor](https://github.com/AdrienTorris/awesome-blazor)」は、[Blazor](https://dotnet.microsoft.com/apps/aspnet/web-apps/client)の記事・動画・書籍等のコンテンツへのリンクが集約された[AdrienTorris](https://github.com/AdrienTorris)氏のGitHubリポジトリです。

Blazorに関する素晴らしいコンテンツが集約されています。

「Official Preview」になったばかりで、情報がもっともっと欲しいこのタイミング。ぜひ、情報収集に活用してみてはいかがでしょうか。

---

Microsoft公式のASP.NET Blogの「[Blazor now in official preview!](https://devblogs.microsoft.com/aspnet/blazor-now-in-official-preview/?utm_source=vs_developer_news&utm_medium=referral)」の「Blazor community page is now Awesome Blazor」セクションには、

> As part of updating the Blazor site, we’ve decided to retire the Blazor community page and instead direct folks to the community driven Awesome Blazor 

とあります。

以前のBlazor公式ページにはコミュニティーページがあったようですがアップデートを機にそれを廃止し、[AdrienTorris](https://github.com/AdrienTorris)氏の「[Awsome Blazor](https://github.com/AdrienTorris/awesome-blazor)」へのリンクを直接置くようにしたようです。確かに、本稿執筆時の[Blazor公式サイト](https://dotnet.microsoft.com/apps/aspnet/web-apps/client)には、「[Awsome Blazor](https://github.com/AdrienTorris/awesome-blazor)」へのリンクが置いてありますね。

公式が頼っている:+1:

---

ところで、いろいろな技術要素に対してAwsome Listというものがあるようです。

詳しくは、こちら「[sindresorhus/awesome](https://github.com/sindresorhus/awesome)」の「[The awesome manifesto](https://github.com/sindresorhus/awesome/blob/master/awesome.md)」を参照してください。


# 実際に読んでみた・試してみた

## 公式サイト

公式サイトはこちら。

https://dotnet.microsoft.com/apps/aspnet/web-apps/client

ちなみに公式ドキュメントはこちら。

https://docs.microsoft.com/en-us/aspnet/core/blazor

ASP.NET CoreのWeb Appsの一部、という位置づけのようです。

## 公式デモ

https://blazor-demo.github.io/ 


テンプレートからBlazorプロジェクトを生成した時の初期状態のやつがGitHub Pagesにホスティングされているようです。（現時点）

「公式」ってことを言及している記述をみつけられなかったのだけど、↓みるとそれっぽいですね。

https://github.com/aspnet/AspNetCore/issues/5477
## FAQ

ぜひ一度は読んでほしいFAQです。

https://github.com/aspnet/Blazor/wiki/FAQ


個人的には特にした二つが読めてよかったです。

* Q: Why Mono? Why not .NET Core or CoreRT?
* Q: Where does the name "Blazor" come from?


綺麗にまとまった情報はここにしかないんじゃないかな？（issueとかを潜ればあるかもしれないけれど・・・）

ところでこのFAQがあるのは、「[aspnet/Blazor](https://github.com/aspnet/Blazor)」。Blazorのコードとissueは、「[aspnet/AspNetCore](https://github.com/aspnet/aspnetcore)」に移っています。このFAQも移して、引き続きメンテナンスをしてほしいです・・・（[issue](https://github.com/aspnet/AspNetCore/issues/9824)は建てました）

## blazor-workshop : そこそこの規模のハンズオン資料

そこそこの規模のハンズオン資料。

ピザの注文ウェブアプリが題材です。

よさそうだけど、まだ試してはいません。

https://github.com/dotnet-presentations/blazor-workshop/


## aesalazar/AsteroidsWasm : Blazor含むマルチプラットフォームのデモ

シンプルでレトロなゲームのデモ。

https://github.com/aesalazar/AsteroidsWasm

Blazor版はここで遊べます。

https://aesalazar.github.io/AsteroidsWasm/

Blazorだけでなく、.NET Standardを用いてコア部分をライブラリ化して、いろいろなプラットフォーム向けように作ったデモのようです。

* WinForms
* WPF
* WPF (.NET Core 3利用) 
* Xamarin (SkiaSharp利用)
* Xamarin.Android (↑のXamarin利用)
* Xamarin.UWP (↑のXamarin利用)
* Blazor (↓のBlazorComponentsの利用)
* BlazorComponents (HTMLとJavaScriptとのブリッジも参考になるかも)
conohaをつかってみた   #GWアドベントカレンダー3日目


 #GWアドベントカレンダー[「使いたかったもの使ってみたカレンダー（1人アドベントカレンダー）」](https://gw-advent.9wick.com/calendars/1)の3日目、29日記事です。


# conohaをつかってみた 

dokkuを使ってみたい！ということで新規にサーバーを立てようと思い立ちました。
いくつかVPSを持っているのですが、１０年前に設定したまま放置の状態で、構成がどうなってるか思い出すよりは作り直したほうが早いかなと。

以前はSAKURAを使っていたのですが今回はconohaにしてみたので、その感想です。

# 調べたVPS一覧

- [sakura](https://vps.sakura.ad.jp/)
- [conoha](https://www.conoha.jp/)
- [amazon ec2](https://aws.amazon.com/jp/ec2/)
- [amazon lightsail](https://aws.amazon.com/jp/lightsail/)


## それぞれ調べた所感

### [sakura](https://vps.sakura.ad.jp/)

以前から使っていたものの、改めて見ても良いサービスだなと思いました。
何よりもサーバー１台借りるのに、月◯円でどういう性能のものが借りれるのか、がわかりやすいです。


<img width="1005" alt="スクリーンショット 2019-04-29 22.08.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/d4f8d0c9-e0b0-680d-f1fe-faf9003a377d.png">

今回、dokkuはメモリ1GBはほしいということで、月972円＋初期費用1620円プランを検討しました

### [conoha](https://www.conoha.jp/)

VPSですが、料金体系がクラウドに近く、初期費用はかからないようです。１時間いくらといった形ですが、なぜか月に上限があって、月ごとに見ると定額という、ちょっと変わったサービスです。
<img width="976" alt="スクリーンショット 2019-04-29 22.09.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/96e11be2-60a4-62a8-457e-1c480fc5e88c.png">

メモリ1Gプランは月900円＋初期費用０円ですね

### [amazon ec2](https://aws.amazon.com/jp/ec2/)

みんな知ってるec2は秒単位の課金ですね。で、いくらになるのかなーと見ようと思ったら、「[AWS 総所有コスト (TCO) 計算ツール](https://aws.amazon.com/jp/tco-calculator/)」なるものが出てきて、ここで挫折です。

秒単位だから30日のときと31日のときで値段違うよとか、
データ転送、Elastic IP アドレスは別料金だよとか、
いろいろ条件がごちゃごちゃしすぎてわからん、やめよう　でした。

データ転送量次第ですが、おそらくこれが一番安いというイメージがありますが、検討挫折です。


### [amazon lightsail](https://aws.amazon.com/jp/lightsail/)

ec2に挫折した人におすすめされるのがlightsail。こちらはsakuraやconohaと似たように、月◯円でだいたい入ってるよ！というサービスです。

<img width="991" alt="スクリーンショット 2019-04-29 22.17.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/cb15dace-5ecc-5942-ff69-55c38b25ddcb.png">

わかりやすいですね！
それで料金はこちら。

<img width="1023" alt="スクリーンショット 2019-04-29 22.15.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/65dbde87-dd36-bb91-52fa-53d7b8a4b6ed.png">

1Gメモリだと$5ですね。


## 比較結果

EC2は比較自体に挫折したので、残り３つから選びました。
自分としては、初期費用は何かなーというところで sakura < conohaになって、
２TBでほとんど使い切らないだろうとは思うものの、転送量課金があるのが怖くて lightsail < conohaになりました。

つまりconoha選びました。

## 良さそうなところ/面白かったところ

- 転送量に悩まされない
- 初期費用がない
- 途中で解約したら１時間◯円で計算された分しか払わない
- でも月単位でみたら定額になっててわかりやすい
- sakuraより安い
- 今回の目的であるdokkuはイメージをconoha側で準備してくれていて、ぼたんぽちぽちでデプロイできる
- SSH keyを入れるのに失敗してもwebコンソールからログインできる(<font color="red">**重要!お世話になりました**</font>)
- 簡易的なモニタリングがついている
- UIがわかりやすくて迷わなかった


## あんまりイケてないところ

うーん、あんまり見つからないような・・・。
そもそもVPS提供者にそれほどのこと求めてない、ということもあり、今の所不満は無いです。

## 総合評価


やすい、はやい、うまい　で、今のところ一番オススメできるVPSになっています。
料理はスピードが命で、WEBサーバーはレスポンスが命だ。

テスト投稿です

見出し
# 見出し 1
## 見出し 2
### 見出し 3
強調
**強調**
リンク
[リンク](http://...)
コード

```ruby:filename.rb
コード
```
リスト

- リスト 1
- リスト 2
    - リスト 2-1
1. 番号付きリスト 1
2. 番号付きリスト 2
3. 番号付きリスト 3
- [ ] チェックボックス 1
- [ ] チェックボックス 2
- [x] チェックボックス 3
自分で勝手に考えたmakeに関する便利なalias

# はじめに
普段からMacやUbuntuを使用していて，ターミナルで`make`コマンドをよく使っている．

コンパイルする際に，プログラムのエラーとは関係のなさそうなものがターミナルに出力されることがあり，自分の場合は経験不足もあって，エラーを探すことに一苦労する．

そこで，それを解決するために勝手に２つのaliasを考えた．

また，おまけとしてMacで`find`コマンドをする際のコツも下で述べる．

# エラーのみを出力する
通常，`$ make`とコマンドを実行すると，エラー以外のものもターミナルに出力される．それによって問題である`error`が埋もれてしまうことが多い．解決策として，`error`というキーワードのある行のみをターミナルに出力することを考えた．そのためには，`make`の代わりに以下を実行すると良い．

```bash:make_output_only_error
$ make 2>&1 | grep error
```

そして，これを勝手に`emake`と命名し，`~/.bashrc`に以下を追記した．`emake`だと長いので`emk`というaliasも作成した．

```sh:~/.bashrc
alias emake='make 2>&1 >/dev/null | grep error'
alias emk='emake'
```

# エラーと警告を出力する
上記のaliasではエラーのみしか出力しないのだが，実際には警告も確認したい時がある．そこで，`error`のみでなく`warning`のある行もターミナルに出力することを考えた．そのためには，`make`の代わりに以下を実行すると良い．

```bash:make_output_only_error_and_warning
$ make 2>&1 | grep -e error -e warning
```

そして，これを勝手に`wmake`と命名し，`~/.bashrc`に以下を追記した．`wmake`だと長いので`wmk`というaliasも作成した．

```sh:~/.bashrc
alias wmake='make 2>&1 | grep -e error -e warning'
alias wmk='wmake'
```

# おまけ
Macで`find`コマンドを使用する際に，`Permission denied`という単語がたくさん出てきて，探しているものを非常に探しづらい．その時は，

```bash:bash
$ find . -name filename 2>/dev/null
```

と実行すると，エラー(`Permission denied`)を出力しないでくれるため，非常に便利である．
Java言語におけるクラスとは(3/?)

# はじめに
こんばんは。またたびです。
記事を書き始めて3日目になりました。
今日も頑張ります。

# カプセル化
今日はカプセル化について書いていきます。
作成したクラスに対してアクセスするインターフェースを明確にすることがカプセル化です。
以下にカプセル化の範囲と指定方法を示します。
非常にわかりやすい表が参考文献に記載されているため、そちらを使わせていただきます。

| 名前 | プログラム中の指定方法 | アクセスを許可する範囲 |
|---|---|---|---|
|private|private|自分自身のクラスのみ|
|package private|何も書かない|自分と同じパッケージに属するクラス|
|protected|protected|自分と同じパッケージに属するか、自分の継承をした子クラス|
|public|public|全てのクラス|

これまでmainメソッドを書くときにpublicと付けていたと思いますがこれはカプセル化を用いています。
mainメソッドはプログラムを実行した際に呼び出されるメソッドですので、この部分をprivateにするとエラーになり実行されません。

それではこれから例を用いてstaticの説明をしていきます。
protectedは継承を説明する際に書いていくので今回は触れません。

```java:Num.java
public class Num{
  static int a = 10;
}
```

この時、privateで定義しているフィールドを別クラスのmainメソッドにて呼び出そうとすると、エラーとなり実行されません。
そのためにゲッターとセッターというメソッドを作成します。

```java:Num.java
public class Calc{
  static int a = 10;

  public int getA(){
   return this.a; 
  }
  public void setA(int a){
   this.a = a; 
  }
}
```

このゲッター、セッターメソッドを用いることで、クラスcalcのフィールドaとbの値を呼び出す、書き込むことが出来ます。

面倒くさがって全てをpublicにしていまうと、本当に想定外の場所でフィールドの値が書き換わってしまい、エラーは発生しないので、可能であればフィールドにはprivateを用いたほうがいいと思います。
またこれと同時に、メソッドの引数とクラス内に定義している変数の区別をつけるために、クラス内に定義しているフィールドにはthisをつけたほうがいいと思います。

# おわりに
今日は無気力症候群が発生し、何もしていませんでした。
正直記事を書こうか悩んだくらいです。。。
インプットていないため、アウトプットが出来ず分量が少なくて申し訳ありません。。。
でも気合を入れたら書けたのでこの調子で今後も頑張って書いていこうと思います。
次回は後輩に進捗を聞かれそうなので、最近勉強を始めたVue.jsについて書いていきます。
Vue.jsを知らない方にもわかるよう頑張って書いていきます。
今回の記事にもミスや表現の違い等あればご指摘いただけると幸いです。

# 参考文献
 [スッキリわかるJava入門 第2版 (スッキリシリーズ) ](https://www.amazon.co.jp/%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8BJava%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E4%B8%AD%E5%B1%B1-%E6%B8%85%E5%96%AC/dp/484433638X/ref=zg_bs_515820_1?_encoding=UTF8&psc=1&refRID=JGCC33P1VGV3V5VKQGQR)
Puppeteer を Raspberry Pi (Raspbian) 上で使う

Puppeteer を Raspberry Pi (Raspbian) 上で使う場合

- puppeteerが自動でダウンロードする Chromium は Raspbian では使えない
- puppeteer の最新版は Raspbianにapt-getでインストールできる(あるいははじめから入っている)バージョンの Chromium に対応していない(場合がある)。

そのため puppeteer のバージョンを落とすか、 最新版 puppeteer に対応する Chromium をインストールするか という方法が考えられますが、後者の方法でうまくいく方法が見つけられませんでした。
この記事では puppeteer のバージョンを落とす方を試します。

Raspbian への Node.jsやChromiumのインストール はこの記事では紹介しません。

# 今回使用したバージョン

- Raspbian raspbian-2018-11-15
- Node.js v10.15.1
- Chromium 65.0.3325.181 (後述の方法で確認)
- Puppeteer 1.0.0 (後述の方法で決定)

# Raspbian 上の Chromium のバージョンを確認

まず、Raspbian にインストールされている Chromium のバージョンを確認します。

```shell
$ /usr/bin/chromium-browser --version
Chromium 65.0.3325.181 Built on Raspbian , running on Raspbian 9.8
```

# 対応したpuppeteerのインストール

puppeteer のバージョンを落とすと言っても具体的にどのバージョンまで落とせばいいか・・・
実は公式ドキュメントに対応しているバージョンが書いてあります。

https://pptr.dev/

左上のバージョン部分をクリックすると puppeteer の各バージョンがどのバージョンのChromium に対応しているかの表が見られます。

![puppeteer_versions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21396/a4b05ba4-0baa-9a83-3616-0ca844aacddf.png)

今回の例の場合、Chromiumのメジャーバージョンは65だったので puppeteer は v1.0.0 を使えばいいことがわかります。

npm でインストール時にバージョンを指定してやります。

その際、puppeteer が自動でChromiumをダウンロードしますが、先述通りこれはRaspbianでは使えません。
使わないだけなのでダウンロードされても別に構わないのですがその分無駄な容量を食ってしまうため
Chromiumのダウンロードを無効にする 環境変数`PUPPETEER_SKIP_CHROMIUM_DOWNLOAD`を設定してpuppeteerをインストールすることをおすすめします。

※もし、対応している puppeteer のバージョンが v1.7.0 以上だったら puppeteer-coreを使ったほうがいいです。puppeteer-core は Chromium をダウンロードしません。

```shell
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true npm install puppeteer@1.0.0
```

package.jsonやpackage-lock.jsonからインストールする場合

```shell
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true npm install
```

# Raspbian上で使えるか確認

index.js

```JavaScript:index.js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    executablePath: '/usr/bin/chromium-browser',
    headless: true,
  });
  const page = await browser.newPage();
  await page.goto('https://www.google.com');
  await page.screenshot({ path: 'google.png' });
  
  await browser.close();
})();
```

```shell
$ node index.js
```

撮れたスクリーンショット

![google.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21396/ea938c36-ba85-89c5-c449-99669232eea2.png)

# 参考URL

[Puppeteer](https://pptr.dev/)
[Raspberry Piでpuppeteerを動かす方法](https://qiita.com/kwbt/items/420b3d02456fe24307ec)
[PuppeteerをRaspberry Piで使う - チカラの技術](https://power-of-tech.hatenablog.com/entry/2018/08/16/220252)
[RaspberryPiでpuppeteerを動かす方法 - 新しいことにはウェルカム](https://www.kwbtblog.com/entry/2019/01/23/032245)
IoTでは知っとかないと　python - 数値計算


◼️　mathモジュール 数値計算
>>> import math
>>> math.pow(2,16)
65536.0
>>> math.sqrt(100)
10.0
>>> math.log10(100)
2.0
>>> math.sin(180)
-0.8011526357338304
>>> math.trunc(3.14)
3
>>> math.pi
3.141592653589793
>>> math.e
2.718281828459045

◼️　decimalクラス  from decimal import Decimal
10進浮動小数点：精度の指定、切り捨てなど規則に厳密さが要求される金額計算などに利用
floatの数値演算では誤差が出る!!
>>> b = float(0.1)+float(0.2)
>>> print(b)
0.30000000000000004

Decimalで見ると・・・デフォルト精度は28桁！
>>> Decimal(float(0.1))
Decimal('0.1000000000000000055511151231257827021181583404541015625')
>>> Decimal(float(0.2))
Decimal('0.200000000000000011102230246251565404236316680908203125')
>>> Decimal(float(0.2)+float(0.1))
Decimal('0.3000000000000000444089209850062616169452667236328125')

こういう時に、decimal.Decimal型は、整数、文字列、タプルから作ることができるため、
以下のようなことができる。

>>> a2 = Decimal('0.1')　文字列から０.１を作成
>>> Decimal(a2)
Decimal('0.1')
>>> b2 = float(0.2)　　Floatから０.２を作成
>>> Decimal(b2)
Decimal('0.200000000000000011102230246251565404236316680908203125')

>>> c2 = a2+b2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'decimal.Decimal' and 'float'
b2はfloatなので、型違いでエラーとなる。当然、、、

>>> db2 = Decimal(b2)　　　float型からDecimal型へ変換
>>> c2 = a2+db2
>>> Decimal(c2)
Decimal('0.30000000')
>>> print(c2)
0.30000000

Decimal型を使った計算はfloat型に比べて圧倒的に処理が遅いので、誤差を許さない計算ではない限り、float型を使うことをお勧めします。

◼️　擬似乱数　randomモジュール

>>> import random
>>> a = random.random() ０.０~１.０間のFLOATを返す！
>>> print(a)
0.020502852686773654

>>> b = random.randint(0,10)  ０〜１０間のINTを返す！
>>> print(b)
6

>>> c = random.uniform(0,10) ０〜１０間のFLOATを返す！
>>> print(c)
9.736606666251387

乱数を再現させたい場合は、「seed(x)」を使えば良い！！ 
＃xは１０など適当な定数。省略時は、システムタイムとなる。

>>> c = random.uniform(0,10)
>>> print(c)
5.714025946899135
>>> c = random.uniform(0,10)
>>> print(c)
4.288890546751146
>>> random.seed(10)
>>> c = random.uniform(0,10)
>>> print(c)
5.714025946899135

◼️　特定分布の乱数生成
nomalvariate(mu,sigma)平均mu 標準偏差sigmaの正規分布
gammavariate(k,theta) 形状母数k,尺度母数thetaのガンマ分布

normal_variate = []
gamma_variate = []

for i in range(1000):
    normal_variate.append(random.normalvariate(0,1))
    gamma_variate.append(random.gammavariate(3,1))
機械学習を使ってIrisデータを分類してみた。

#目的
久しぶりの投稿となりました！！
現在、大学の研究室でDeeplearningを使ったClassificationをしていることもあるので基本的な機械学習も合わせて勉強していき、アウトプットしていきたいと思います。
*今回の記事は「PythonによるAI・機械学習・深層学習アプリのつくり方」という書籍を参考にしています。

#手順
(1)データの取り込み
(2)前処理
(3)学習
(4)テスト

###(1)データの取り込み
今回はgithubからデータを落とし込んできました。
以下のサイトからcsv形式でデータを保存します。
https://raw.githubusercontent.com/pandas-dev/pandas/master/pandas/tests/data/iris.csv

```python:iris.py
#アヤメデータの読み込み
iris_data = pd.read_csv("iris.csv", encoding="utf-8")
```
実際に表示して見ると以下のようになります。

![スクリーンショット 2019-04-28 22.05.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284340/1f70cdf3-66df-84cc-72a8-523de957afa4.png)

###(2)前処理
次にこのデータを入力データとラベル(解)に分けましょう。

```python:iris.py
#アヤメのデータをラベルと入力データに分離
y = iris_data.loc[:,"Name"]
x = iris_data.loc[:,["SepalLength","SepalLength","SepalWidth","PetalLength","PetalWidth"]]
```
###(3)学習
それでは実際に学習させてみましょう!!
今回は学習モデルにSVC(SVM Classification)を用いました。

```python:iris.py
#学習
clf = SVC()
clf.fit(x_train, y_train)
```
これで学習することができました。

###(4)テスト
最後に実際にtestデータを使って評価してみましょう。

```python:iris.py
#テスト
y_pred = clf.predict(x_test)
print(accuracy_score(y_test, y_pred))
```

#結果
約97%の成果が出ていますね！！
![スクリーンショット 2019-04-29 12.38.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284340/ca0574e7-30b5-55d5-2e24-374fbc691ec8.png)


#まとめ
以下の手順によってSVCモデルでアヤメのデータを分類することができました。

これからも様々な種類のモデルで遊びスキルをつけていきたいです！！
jetsの開発環境をdocker-composeを利用して、dynamodb(dynamodb-local, dynamodb-admin)も使いたい

## 前提条件
api-modeで利用しているので、front周りを触るなら、他の記事を参考に変更する必要があるかもしれない

```yml:docker-compose.yml
version: '3.3'
services:
  jets:
    stdin_open: true
    build: .
    volumes:
      - .:/usr/src/app
      - volume-config:/usr/src/app/.bundle
      - volume-gem:/usr/local/bundle
      # deploy時にここをキャッシュしておくと早い
      - volume-tmp-jets:/tmp/jets
    ports:
      - "8888:8888"
    command: ["jets", "server", "--host", "0.0.0.0"]
    environment:
      - AWS_ACCESS_KEY_ID
      - AWS_SECRET_ACCESS_KEY
      - AWS_REGION
    depends_on:
      - dynamodblocal
  dynamodblocal:
    build: ./containers/dynamodb
    volumes:
      - volume-dynamodb_data:/home/dynamodblocal/data
    command: ["-jar", "DynamoDBLocal.jar", "-dbPath", "./data", "-port", "8002"]
    ports:
      - "8000:8002"

  dynamodbadmin:
    image: instructure/dynamo-local-admin
    ports:
      - 8001:8001
    environment:
      DYNAMO_ENDPOINT: http://dynamodblocal:8002
      # jetsで利用しているkeyと同じにしないと閲覧できない
      AWS_REGION: ${AWS_REGION}
      AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
    depends_on:
      - dynamodblocal

volumes:
  volume-gem:
    driver: 'local'
  volume-config:
    driver: 'local'
  volume-tmp-jets:
    driver: 'local'
  volume-dynamodb_data:
    driver: 'local'
```

## ハマりどころ
- jetsで利用しているdynomite(ORM的なもの)がdynamodbのendpointにport:8000が設定されていると、ローカル起動とみなし、チェックをするようになっている([127.0.0.0:8000で利用してないとローカル起動チェックでコケる](https://github.com/tongueroo/dynomite/blob/e58476c3f794a7e0926b2707eb480ce5b793cb9d/lib/dynomite/db_config.rb#L46))
  - そこで、dynamodb-localの-portオプションで、8000以外で起動することで回避する
  - 2019/04/29 現在の状況
- dynamodb-adminでREADMEの通りに起動しても、jetsから作成したtableが閲覧できない
  - AWSの[アクセスキー](https://github.com/aaronshaf/dynamodb-admin/blob/f909e48446eadd9401878dd4095cb260f3f4c1e3/lib/backend.js#L74)と[リージョン](https://github.com/aaronshaf/dynamodb-admin/blob/f909e48446eadd9401878dd4095cb260f3f4c1e3/lib/backend.js#L70)を見ているようで、それをJETSで利用しているものと合わせないと閲覧できなかった。
- AWSのクレデンシャル情報は適当で入れても、dynamodb-adminは大丈夫だったけれど、jetsの方で、フォーマットが正しくないと怒られたので、本番で利用している(deployで利用)ものをそのまま環境変数で渡して利用している

## 参考URL
[dynamodb-admin/backend.js at f909e48446eadd9401878dd4095cb260f3f4c1e3 · aaronshaf/dynamodb-admin](https://github.com/aaronshaf/dynamodb-admin/blob/f909e48446eadd9401878dd4095cb260f3f4c1e3/lib/backend.js)
[dynomite/db_config.rb at e58476c3f794a7e0926b2707eb480ce5b793cb9d · tongueroo/dynomite](https://github.com/tongueroo/dynomite/blob/e58476c3f794a7e0926b2707eb480ce5b793cb9d/lib/dynomite/db_config.rb)
[Docker（Docker Compose）から DynamoDB Local を使う際にデータを永続化する - Qiita](https://qiita.com/okashoi/items/f1c757279574d37b812e)
[【dynamodb】ローカル環境のデータをGUIで確認するまで - Qiita](https://qiita.com/mk-tool/items/dd3f97611dd8b4723929)
CentOS7にEFLTKをインストール

[RTAI-Lab tutorial: Scilab, Comedi, and real-time control](https://www.rtai.org/userfiles/downloads/RTAILAB/RTAI-Lab-tutorial.pdf)の「2.3 EFLTK library」の内容です。

#### ソースコードの入手

チュートリアルでは、SVNで取得する手順になっているが、リポジトリが移動?していたので、直接 https://sourceforge.net/projects/ede/files/ から最新のバージョン( efltk-2.0.8.tar.gz, ede-2.1.tar.gz )を取得。

#### ビルド時のエラー1

チュートリアル記載の順に

```
# autoconf
# ./configure --disable-mysql --disable-unixODBC
# ./emake
```

とすすめたところ、以下のエラー。

```
filename_list.cpp: 関数 ‘int fl_filename_list(const char*, dirent***, int (*)(dirent**, dirent**))’ 内:
filename_list.cpp:62:71: エラー: ‘int (*)(const void*, const void*)’ から ‘int (*)(const dirent**, const dirent**)’ への無効な変換です [-fpermissive]
     return scandir(dir, list, 0, (int(*)(const void*,const void*))sort);
                                                                       ^
In file included from /usr/src/efltk/efltk/filename.h:49:0,
                 from filename_list.cpp:35:
/usr/include/dirent.h:255:12: エラー:   initializing argument 4 of ‘int scandir(const char*, dirent***, int (*)(const dirent*), int (*)(const dirent**, const dirent**))’ [-fpermissive]
 extern int scandir (const char *__restrict __dir,
```

エラーチェックが働きすぎているようなので、エラーチェックを止めようとする。

```
# ./configure --disable-mysql --disable-unixODBC CXXFLAGS='-fpermissive'
```

上記でうまくいないので、「configure」ファイル内のCFLAGSと、CXXFLAGSに'-fpermissive'を追加して再度、ビルド。

#### ビルド時のエラー2

```
In file included from Fl_Png.cpp:5:0:
/usr/include/png.h:857:16: エラー: forward declaration of ‘png_struct {aka struct png_struct_def}’
 typedef struct png_struct_def png_struct;
```

はじめのエラーは抜けられたが、別のエラーで止まった。調べてみたところ、libpngのインタフェースが途中(1.5.x ?)で変更になった事が原因のよう。古いインタフェースのlibpngを追加インストール。

```
# yum install libpng12-devel
```

古いlibpngの指定を、環境変数や、configureのオプションでやりたかったけど、上手くいかないので、思い切って、``src/images/Fl_Png.cpp``の、``#include <png.h>``を``#include <libpng12/png.h>``に変更して切り抜けた。

上記で、ビルドが最後まで通るようになりました。
Mac mini 2018 + bootcamp + eGPU(vega 56)

###■ハードウェア
・mac mini 2018 (i7 memory 8G SSD 256G)
・グラボ(msi radeon rx vega 56 air boost 8g oc)
・eGPUケース（Razer Core X）

###■OS/起動関連作業
1. mac osにて、EFI Boot用パーティション作成し、FAT(FAT16)でフォーマットする
2. [automate-eGPU EFI](https://egpu.io/forums/mac-setup/automate-egpu-efi-egpu-boot-manager-for-macos-and-windows/)を上記EFI Boot用パーテイションにコピーする
3. bootcampでwindows10をインストールする
4. mac mini 起動と同時にoptionキーを長押しし、bootメニューが表示され、そしてEFI Bootを選んで、Windowsを起動できることを確認する
※以下Windows起動とは、EFI BootよりWindowsを起動することを指す

###■eGPUインストール
1. Windows起動し、デバイスマネージャーで、以下赤枠で示したデバイスを禁止する
![PCIE禁止.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407825/8a7cdc3d-8846-84ce-dc35-6cef3d79513b.png)


*禁止する理由は、eGPUは接続してから、リソース不足によりerror 12が表示されることがあるため、上記を禁止することにより、リソースの競合が回避できると思われる*
2. eGPUを接続し、普段通りにドライバーをインストールする

###■eGPU + iGPU両方生かして使う方法
1. eGPUをmac miniに挿し込み、eGPUの電源をOnにする
2. mac mini 電源onしてすぐoptionキー長押する
![IMG_3329.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407825/6f3b94b9-14bc-8dbb-f37a-5d6b6cbfaefc.jpeg)
3. BootメニューからEFI Bootを選択する
4. EFI Bootの画面に、GPUが2つ検出されたことを確認する
![IMG_3330.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407825/1b9cb59a-e45b-d53d-d542-41800f6023bb.jpeg)
上図のように、[0x8086 0x3E9B]が1つのGPU（=iGPU）で、[0x1002 0x687F]が2つ目のGPU（eGPU）となります。
16進数はGPUのメーカーによって変わると思われます。~~

5. Windowsを起動する
6. Windowsログインしてから、eGPUがエラーなく使用できる状態にあることを確認する
①Radeonグラボの場合、ログインしてから少し時間たったら下記通知が表示されるはず
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407825/ad053ea2-3c4b-4d8a-d32f-d2c09afc7b40.png)
②デバイスマネージャーにてiGPUとeGPU両方が正常状態にある
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407825/5d4ae40c-06a0-1234-4216-46c830e6224e.png)
③eGPUはPCIe Controller (×8)の下にぶら下がることが正しい
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407825/2e89ec62-d7c0-80b9-0d92-8bbbd21ac564.png)

###■eGPU だけ生かして使う方法
1. eGPUをmac miniに挿し込み、eGPUの電源をOnにする
2. mac mini 電源onしてすぐoptionキー長押する
3. BootメニューからWindowsを選択する
4. Windowsを起動する
※bootcampの設定で、デフォルトでwindows起動になっているなら、2. 3.は不要
zstandardを軽く調べておく

#LZ4さんは負けました？
なんか調べていくと、zstandardが現状かなりいい感じらしい、ということが分かってきたので、これを調べることに。

LZ4に関しては、ここが一番わかりやすいと思います！
https://www.slideshare.net/komiyaatsushi/dsirnlp-3-lz4

#zstandardとは？

http://facebook.github.io/zstd/

> Zstandardは、リアルタイム圧縮アルゴリズムであり、高い圧縮率を有する。非常に高速なデコーダによって、非常に広範囲の圧縮率/速度のトレードオフを提供します。また、圧縮辞書と呼ばれる小さなデータのための特別なモードによって、どんなサンプルセットからでも辞書を作成できる。ZstandardライブラリはBSDライセンスを使ったオープンソースソフトウェアとして提供されている。

# どんなアルゴリズムなの？

アルゴリズムは、RFC8478として公開されている。
えっとですねえ…

https://mag.osdn.jp/16/09/01/163000
http://fastcompression.blogspot.com/2013/12/finite-state-entropy-new-breed-of.html

多分、こんな感じの話。

エントロピー via シャノン
↓
ハフマン符号化(整数のビット数を使用する制限付き）
↓
算術符号化(1bit未満で表現できるが、特許問題などなど＋複雑すぎる実装）
↓
↓　Jarek DudaのANS理論
↓　↓
有限状態エントロピー（1bit未満で表現できるうえに、除算などを含まないロジック）

となったと。

もっともっと詳しいのはこのあたり

https://en.wikipedia.org/wiki/Asymmetric_numeral_systems#Tabled_variant_(tANS)

と、今日はここまで…。
リスト内包表記を使いこなす

# リスト内包表記とは？ List Comprehensions
複雑な値を持つリストやタプル・辞書型を生成するための表記方法。

```python
>>> [i for i in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> [i for i in range(10) if i % 2 == 0]
[0, 2, 4, 6, 8]

>>> list_str = ["abc", "def", "ghi"]
>>> [s[0] for s in list_str]
['a', 'd', 'g']
```
プログラミング学習記録72〜女性ボイス〜

##今日やったこと
- Progate JavaScript4リセット復習
- ドットインストール「初めてのJavaScript」を一通りやる

昨日やったProgateのJavaScript4をリセット復習でもう一度やってみました。
クラスの継承やオーバーライドを昨日よりも理解できた気がします。

あと、ドットインストールのプレミアム会員（有料会員）にしてみました。

プレミアム会員では、女性ボイスで動画を見ることができます。

正直、男性ボイスでも女性ボイスでもそこまで変わらないだろうと思っていたのですが、思った以上に女性の声が聴きやすくてよかったです。

男性ボイスでもそうなのですが、通常「〜しましょう」と言うところを「〜してあげましょう」と言ってるのが、若干気になりなるぐらいで、あとは全く問題ないです。

話してる内容もテキストで動画の下に表示されているのもありがたいですね。

<br>
文法の基礎を復習しつつ、簡単なミニアプリをドットインストールの動画を見ながら作っていきたいと思います。

おわり
CentOS7でRTAI-Lab

HILS(Hardware In the Loop Simulation)環境を低コストで作成しようとしています。

RTAI-Labとして公開されている、リアルタイムで動くモデル環境を作り、モータ等のモデルを作って動かす事を考えています。

[RTAI - the RealTime Application Interface for Linux - About RTAI-Lab](https://www.rtai.org/?About_RTAI-Lab)で公開されているチュートリアルに従って、環境構築を進めていきます。
( RTAIは一度インストールしてから、このチュートリアルを知ったので、飛ばす所はでてきます。 )

- [Mesaをインストール](https://qiita.com/ProjectM_TACCMI/items/78bc982bc399f13d61bd)
- [EFLTKをインストール](https://qiita.com/ProjectM_TACCMI/items/13abad43f40c811c8063)
- [Comediをインストール](https://qiita.com/ProjectM_TACCMI/items/aabf1a324b03ccf3813b)
- [RTAIのComedi,EFLTK有効化](https://qiita.com/ProjectM_TACCMI/items/8c12c40b1e52d1a1564c)
- [Scilab/Scicosのビルド](https://qiita.com/ProjectM_TACCMI/items/000a2fbcce1f7ed6a89a)
- [RTAIブロックからコード生成](https://qiita.com/ProjectM_TACCMI/items/18dcb06aa17b0390a494)
- 続きます
CentOS7にMesaをインストール

[RTAI-Lab tutorial: Scilab, Comedi, and real-time control](https://www.rtai.org/userfiles/downloads/RTAILAB/RTAI-Lab-tutorial.pdf)の「2.2　Mesa library」の内容です。

http://www.mesa3d.org より 6.5.3のソースコードを入手。19までメジャーバージョンが上がってましたが、チュートリアルに従い、メジャーバージョンが6の最新版を選びました。

ソース展開後、`make realclean`して、`make linux-x86-64`を実行。

**-64**を入れないと、途中でエラーになりました。64ビット環境の場合は、**-64**が必須のようです。
EKSハンズオン：Pod 作成

# 目次はこちら
[EKS ハンズオン：目次](https://qiita.com/asahi0301/items/3b908be2818581d3feb8)

# TL;DR
Kubernetes(以降、k8s)で動くコンテナの最小単位をPodといいます。
このハンズオンではPod(コンテナだけ作成します)

# サンプルコード
こちらに載せています
[github](https://github.com/asahi0301/eks-handson/tree/master/pod-handson)


# nginxコンテナを作成する


```shell

kubectl apply -f pod-nginx.yml 
pod/nginx-pod created
```

これでnginx コンテナが立ち上がります。
確認してみましょう

```sh
kubectl get pods
NAME        READY     STATUS    RESTARTS   AGE
nginx-pod   1/1       Running   0          94s


kubectl get pod nginx-pod -o wide
NAME        READY     STATUS    RESTARTS   AGE       IP               NODE                                          NOMINATED NODE
nginx-pod   1/1       Running   0          2m44s     192.168.52.183   ip-192-168-56-26.us-west-2.compute.internal   <none>
```

nginx-podという名前のコンテナが一台、ip-192-168-56-26.us-west-2.compute.internal というworker node(EC2)上に起動していることが分かります。

# コンテナを削除する
作成したコンテナを削除します。

```sh
kubectl delete -f pod-nginx.yml                                                                
pod "nginx-pod" deleted


kubectl get pods
No resources found.
```

はい、コンテナが削除されました。

# まとめ
コンテナを作って消すという単純なハンズオンでしたが、ymlファイルを作成して、applyする(削除する場合はdeleteする)。これが全てのk8s オペレーションの基本となります。
次回は、Deploymentというコンテナのアップデートやロールバックといったデプロイ管理の仕組みのハンズオンを行います