Dockerメモ

やったこと

  • 事前準備

    • DockerをUbuntu上にインストール
      • 以下の記事を参考にインストール
        • しかし、記事の注意事項に書いてあるとおり商用版Docker EEをリリースしたことにより無償版はDocker CEに名称変更。
          • これにより、パッケージ名がdocker-engineからdocker-ceに。インストール手順はほぼ変らないが、気持ち悪いのでアンインストールして再度ceをインストールし直した。
      • non-root userでDockerをwork betterにするための設定
      • 自動起動の設定はしなかった
  • 講座・ハンズオン

    • Dockerの仕組みのかんたんな紹介
    • Dockerを使うために最低限理解しておくこと
    • Step.1 公開されているイメージを使う
      • MySQL5.6
      • MySQL5.7
    • Step.2 Dockerfileからイメージを作成し使う
      • サンプルのDockerfileからphpを実行するAPコンテナを作成
    • Step.3 イメージを組み合わせて使う
      • サンプルのDockerfileからWebサーバ環境(コンテナの組合せ)を作成

インストール

1. アンインストール

  • まず、インストールしてしまったdocker-engineをアンインストール
sudo apt-get purge docker-engine
sudo rm -rf /var/lib/docker

2. SET UP THE REPOSITORY

dockerの公式ドキュメントの通りにインストール

https://docs.docker.com/install/linux/docker-ce/ubuntu/#uninstall-docker-ce

  • Update the apt package index:
sudo apt-get update
  • install packages to allow apt to use a repository over HTTPS:
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
  • Verify that you now have the key with the fingerprint
sudo apt-key fingerprint 0EBFCD88

pub   4096R/0EBFCD88 2017-02-22
      Key fingerprint = 9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid                  Docker Release (CE deb) <docker@docker.com>
sub   4096R/F273FCD8 2017-02-22
  • Set up the stable repository
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

3.INSTALL DOCKER CE

  • Update the apt package index.
sudo apt-get update
  • Install the latest version of Docker CE
sudo apt-get install docker-ce
  • Verify that Docker CE is installed correctly by running the hello-world image.
sudo docker container run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

4. non-root userでDockerをwork betterにするための設定

以下の理由より、インストールしただけだとsudoを常にしないいけなにので、めんどう

The Docker daemon binds to a Unix socket instead of a TCP port. By default that Unix socket is owned by the user root and other users can only access it using sudo. The Docker daemon always runs as the root user.

  • Create the docker group
sudo groupadd docker
  • Add your user to the docker group
sudo usermod -aG docker $USER
  • Log out and log back in so that your group membership is re-evaluated

  • Verify that you can run docker commands without sudo

docker run hello-world

基本コマンド

systemctlコマンド

  • docker service起動
❯ systemctl start docker.service
  • docker service停止
❯ systemctl stop docker.service
  • docker service ステータス確認
❯ systemctl status docker.service

dockerコマンド

  • Dockerfileからイメージをビルド
    • ${PATH}はDockerfileがあるパス
docker build -t ${REPOSITORY}[:${TAG}] ${PATH}
  • コンテナ起動、停止、再起動
docker start | stop | restart ${コンテナID}
  • 起動中のコンテナプロセス表示(-aオプションで停止中のプロセスも表示)
docker ps
  • コンテナのログを表示
docker logs ${コンテナID}
  • コンテナ内でコマンド実行
docker exec ${コンテナID} ${コマンド}
  • コンテナへのログイン
    • exec はすでに起動しているコンテナでコマンドを実行する。 run コマンドは新たにコンテナを起動してからそのコンテナでコマンドを実行する。
docker exec -it ${コンテナID} bash
  • コンテナ削除
    • 削除前に対象コンテナの停止が必要
docker rm ${コンテナID}
  • イメージを削除
docker rmi ${イメージID}
  • Run a Docker Container
    • runコマンドはコマンド実行中のみコンテナを起動。コマンド実行終了後にはコンテナはendする。
docker run ${イメージ名 || イメージID} ${command to run into container}
  • e.g. catコマンドを実行
docker run ubuntu cat /etc/issue
  • 初回の動作確認
❯ sudo docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
  • Run an Interactive Session into a Container
    • いわゆるコンテナへのログイン
    • -i : start an interactive session
    • -t : allocates a tty and attaches stdin and stdout
    • ubuntu : the image that we used to create the container
    • bash (or /bin/bash) : the command that we are running inside the Ubuntu container
docker run -it ubuntu bash
  • 起動しているコンテナのセッションからhostのターミナルに戻るには2通りある。
    • 1 exit
      • exit はコンテナの全てのセッションを終了して、そのコンテナ自体も停止させる
    • 2 Ctrl+p or Ctrl+q
      • セッションを維持しつつ、hostのターミナルに戻りたい場合はこのキーを使う
      • 新規セッションを作ってこのキーで出たりを繰り返すと、その分だけコンテナが起動しセッションも生成されてしまうので注意。元のセッションへの戻り方は次の項目に記載
❯ docker run -it ubuntu bash
root@7519130e117b:/# exit
exit

~
❯ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

~
❯ docker run -it ubuntu bash
root@f0dffe57d9ce:/#   
~ 27s
❯ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
f0dffe57d9ce        ubuntu              "bash"              31 seconds ago      Up 29 seconds                           friendly_stonebraker
  • 再度、コンテナに戻る方法
    • まず、 docker ps でID or nameを確認する。
    • そして以下のコマンドで元のセッションのコンテナに接続し直す
    • exec でコンテナに入るのと同じこと?
docker attach ${コンテナID or name}
  • 稼働しているコンテナをホストから停止する
docker kill ${コンテナID or name}

docker-composeコマンド

  • 複数イメージを組合せたコンテナ群(docker-compose.yml)を起動
docker-compose up -d
  • docker-composeで起動した各コンテナの状態を確認
docker-compose ps
  • コンテナ群の起動、停止、再起動
docker-compose start | stop | restart
  • コンテナを停止して、削除
docker-compose down

Docker用語

  • Dockerイメージ
  • Dockerコンテナ

ハンズオン

Step.1 公開されているイメージを使うパターン

  • mysqlのイメージを使う
  • 使い方はdocker hubのイメージのページにだいたい書いてある
  • 実際にpullするイメージのDockerfileはGithubで確認できる

https://hub.docker.com/_/mysql

1. mysqlのdockerイメージ取得

  • docker hubのページでsupportされているタグを確認
  • タグ指定無しはバージョンlatast扱いになる
  • debianベースのmysqlサーバー

  • 構文

docker pull ${REPOSITORY}[:${TAG}]
  • バージョン(5.6)を指定してdockerイメージを取得
docker pull mysql:5.6

2. dockerイメージを確認

  • 取得したイメージを確認する
docker images

3. 取得したdockerイメージからmysqlコンテナ起動

  • dockerイメージからコンテナを起動
  • 上記で確認した${REPOSITORY}[:${TAG}]を指定する
  • 今回の起動コマンドの基本構文は以下の通り

  • 基本構文

docker run -d --name ${NAME} -e MYSQL_ROOT_PASSWORD=my-secret-pw ${REPOSITORY}[:${TAG}]
  • ${NAME} : コンテナに割り当てたい任意の名前
  • my-secret-pw : MySQLのrootユーザーのパスワード
  • ${TAG} : MySQLのバージョンを明示をする際に付ける
  • -d : コンテナをバックグラウンド実行

docker run -d --name mysql5.6 -e MYSQL_ROOT_PASSWORD=password mysql:5.6

4. mysqlコンテナ内でコマンド実行

  • login shellとしてbashを実行(コンテナにログイン)
docker exec -it some-mysql bash
  • 他のコマンド
docker exec -it mysql5.6 ls -al

5. mysqlサーバーのログを見る

docker logs some-mysql

Step.2 Dockerfileからイメージを作成するパターン

1. Dockerfileをビルドしイメージを作成する

docker build -t ${REPOSITORY}[:${TAG}] ${PATH}
docker build -t php .
  • tag : イメージのバージョンを明示する際に付ける

2. dockerイメージを確認

  • 取得したイメージを確認する
docker images

3. 上記で作成したイメージからコンテナを起動する

  • 基本構文
docker run -d --name ${NAME} ${REPOSITORY}[:${TAG}] -p ${HOST PORT: CONTAINER PORT}
  • -d : コンテナをバックグラウンド実行

docker run -d --name php -p 80:80 php

Step.3 docker-compose.ymlからイメージを組合せて作成するパターン

  • docker-compose.ymlがあるディレクトリをカレントにする

  • docker-composeコマンドを実行する

sudo docker-compose up –d
  • ホストで使用するポートを専有している場合は、サービスを停止しておく
    • 今回はMySQL(3306)が起動しており、コンテナ起動失敗した

18.6501x Fundamentals of Statistics(Unit1-2) チェックリスト

Unit1 Introduction to Statistics

What you learned

Lec1: What is statistics

Lec2: Probability Redux

  • Sample average
    • estimatorとして使う
  • probabilistic tools
    1. LLN(Laws(weak and strong) of large numbers)
      • a.s. convergence
      • Convergence in probability
    2. CLT(Central limit theorem)
      • Convergence in distribution
    3. Hoeffinding's inequality
      • sample size nが小さくても使える。(n=1でもいい)
      • CLTが使えない時の代り、ただし精度はCLTほどでない
    4. Consistent estimator
    5. Gaussian distribution
      • PDF, CDF
      • Affine transformation
      • Standardization
      • Symmetry
      • Table(CDF of Standard normal distribution)
      • Quantiles
    6. Three types of convergence
      1. Almost surely(a.s.) convergence
      2. Convergence in probability
      3. Convergence in distribution
    7. Addition, multiplication, division
      • Almost surely(a.s.) convergence and Convergence in probability
    8. Addition, multiplication, division (Slutsky's theorem)
      • Convergence in distribution
    9. Continuous mapping theorem

What you noticed

  • sample averageにCLTを適用することで、Gaussian distributionに分布収束する。その際sampleのr.v.はGaussianである必要はない、任意の分布のr.v.でも大丈夫
  • sample sizeが小さくてCLT適用できない時は、Hoeffinding's inequality
  • CLTもHoeffinding's inequalityもestimatorであるsample averageがunknownな母集団の期待値にどれくれい近いかを測るために使う

その他

参考文献


Unit2 Parametric Inference

What you learned

Lec3: Parametric Statistical Models

  • Trinity of statistical inference
    1. Estimation
    2. Confidence intervals
    3. Hypothesis testing
  • The goal of statistics is to learn the distribution of r.v
  • discrete r.v.s

ja.wikipedia.org

ja.wikipedia.org

ja.wikipedia.org

ja.wikipedia.org

ja.wikipedia.org

  • statistical model is a pair of sample space and a family of probilty distributions.
  • well specified
  • parametric
  • non-parametric
  • semi parametric is a hybrid model
    • nuisance parameter (撹乱母数、迷惑母数)
  • Linear regression model (線形回帰モデル)
  • Cox proportional Hazard model (コックス比例ハザードモデル) 生存モデル
  • identifiable

Lec4: Parametric Estimation and Confidence Intervals

  • Definitions
    • Statistic
      • Any measurable function of the sample
      • Rule of thumb : if you can compute it exactly once given data, it is measurable.
    • Estimator of theta
      • Any statistic whose expression does not depend on theta(data)
    • weakly (resp. strongly) consistent estimatorの条件
    • asymptotically normalの条件
      • estimatorはr.v. そのestimatorも正規分布に近似できる。
      • 近似した際の、分散をasymptotic variance
  • Bias of an estimator
  • Risk (or quadratic risk)
    • varianceとbiasを求めて、これを求めるという流れ
    • MSEと同じ意味合いだけと思うけど、言葉は区別した方いいのかな
  • Confidence intervals(C.I.)
    • confidence interval of level 1 - alpha for theta
      • any random interval whose boundaries do not depend on theta
      • true value theta が、interval内である確率が1 - alpha 以上のintervalのこと
    • C.I. of asymptotic level 1 - alpha for theta
      • any random interval whose boundaries do not depend on theta
      • sample size nの極限を取った時に、上記のような条件を満たすintervalのこと
  • A confidence interval for the kiss example
    • sample spaceの分布がBer(p)の場合
    • CLTより、estimator(sample ave)を標準正規分布に近似がスタート
    • 標準正規分布への近似だけでは、完璧なC.I.は求まらない。なぜならパラメーターに依存した形だから。(今回の場合は、true value p)
    • 次の3つの方法で求める
      1. Solution 1. Conservative bound
      2. Solution 2. Solving the (quadratic) equation for p
        • 実際は、解の公式よりコンピューター計算
      3. Solution 3. plug-in
        • Slutskyより、true vale pの代りにestimatorをplug-inして求める

What you noticed

  • どの分布が適切かを選択するのが、statistical modelingの第一歩
  • その際に、離散な確率変数であれば「台」に注目するのもポイント。有限個なのか無限個なのか

Lec5: Delta Method and Confidence Intervals

  • C.I.の復習

    • 95%,98%の区間があるからといって、必ずしも98%区間の方が広いわけではない
    • 同じ50%のC.I.でも区間の広さは異なる。正規分布の形から区間の中点を正規分布の中心に持ってくる時、一番区間を小さくできる
    • n → ∞にした時に成立するものをasymptotic confidence intervalと呼ぶ。(つまりn=1の時などは成立しない)
    • [0.34, 0.57]が95% confidence interval、と言われた時どう捉えるか?
      • この区間にunknownなパラメーターpが入る確率は0,1。0.95ではない。
      • realizationしたC.I.には注意
      • それでも、[0.34, 0.57]を95%のC.I.と呼ぶので注意。
      • これはあくまでも1 - alpha = 0.95でrandom C.I.をdeterministicな区間にrealizationしただけ
  • Red line TのKenall stでの待ち時間のモデル(delta method)

    • 電車の到着間の時間を計測する(つまり次の電車が来るまでの待ち時間)
    • この各待ち時間をモデル化する
    • 以下の様に仮定する
      • Mutually independent
      • パラメーターlambdaの指数分布
    • この時、lambdaをestimateする
    • lack of memory
      • why would I use exponential?
        • It's a very common distribution for inter-arrival times
        • main reason "lack of memory"
    • exponentialのexpectationからわかるように、LLN -> CLTを適用しても、単純にsample aveをestimatorにしてただけではlambdaのestimateできない
    • ここで、delta methodの登場

ja.wikipedia.org

  • delta method
    • this is important
    • 確率変数の列がthetaで正規分布に分布収束するとする
      • この時、この列をasymptotically normal around thetaと言う
    • 次に、thetaでcontinuously differentiableな関数gを考える
    • 上記の確率変数の列をこの関数に関しても、正規分布へ分布収束する
    • delta methodの導出にはtaylor展開を使う
    • 指数分布の場合は、estimatorをsample aveの逆数を取る。このestimateの時にLNN,CLTに加えてdelta methodを使う
  • frequentist interpretation
    • 複数回試行を行ったとき、true value lambdaがC.I.に入る確率は95%
    • 1111011101111..のような結果になる。

What you noticed

  • パラメーターに依存するrandom intervalは実際はC.I.ではない
  • 3つのsolutionを用いて、数値化(realizations)したendpoint間のintervalがC.I.
  • このように、まずC.I.はrandomなのか、realizationしたdeterministicな区間なのかをまず区別する
  • HW2より。正規分布の確率変数の列の和も正規分布になる
  • HW2でガウス分布登場

ja.wikipedia.org

Firebase使い始め [Androidアプリの追加]

  • Firebaseのプロジェクトを作成したら、そのプロジェクトに自分が作成しているアプリを追加する必要がある。
  • 今回は作成中のAndroidのアプリを追加してみる。

What you will learn

  1. Add Firebase to your Android app

Requirements

  • Device/Emulator :
    1. Android Device API level9+(Android 2.3)
      1. Play Service9.0+
        • setting -> app -> GooglePlay servicesでバージョンを確認
  • Android SDK(Android Studio) : 以下の要件を満たすことでFirebase client libraryをビルド可能になる
    1. Google Plya services rev 30+
    2. Google Repository rev 26+
      1. Android Studioを開き、SDK Mangerを開く。
      2. Appearance & Behavoir -> System Settings -> Android SDKを開き、中央のSDK Toolsを開く。
      3. 以下を確認
        1. Google Plya servicesのrevが30+
        2. Google Repositoryのrevが26+

FirebaseにAndroidアプリ追加手順

1. Firebaseコンソールから作成したプロジェクトを選択

2. Androidアプリの追加

f:id:mizushou:20190213174349p:plain

2-1. アプリの情報を入力する

  • コンソール上部のAndroidのマークのボタンをクリック
  • 以下の情報を入力する
    1. Androidパッケージ名
      • build.gradle(app)のapplicationIdに記載されているもの(念の為)
    2. デバッグ用証明書のSHA1フィンガプリント (SHA-1 hash of your debug key)
      • 2-2.のフィンガプリントの取得方法へ

2-2.デバッグ用証明書のSHA1フィンガプリントを取得

  • 2-1.で求められたデバッグ用証明書のフィンガプリントをAndroidStudioの機能を用いて取得する。コマンドでも取得できるがこっちのほうが楽。
  • AndroidStudioの右側におそらくあるはずの[Gradle]を開く
  • {プロジェクト名}/app/Tasks/android/signingReportをダブルクリックで実行
  • そうすると、AndroidStudio上で証明書の情報が表示される。
  • その中にSHA1の値がある。これを2-1のアプリ情報としてコピペする

f:id:mizushou:20190213174716p:plain

2-3. google-services.json(設定ファイル)を配置

  • パッケージ名とフィンガプリントを入力したらregisterする

f:id:mizushou:20190213173920p:plain

  • そうすると、jsonファイルをダウンロードできる

f:id:mizushou:20190213174058p:plain

  • jsonファイルをダウンロードしたら、appフォルダ配下に配置
    • AndroidStudioの場合は、[Project]に切り替えて、appフォルダに配置すればいい

2-4. Add dependencies(Firebase SDKの追加)

  • Firebase client libraryをインポート・ビルドするためにgradle fileにdependenciesを追加
  • dependenciesをすべて追加してから、最後にsyncする
  • 追加するdependenciesのバージョンは以下のページで最新版を確認

firebase.google.com

2-4-1. build.gradle(module)
dependencies {
    ...
    classpath 'com.google.gms:google-services:4.0.0'
    ...
}
2-4-2. build.gradle(app)
  • ライブラリの追加(Firebaseの機能を追加するたびに追加する)
  • パス : /app/build.gradle (app配下にある)
    1. 最終行に追加
    2. dependenciesに使用するpluginを追加。最初はcore(analtics)を追加
//これを最終行に
apply plugin: 'com.google.gms.google-services'

dependencies {
    ....
    // Firebase dependencies
    implementation 'com.google.firebase:firebase-core:16.0.1'
}

2-4. 確認

  • アプリを起動し、logcatで確認
    • FirebaseApp initialization successfulが出ていることを確認してひとまず完了
2018-06-14 13:16:33.947 4655-4655/com.example.shouhei.mlkitdemo I/FirebaseInitProvider: FirebaseApp initialization successful

f:id:mizushou:20190213174425p:plain

Firebase使い始め [プロジェクト作成]

What you will learn

  1. Firebaseのプロジェクト作成
    • プロジェクト名の設定
    • Analyticsのロケーションの選択
    • Cloud Firestoreのロケーションの選択

Terminology

cloud.google.com

  • ロケーション(location)
    • 北米、南米、ヨーロッパ、アジア、オーストラリアなど地理的な範囲を示す
    • 各々のロケーションはリージョンに分割される。さらにリージョンはゾーンに分割される。
  • リージョン(region)
    • ゾーンから構成される地理的エリア。
    • リージョン内は95%がネットワーク遅延 < 1msに抑えられるらしい
  • ゾーン(zone)
    • リージョン内のCloud Platformリソースのデプロイメントエリア
    • リージョン内の単一障害点となる
    • 高可用性を保つには複数のゾーンにデプロイする必要がある

cloud.google.com

1.プロジェクトのロケーションについて

1-1. ロケーションの種類

  • ロケーションはマルチリージョン(multi-region location)と(単一)リージョン(single, regional location)の2種類から選択できる。

    1. マルチリージョンは一般的な国単位の地理的エリアをイメージすればいい。例えばアメリカなど。
      • Cloud Firebase databaseの高可用性と冗長性を最大限にできる。
      • マルチリージョンが使用可能なのは、現在はアメリカのみ。(2019年2月現在)
    2. リージョンは都市など特定の地理的場所をイメージするといい。例えば、サウスカロライナ州など。
      • データはリージョン内の複数のゾーンにレプリケーションされる。
      • リージョンを選択した時は、ネットワーク遅延や他のGCPリソース利用する場合などに注意を払った方がいい。
  • 個人的にFirebaseを試してみる場合などは、特にそこまで気にすることはない。自分の住んでいる一番近い都市を選択すればよいと思う。

  • 以下、雑な絵。以下の3つのサービスはプロジェクトのロケーションを共有するらしい。

    • Cloud Firestore
    • Cloud Storage
    • App Engine

f:id:mizushou:20190206231423p:plain

1-2. 選択するロケーション

  1. Analytics location

Analytics location, which represents the country/region of your organization

--

  1. Cloud Firestore location

Cloud Firestore location, which represents where your data is stored by Google Cloud Platform services that support data location, like Cloud Firestore

--

Once you select a location for your project, you cannot change it.

1-3. ロケーションをどう決めるか

  • Analytics location
    • これは収益レポートを作る際の通貨に関わってくるので、実際に組織がある国を選択すればよさそう
    • このロケーションは、データがどのリージョンのFirebaseに蓄積されるかなどには影響しない。つまり、次で設定するFirebaseのロケーションとは関係しない。
  • Cloud Firestore location
    • 選択したロケーションがCloud Firestoreにも適用される。パフォーマンスや可用性などを考慮して実際にユーザーに近い場所やサービスとして必要とされる場所を選択したほうがよさそう。

2. プロジェクト作成手順

ロケーションについてある程度理解したので、実際にプロジェクトを作成してみる。作成自体は一瞬。Firebase(https://firebase.google.com/)開いて、コンソールへ移動。プロジェクト作成をクリックして、以下を設定し作成。

  1. プロジェクト名(任意)
  2. Analytics location
  3. Cloud Firestore location

ExpoでReactNativeアプリを起動するまで(Android向け)

ExpoでReactNative appを起動してみる。

  • 前回は、環境構築まで行ったがアプリをロード(起動)できなかった。

mizushou.hatenablog.com

  • 今回は、アプリのロードまでに行ったことをチェックリスト形式にして、Expoで作成したアプリの起動手順を書いていく。
  • Android実機とエミュレータでアプリを起動する手順になる。(ただ、チェックリストはプラットフォーム関係なく使えると思う。)
  • Expoを使う理由はReact Nativeの公式ドキュメントのQuick StartがExpo前提で書かれていたから。

facebook.github.io

Requirments

  • Node+Expo環境の構築(前回の記事)

What you will learn

  1. Expoでのサンプルアプリの作成手順
  2. Android実機とエミュレータ上でExpoで作成したReact Nativeアプリのロード

Let's start

1. まずExpoプロジェクトを作成

前回は適当に作成したので、Expoのドキュメントに従って作成してみる

docs.expo.io

1-1. Creating the project

  • プロジェクト名を指定してプロジェクトを作成する(指定したプロジェクト名のディレクトリがカレントに作成される)
expo init {project name}
  • 次に色々と聞かれる。ここではドキュメントに従ってtemplateはtabsを選択
  • 選択後、Expo CLIがプロジェクトを作成し始める。その際にreact, react-native, expoもインストールしてくれる。
  • 今回作成したプロジェクト
    • template : tabs
    • workflow : managed
    • name": first-app
    • slug : first-app

まず、template選択

shouhei-ubuntu% expo init
? Choose a template: 
  blank
  minimum dependencies to run and an empty root component 
❯ tabs
  several example screens and tabs using react-navigation

次に、workflowを選択

? Choose a template: expo-template-tabs
? Choose which workflow to use: 
❯ managed (default)
  Build your app with JavaScript with Expo APIs. 
  advanced (experimental 🚧)
  Build your app with JavaScript with Expo APIs and custom native modules. 

最後に、アプリのnameとslugを入力

shouhei-ubuntu% expo init
? Choose a template: expo-template-tabs
? Choose which workflow to use: managed
? Please enter a few initial configuration values.
  Read more: https://docs.expo.io/versions/latest/workflow/configuration ‣ 100% completed
 {
   "expo": {
     "name": "first-app",
     "slug": "first-app"
   }
 }

1-2. Confirm npm modules in current directory

  • インストール後、一応確認
  • webpackはインストールしたらERR消えたが、古いreact, react-nativeへの依存は放置した。
shouhei-ubuntu% npm list --depth=0
/home/shouhei/Documents/ReactNative/first-app
├── @expo/samples@2.1.1
├── babel-preset-expo@5.0.0
├── expo@32.0.3
├── jest-expo@32.0.0
├── mkdirp@0.5.1
├── react@16.5.0
├── react-native@0.57.1
└── react-navigation@3.1.2

npm ERR! peer dep missing: react-native@^0.55.4, required by expo-google-sign-in@2.0.0
npm ERR! peer dep missing: react-native@^0.44.1, required by react-native-reanimated@1.0.0-alpha.11
npm ERR! peer dep missing: react@16.0.0-alpha.6, required by react-native-reanimated@1.0.0-alpha.11
npm ERR! peer dep missing: webpack@^3.0.0 || ^4.0.0, required by url-loader@1.1.2

2. Start the development server

  • プロジェクトディレクトリをカレントにして、Metro Bundler?を起動
  • 起動すると、サーバーのURLexp://192.168.1.30:19000みたいなのとQRコードが表示される
cd {プロジェクトディレクトリ}
npm start
  • Metro BundlerというJSをBabelコンパイルしてくれるwebサーバーが起動するらしい(各キーワードの意味わかってない)

Expo CLI starts Metro Bundler, which is an HTTP server that compiles the JavaScript code of our app using Babel and serves it to the Expo app. It also pops up Expo Dev Tools, a control panel for developing your app, in your default web browser.

3. Open the app on your phone or simulator (For Android)

  • ここが前回詰まったところ。
  • 以下、起動成功までに確認とやってみたことリスト

3-1. 起動する前のチェックリスト

No. 項目 実機 エミュレータ
1 接続ネットワーク確認 必要 不要
2 Expoアカウント作成し、Expo CLIとExpo moile appにログイン 不要 不要
3 Expo moile appインストール 必要(PlayStoreから手動でインストール) 必要(ロード時に自動でインストールされる)
4 adbコマンドなどパスを通す 不要 必要
5 root権限で起動してみる 環境による 環境による

チェックリストNo.1

  • 実機の場合は、まずサーバーとなる自分のパソコンと実機が同じネットワーク内にあるのかを確認しておく必要がある。
ifconfig -a

チェックリストNo.2

  • ドキュメントには手順として書いてあったのでやっておいたが、必須ではなさそう。(ログインしておくほうが色々と便利な気はする、たぶん)
  • ExpoサイトまたはExpo CLIからでもアカウントは作成可能
  • Expo CLIと実機にインストールしたExpo moile appでログインしておく。
  • エミュレータの方はログインしたことないので不要?

チェックリストNo.3

  • 実機の場合はインストールしておく必要がある。
  • 上記の通り、作成したExpoアカウントでログインしておく

チェックリストNo.4

  • エミュレータの場合は以下のようにパスを通しておく必要がある
  • 最終的にはadbコマンドのパスが通っていることが最低限必要そうなので、2個目のコメントはmacOSだけと書いてあるが、Ubuntu機の私も行った。

If you are on macOS or Linux, add the Android SDK location to your PATH using ~/.bash_profile or ~/.bash_rc. You can do this by adding a line like export ANDROID_SDK=/Users/myuser/Library/Android/sdk.

--

On macOS, you will also need to add platform-tools to your ~/.bash_profile or ~/.bash_rc., by adding a line like export PATH=/Users/myuser/Library/Android/sdk/platform-tools:$PATH

--

Make sure that you can run adb from your terminal.

チェックリストNo.5

  • これは私の環境だけかもしれないが、これが私の環境では必須
  • /tmp/metro-cache/配下のオーナーがrootと一般ユーザがごっちゃになっていてpermission deniedで動かなかったので、結局root権限で起動している
  • ローカルの開発環境の権限設定とかもしっかりしたい。。。
sudo npm start

3-2. ひとまずこのチェックリストにあることをこなす

  • チェックリストを確認したら、
    • 実機の場合は、表示されたQRコードをExpo client appでスキャンすると勝手にアプリがロードされ起動する
    • エミュレータの場合は、起動したブラウザツールでのRun on Android device/emulatorをクリックすると勝手にロードされ起動する。(ここで気づいたけど、この手順はエミュレータだけでなくUSBで接続した実機でも同じ)
  • アプリ編集後、編集内容がアプリに同期されることも確認できた。
  • 本来ここまで大変ではないと思う笑
  • 以下の画像は実際に起動したサンプルアプリと起動後のMetro Bundlerの画面。

f:id:mizushou:20190204143533j:plain

f:id:mizushou:20190204143818p:plain

ReactNative+Expo環境構築 on Ubuntu

what you install

  1. Node(とnpm)
    • n packageでインストール
  2. Expo
    • This will start a development server for you.

how to set up

1. install Node

[参考]

qiita.com

1-1 nodejs,npmを用意

UbuntuにインストールされていたNodeとaptでインストールしたnpmがめっちゃ古い

  • 元々インストールされていたnodejs(パッケージ名はnodejs、、)
nodejs -v
v4.2.6
  • aptでインストールしたnpm
npm -v
3.5.2

1-2 n packageをインストール

shouhei-ubuntu% sudo npm install n -g 
/usr/local/bin/n -> /usr/local/lib/node_modules/n/bin/n
/usr/local/lib
└── n@2.1.12 

1-3 n packageを使って、最新のnodeをインストール

  • 以下のコマンドで最新版のnodeをインストール。以下は、インストール後の情報。
    • インストールディレクトリ : /usr/local/bin/node
    • Node : v4.2.6 -> v11.8.0
    • npm : v3.5.2 -> v6.5.0
shouhei-ubuntu% sudo n stable

     install : node-v11.8.0
       mkdir : /usr/local/n/versions/node/11.8.0
       fetch : https://nodejs.org/dist/v11.8.0/node-v11.8.0-linux-x64.tar.gz
######################################################################## 100.0%
   installed : v11.8.0

shouhei-ubuntu% /usr/local/bin/node -v
v11.8.0

1-4 シンボリックリンクを貼って、パスを通しておく

shouhei-ubuntu% sudo ln -sf /usr/local/bin/node /usr/bin/node
shouhei-ubuntu% node -v
v11.8.0
shouhei-ubuntu% npm -v
6.5.0

1-5 事前にインストールされていた古いバージョンのnodeとnpmをアンインストール

sudo apt-get purge -y nodejs npm

2. install Expo

  • React Nativeの公式ドキュメントよりExpoを使ってReactNativeのサンプルアプリを動かしてみる。
  • 実際はすんなり起動とはいかず、四苦八苦した。
  • 起動までの試行錯誤はまた別エントリで書くことにする

[参照]

facebook.github.io

2-1 install expo-cli

shouhei-ubuntu% sudo npm install -g expo-cli

3. create a React Native app via Expo

  • expoコマンドでサンプルプロジェクトをビルドしてみる
  • テンプレートやapp nameなどを入力するとビルドが開始する
expo init AwesomeProject
  • しかし、permissonエラーで失敗。(なぜここで、sudoで実行したのかは覚えていない。ドキュメントはsudoなしでコマンドを実行している)
shouhei-ubuntu% sudo expo init AwesomeProject
? Choose a template: expo-template-blank
? Choose which workflow to use: managed
✔ Please enter a few initial configuration values.
  Read more: https://docs.expo.io/versions/latest/workflow/configuration · 100% completed
[11:23:37] Extracting project files...
[11:23:37] Customizing project...
[11:23:37] Initialized a git repository.
[11:23:37] Installing dependencies...
npm ERR! code 1
npm ERR! Command failed: /usr/bin/git clone --depth=1 -q -b expo-font-fix git://github.com/expo/vector-icons.git /home/shouhei/.npm/_cacache/tmp/git-clone-58fb5883
npm ERR! /home/shouhei/.npm/_cacache/tmp/git-clone-58fb5883/.git: 許可がありません
npm ERR! 

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/shouhei/.npm/_logs/2019-02-02T02_23_56_300Z-debug.log
[11:23:56] Process exited with non-zero code: 1
[11:23:56] Set EXPO_DEBUG=true in your env to view the stack trace.
  • permission関連ぽい。~/.npm配下は一般ユーザがオーナーなのでrootでアクセスできなかったってことか?
npm ERR! /home/shouhei/.npm/_cacache/tmp/git-clone-58fb5883/.git: 許可がありません
  • 原因切り分けのため、一般ユーザで実行(というかドキュメントは元々sudoなしで実行している)
shouhei-ubuntu% expo init AwesomeProject               
? Choose a template: (Use arrow keys)
❯ blank
  minimum dependencies to run and an empty root component 
  tabs
  several example screens and tabs using react-navigation Uncaught Error { [Error: EACCES: permission denied, open '/home/shouhei/.expo/state.json.911742535']
  errno: -13,
  code: 'EACCES',
  syscall: 'open',
  path: '/home/shouhei/.expo/state.json.911742535' }
  • 今度は/home/shouhei/.expoらへんがおかしそう
EACCES: permission denied, open '/home/shouhei/.expo/state.json.911742535']
  • /home/shouhei/.expo配下がroot権限になっていたので、オーナーを変更
sudo chown shouhei:shouhei /home/shouhei/.expo
  • オーナー変更後、再度実行するとひとまずビルド成功。
  • WARNが出ているが、この後このままでもアプリは動作したので放置している。
shouhei-ubuntu% expo init AwesomeProject
? Choose a template: expo-template-blank
? Choose which workflow to use: managed
✔ Please enter a few initial configuration values.
  Read more: https://docs.expo.io/versions/latest/workflow/configuration · 100% completed
[11:40:10] Extracting project files...
[11:40:10] Customizing project...
[11:40:10] Initialized a git repository.
[11:40:10] Installing dependencies...
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN expo-google-sign-in@2.0.0 requires a peer of react-native@^0.55.4 but none is installed. You must install peer dependencies yourself.
npm WARN react-native-reanimated@1.0.0-alpha.11 requires a peer of react@16.0.0-alpha.6 but none is installed. You must install peer dependencies yourself.
npm WARN react-native-reanimated@1.0.0-alpha.11 requires a peer of react-native@^0.44.1 but none is installed. You must install peer dependencies yourself.
npm WARN url-loader@1.1.2 requires a peer of webpack@^3.0.0 || ^4.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.7 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.7: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

added 858 packages from 426 contributors and audited 19840 packages in 59.389s
found 0 vulnerabilities


Your project is ready at /home/shouhei/Documents/ReactNative/AwesomeProject
To get started, you can type:

  cd AwesomeProject
  npm start

4. Start the development server

  • コンソールに表示された通り、プロジェクトのディレクトリをカレントにして起動する
cd AwesomeProject
npm start

5. Open the app on your phone or simulator

  • サーバーを起動させたら、
    • 実機の場合は、コンソールまたはブラウザツールに表示されるQRコードをインストールしておいたExpoアプリでスキャンすればアプリがロードされ起動する
    • エミュレータの場合は、AndroidStudioでエミュレータを起動させた後にブラウザツールのRun on Android device/emulatorをクリックすると自動でロードが開始する。(エミュレータの場合はExpoアプリは自動でインストールしてくれる)または、コンソールでaを入力するだけでもいい。
  • しかし、私の場合は初回は実機もエミュレータ共にエラーが起きて起動しなかった。
    • 以下が実際に起動した時のエラー
    • Something went wrongと表示された。ログを見ても同様のメッセージが表示されていただけだった。
    • 表示されたURLがexp:でアクセスしてるURLは普通にhttp:なのがいけないのか?などとにかく最初全く原因がわからなかった。
    • 起動するまでに何をしたかは別エントリで書くが、上手く行く時はまったく上記のこととか気にするこなく起動する

実機の場合(QRコードをスキャン)

f:id:mizushou:20190203232245j:plain

エミュレータの場合

f:id:mizushou:20190204005243p:plain

  • 以下エントリで動作までの手順(試行錯誤)を書いている

mizushou.hatenablog.com

Pythonのif文まとめ

Pythonのelifが最初よく理解できず、併せてfor文のネストも混乱したのでまとめておく。今回、if文を勉強するために参照した以下のサイトの図やコードを引用している。

www.programiz.com

What you will learn

Pythonのif文.

  1. if statements
  2. if...else statements
  3. if...elif...else statements
  4. nasted if statements
  5. nasted if statements with elfi (same sa switch statement)

Notice

  • インデントが重要
    • Pythonのif文のbodyはインデントで表現する。なのでPythonにおいてインデントはより重要
    • Javaのように{}などでブロックは作成しない
  • elfiが特殊
    • Pythonにはdefaultではswitch-case文がないので、switch-case文などを書きたい場合にも活躍する
  • True : non-zero or non-null
  • False : zero or null

1. if statements

Synax

if test expression:
    statement(s)

Flow Diagram

f:id:mizushou:20190113233942p:plain

Example

var1 = 100
if var1:
    print("1-Got a true expression value")
    print(var1)
var2 = 0
if var2:
    print("2-Got a ture expression value")
    print(var2)
print("Good bye!")

Output

1-Got a true expression value
100
Good bye!

2. if...else statements

Synax

if test expression:
    Body of if
else:
    Body of else

Flow Diagram

f:id:mizushou:20190113234141p:plain

Example

var1 = 100
if var1:
    print("1-Got a true expression value")
    print(var1)
else:
    print("1-Got a false expression value")
    print(var1)

var2 = 0
if var2:
    print("2-Got a true expression value")
    print(var2)
else:
    print("2-Got a false expression value")
    print(var2)
print("Good bye!")

Output

1-Got a true expression value
100
2-Got a false expression value
0
Good bye!

3. if...elif...else statements

Synax

if test expression:
    Body of if
elif test expression:
    Body of elif
else:
    Body of else

Flow Diagram

f:id:mizushou:20190113234209p:plain

Example

var = 100
if var == 200:
    print("1-Got a true expression value")
    print(var)
elif var == 150:
    print("2-Got a true expression value")
    print(var)
elif var == 100:
    print("3-Got a true expression value")
    print(var)
else:
    print("4-Got a true expression value")
    print(var)
print("Good bye!")    

Output

3-Got a true expression value
100
Good bye!

4. nasted if statements

Synax

if test expression1:
    if test expression2:
        Body of if2
    else:
        Body of els2
else:
    Body of else1

Flow Diagram

f:id:mizushou:20190114223236p:plain

Example

var1 = 100

if var1 % 2 == 0:
    print("even number")
    if var1 % 5 == 0:
        print("multiple of five")
    else:
        print("not multiple of five")
else:    
    print("odd number")

Output

even number
multiple of five

5. nasted if statements with elfi (same as switch statement)

Synax

if test expression:
    Body of if
elif test expression1:
    Body of elif1
elif test expression2:
    Body of elif2
elif test expression3:
    Body of elif3
             .
             .
             .
else:
    Body of else

Flow Diagram

f:id:mizushou:20190114230308p:plain

Example

var = 2
if var == 1:
    print("case1")
elif var == 2:
    print("case2")
elif var == 3:
    print("case3")
elif var == 4:
    print("case4")
else:
    print("default")

Output

case2

Javaのswitch-case文で書くと...

public class SwitchCaseExample2 {

   public static void main(String args[]){
      int i=2;
      switch(i)
      {
     case 1:
       System.out.println("Case1 ");
       break;
     case 2:
       System.out.println("Case2 ");
       break;
     case 3:
       System.out.println("Case3 ");
       break;
     case 4:
       System.out.println("Case4 ");
       break;
  default:
       System.out.println("Default ");
      }
   }
}

Output

case2