最低限のjavascript開発環境を作って公開した

三行

  • yarn, gulp, babel, webpack, React, ESlintを使って,最低限のjavascript開発環境を作った
  • 最低限 = ES6で書いたものがコンパイルされてブラウザで見れる状態
  • 最適な環境なのかはわからないが,とりあえず開発できる

作ったもの

github.com

使い方

$ git clone https://github.com/johshisha/js_development
$ cd js_development
$ yarn
$ yarn start
$ open http://localhost:8080/webpack-dev-server/index.html

buildの仕方

$ yarn start build

参考文献

基本的にこれを参考にさせてもらった
これの8章までに webpack-dev-server を加えた形 qiita.com

webpack-dev-server dackdive.hateblo.jp 補助:
Webpack-stream WITH Gulp WITH webpack-dev-server?? · Issue #121 · shama/webpack-stream · GitHub usage with gulp

HMR

blog.mismithportfolio.com

詰まった点

Hot Module Replacement (HMR)がうまく動作しない

webpack-dev-serverでHMRをしようとおもい, hot: trueにしたが,うまく動作しなかった
HMR: リロードせずとも,変更のあった部分だけ更新してくれる機能

  • 原因
    設定が正しく出来ていなかった

  • 解決法
    github.com

それでもHot Module Replacement (HMR)がうまく動作しない

f:id:johshisha:20171013045720p:plain こういう変更をリロード無しで更新してくれることを期待していた

Before

const App = () => (
  <div>
    Hello world!
  </div>
);

After

const App = () => (
  <div>
    Hello world!!!!!!!!!!!!!!!!!
  </div>
);
  • 原因
    HMRを万能なものと思いすぎていた
    すべての変更に対応しているわけではなく,HMRに対応している変更としていない変更がある

  • 解決法
    ファイルを分割してReact ComponentにすることでComponent内の変更はHMRに対応することができた
    このあたりの仕組みまでは理解できていないので,理解する必要がある.
    ↓こんな感じに分割した https://github.com/johshisha/js_development/blob/master/src/client/Message.jsx

class Message extends Component {
  render() {
    return (
      <div>
        Hello world!
      </div>
    );
  }
}

コンポーネントとか期待してたのに, undefinedが返ってきてるじゃん!というエラー

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in.
  • 原因
    importの仕方を間違っていた

  • 解決法

- import { Message } from './Message';
+ import Message from './Message';

RaspberryPiにDocker環境を整える[docker+docker-compose]

参考資料 blog.hisurga.com

この資料にそってやるのがいいかと

一応コマンドだけ残しておく(同じことしている)

dockerのインストール

$ curl -sSL https://get.docker.com | sh
$ sudo usermod -aG docker [username] # root以外でもdocker使えるようにする

一旦ログアウトする

動作確認

$ docker run -d -p 80:80 hypriot/rpi-busybox-httpd

clientから,ブラウザでraspberry piのIPにアクセスすると画像が表示されればOK

docker-composeのインストール

なぜかエラーが出た.. が,docker rmiしてからやり直すといけた

$ git clone https://github.com/docker/compose.git
$ cd compose
$ cp -i Dockerfile Dockerfile.armhf
$ sed -i -e 's/^FROM debian\:/FROM armhf\/debian:/' Dockerfile.armhf
$ sed -i -e 's/x86_64/armel/g' Dockerfile.armhf
$ docker build -t docker-compose:armhf -f Dockerfile.armhf .
$ docker run --rm --entrypoint="script/build/linux-entrypoint" -v $(pwd)/dist:/code/dist -v $(pwd)/.git:/code/.git "docker-compose:armhf"

Raspberry Pi 3インストールから初期設定まで

インストール

今回は,2017-04-10-raspbian-jessie-lite.imgを使用しました. 各自公式からダウンロードしてきてください.

SDのフォーマット

SDを挿入してから,DiskUtilityを開いて,該当SDを初期化します. 右クリックして,「削除」を選択し,名前をつけて削除すると完了.

SDへ書き込み

$ diskutil list
...
/dev/disk4 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *31.0 GB    disk4
   1:                 DOS_FAT_32 RASPBIAN                31.0 GB    disk4s1

該当のSDを見つけます. 以下のコマンドを実行し,SDに書き込む.(10分ほど?適当に放置して待ちましょう)

$ diskutil unmountDisk /dev/disk4
$ sudo dd if=path/to/file/2017-04-10-raspbian-jessie-lite.img of=/dev/disk4 bs=1m

以上を行うと準備は完了なので,RaspberryPiに挿入して電源を入れましょう

初期設定

初期のパスワード

user name: pi
password: raspberry

rootのパスワード設定

sudo passwd root

以下からはrootで行う

$ su -
password

Wifiの接続

$ export PASSWORD=password
$ export SSID=wifi-ssid
$ wpa_passphrase $SSID $PASSWORD >> /etc/wpa_supplicant/wpa_supplicant.conf

Time Zoneの設定

$ raspi-config

「4 Localisation Options」-> 「I2 Change Timezone」->「Asia」-> 「Tokyo」

SSHの有効化

$ raspi-config

「5 Interfacing Options」-> 「P2 SSH」->「Yes」

接続先IPは以下で確認

$ ip route
default via 192.168.1.1 dev wlan0  metric 303
192.168.1.0/24 dev wlan0  proto kernel  scope link  src 192.168.1.42  metric 303

今回の場合は192.168.1.42となります.

$ ssh pi@192.168.1.42

で接続できるはずです

おまけ

SSHのポート変更

/etc/ssh/sshd_configのPort 22を変更する

ユーザの追加と削除

追加

$ sudo adduser hoge
$ sudo gpasswd -a hoge sudo

削除

$ sudo userdel pi

公開鍵認証

$ ssh-keygen -t rsa
$ scp -P [port_number] ~/.ssh/id_rsa.pub [username]@[ip]:
$ ssh -P [port_number]  [username]@[ip]

raspberrypi側で,

$ mkdir .ssh
$ mv ~/id_rsa.pub ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys
$ sudo service ssh restart

ローカルのマシンの別ターミナルで

$ ssh -p [port_number] -i ~/.ssh/id_rsa [username]@[ip]

うまくsshできることが確認できたら

raspberry側で,

$ sudo vim /etc/ssh/sshd_config
- # PasswordAuthentication no
+ PasswordAuthentication no

と変更する

ssh configの設定

~/.ssh/configに以下を追記

Host raspberry
    Hostname [ip]
    Port [port_number]
    User [username]
    IdentityFile ~/.ssh/id_rsa

これを記載することで,sshを簡単にできる

$ ssh -p [port_number] -i ~/.ssh/id_rsa [username]@[ip] # 通常はこれ
$ ssh raspberry # configを設定することで簡略化できる

firewall

$ sudo apt-get install ufw -y
$ sudo ufw default deny
$ sudo ufw allow 80/tcp
$ sudo ufw allow [ssh port_number]
$ sudo ufw enable

docker関連のerrorと対処法集

dockerを勉強し始めて,詰まった部分などを書き溜めていく.
同じエラーで詰まった人の助けになれば幸いです.
エラーに遭遇する度に追加していく予定

tips

  • 何かしらのエラーでうまく動かないときは,docker logs [container id]でログを見ることができる.

  • unicornのエラーは標準出力には出力されなかったので,直接エラーログファイルを見に行く必要があった.
    例えば,以下のようなエラーの場合は,unicorn系のエラーだったのでrun bashで内部に入って,同様のコマンドを実行してエラーログファイルを参照した.

[error] 5#5: *11 connect() to unix:/share/unicorn.sock failed (111: Connection refused) while connecting to upstream, client: 192.168.99.1, server: , request: "GET / HTTP/1.1", upstream: "http://unix:/share/unicorn.sock:/", host: "192.168.99.104"
  • eval $(docker-machine env default)
    dockerの接続先を指定するためのコマンド.(この場合は指定先をdefaultにするコマンド)
    ターミナルが変われば,この接続先は再指定する必要がある.
    逆に,ターミナルごとに接続先を指定できる.
    docker-machine lsでACTIVEにマークがついているかちょくちょく確認したほうがよい.

docker-machine起動関連のエラー

  • error
$ docker-machine env default
Error checking TLS connection: Host is not running
  • 解決法
    docker-machineが起動していなかった.
$ docker-machine start default

  • error
$ docker-machine env default
Error checking TLS connection: Error checking and/or regenerating the certs: There was an error validating certificates for host "192.168.99.101:2376": x509: certificate is valid for 192.168.99.100, not 192.168.99.101
You can attempt to regenerate them using 'docker-machine regenerate-certs [name]'.
Be advised that this will trigger a Docker daemon restart which might stop running containers.
  • 解決法
    前起動していたときとIPが変わっているために発生するエラー.
    エラー文に書いているが,
$ docker-machine regenerate-certs default
Regenerate TLS machine certs?  Warning: this is irreversible. (y/n): y
Regenerating TLS certificates
Waiting for SSH to be available...
Detecting the provisioner...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...

これで起動する.


  • error
$ docker-machine regenerate-certs default
Regenerate TLS machine certs?  Warning: this is irreversible. (y/n): y
Regenerating TLS certificates
Waiting for SSH to be available...
Too many retries waiting for SSH to be available.  Last error: Maximum number of retries (60) exceeded
  • 解決法
    docker-machineを起動していない.
$  docker-machine start default && docker-machine regenerate-certs default

docker/docker-machine/docker-compose/docker-swarmを学ぶときにわかりやすかった資料達

なにか

Dockerって開発環境構築するときに使うとナウいんでしょ?程度の知識しかない初心者が,Dockerについて学んだときにわかりやすかった資料をまとめたものです.

上から順に読んでいくとわかりやすいと思います.

docker

一言で言うと,dockerはバージョン管理しながらプロセス単位で仮想化するもの

1〜6まである.仮想化とは?から順にdockerのメリットややっていることが理解できる. qiita.com

docker-machine

一言で言うと,docker-machineはdockerの開発環境を作るもの&管理するもの(virtualenv的なもの?).

knowledge.sakura.ad.jp

docker-compose / docker-swarm

一言で言うと,docker-composeは複数のdockerコンテナを管理するもの. docker-swarmは複数のマシンでdockerコンテナを管理するもの.

https://www.slideshare.net/zembutsu/introduction-to-docker-compose-and-swarm

dockerの問題点

Dockerの諸問題とRocket登場の経緯 | SOTA

以下使用に関する記事

dockerのコマンド

qiita.com

dockerの使用例

dockerfileの開発Tips

qiita.com

Dockerfile のベストプラクティス — Docker-docs-ja 1.9.0b ドキュメント

nginx + mysqlで簡易アプリ作成(みただけ)

qiita.com

docker-machine + docker-compose + docker-swarmの使用例(ちょっと古い)

qiita.com

サービス開発参考

qiita.com

pandas便利な使い方メモ(随時更新)

pandasの便利な使い方を毎度調べたり試行錯誤したりするのは効率が悪いのでここに雑に書き溜める。
もしおすすめの使い方やもっと効率のいい方法などあれば教えていただきたいです!

DataFrame内のあるカラムにある文字列が含まれている行だけ取り出す

要は'hoge' in textTrueになる行だけ選択してくる。

df[df['text'].apply(lambda x: 'hoge' in x)]

同じ要領で、キーが複数ある場合。('hoge', ‘huga’, ‘hogu'で選択してきたい場合)

df[df['text'].apply(lambda x: any([key in x for key in ['hoge', 'huga', 'hogu']))]

あるカラムがnullだったら削除する

df = df.drop(df[df['nanika'].isnull()==True].index)

csv読み込み

df = pd.read_csv(path, names=('hoge', 'huga', 'hogu'), delimiter='nanika')

merge

new = pd.merge(df1, df2, left_on='hoge', right_on='hoge') # カラムの値が一致するものでマージする

shuffle

df = df.reindex(np.random.permutation(df.index))

(おまけ)numpy編

条件に一致するものだけ置換する

値が5以上のものを0に置換する

x[ x >= 5 ] = 0

pandasで値の順位を取得したい(おまけにソート方法いろいろ)

pandasでDataFrameにorderを付与したいときのメモ

状況

↓こういうDataFrameに対して、testカラムの値が並び替えた時に何番目になるのかを知りたい

   test
0     1
1     4
2     6
3     3
4     2
5     7
6     9

具体的には、こういう結果がほしい

   test  order
0     1      0
1     4      3
2     6      4
3     3      2
4     2      1
5     7      5
6     9      6

値で並び替える方法はたくさんあるし、並び替えた時に何番目にすればいいのかのindexを取得してくる方法もたくさんあるが、 並び替えた時に何番目になるのかを取得してくる方法が意外となかった。(みんな考えるまでもないのだろうか?)

解決方法

追記

以前の方法(↓に書いてある方法)では同値を適切に扱えてなかった。 scipyを使うとめちゃくちゃカンタンにできた。 stats.mstats.rankdataという関数がそれ。

from scipy import stats
test = np.array([1,4,6,3,2,7,6])
a=pd.DataFrame(test, columns=(['test']))
a = a.assign(order=stats.mstats.rankdata(a.test))

で実現できる

以下のような出力が得られる。同値は小数で表示される。 (この例の場合、indexが2と6のところで5位タイが存在するが、5.5位として表示される)

   test  order
0     1    1.0
1     4    4.0
2     6    5.5
3     3    3.0
4     2    2.0
5     7    7.0
6     6    5.5

以下追記前の方法

(雑だが)aというDataFrameのtestカラムで並び替えた時の順位が知りたい場合、

np.argsort(a.sort_values('test').index)

で取得できる。

全体はこんな感じ

test = np.array([1,4,6,3,2,7,9])
a=pd.DataFrame(test, columns=(['test']))
a = a.assign(order=np.argsort(a.sort_values('test').index))

上のような結果が得られる。

おまけ

単純に並び替える

>>> a.sort_values('test')
   test
0     1
4     2
3     3
1     4
2     6
5     7
6     9

並び替えた時のインデックスを取得

たまにインデックスだけほしくなる。

>>> a.sort_values('test').index.values
array([0, 4, 3, 1, 2, 5, 6])

こうすれば並び替えることができる。

>>> [a.get_value(i, 'test') for i in a.sort_values('test').index]
[1, 2, 3, 4, 6, 7, 9]

こういう用途であればそもそもこれで完結するが、

>>> a.sort_values('test').test.values
array([1, 2, 3, 4, 6, 7, 9])

以上、メモでした。