とあるお兄さんの雑記

基本的に技術系の内容を書きますが、何を書くかは私の気分です。

Dockerを学ぶ第3回~コンテナ操作~

HTC Advent Calendar 2020の15日目を担当します、kurasherです。

第3回は起動したコンテナを操作する方法を学んでいきます。

コンテナを操作する

「コンテナの中に入って操作する」と言われると何を想像するでしょうか?私がDockerを学びたての頃にこんなことを言われたときは、いまいち理解出来ませんでした。
Dockerを学んでいる中、ずっと、

( ゚Д゚)ハァ?

という状態でした。

コンテナを操作するとは?

実際に試してみましょう。今回引っ張ってくるイメージはalpineという非常に軽量なLinuxです。ひとまず、Linuxに入るってことを理解してればいいかと思います。

一旦、イメージを探してみましょう。

$ docker search alpine
NAME                                   DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
alpine                                 A minimal Docker image based on Alpine Linux…   6935                [OK]
mhart/alpine-node                      Minimal Node.js built on Alpine Linux           476
anapsix/alpine-java                    Oracle Java 8 (and 7) with GLIBC 2.28 over A…   460                                     [OK]
frolvlad/alpine-glibc                  Alpine Docker image with glibc (~12MB)          249                                     [OK]
gliderlabs/alpine                      Image based on Alpine Linux will help you wi…   183
alpine/git                             A  simple git container running in alpine li…   156                                     [OK]

いろんなものがありますね。このように必要に応じて自分が欲しいイメージを探すようにしましょう。

今回は一番上のOFFICIAL[OK]とあるalpineをpullしてきましょう。

$ docker pull alpine

これでalpineイメージを取得できました。この後、alpineのコンテナを起動して、alpineコンテナの操作をするには以下のようにコマンドを打ちます。

$ docker run -it --name alpine_con alpine /bin/sh
/ #


これでコンテナ内部に入れました。lsとか打つと

/ # ls
bin    dev    etc    home   lib    media  mnt    opt    proc   root   run    sbin   srv    sys    tmp    usr    var

と出力されます。めっちゃ遊べますよ。終わる場合はexitと打つか、Ctrl + Cでコンテナから抜け出せます。

/ # exit
$

Dockerコマンド解説

先ほど打ったコマンドは以下でした。

$ docker run -it --name alpine_con alpine /bin/sh
  1. docker runでコンテナの起動
  2. -itでコンテナ内部に入るように設定
  3. --name コンテナ名で起動するコンテナ名を指定。起動する際に毎回つける必要はありません。無くても大丈夫です。
  4. --name alpine_conの後ろは起動するコンテナのもとになるイメージを指定。今回はalpineイメージです。
  5. /bin/shalpineコンテナのシェルを起動

ちなみに、最後のシェルの起動の部分ですが、大抵のコンテナは/bin/bashを指定しますが、alpineだけは/bin/shを指定します。
理由は↓の記事を参考にしてください。
dockerでalpine linux ベースのcontainerに入って、shellを使いたいとき。

コンテナでWebサーバを動かす:ポートフォワーディング

コンテナでWebサーバを動かすための、ポートフォワーディングという技術について学びましょう。内容としては、外部からコンテナ内のサーバにアクセスするためのポートを指定するというだけの話です。

今回使用するイメージはNginx(エンジンエックス)と呼ばれるWebサーバーです。以下のようにして取得できます。

$ docker pull nginx

せっかくなので、適当な名前を付けてコンテナを起動します。

$ docker run --name nginx_con -p 8000:80 nginx

これでDocker Desktopならlocalhost:8000でコンテナ内部のnginxにアクセスすることが出来ます。

一方、Docker Toolboxlocalhost:8000としてもつながりません。
以下のコマンド打って、ipアドレスを取得します。

$ docker-machine ip default
192.168.99.100

私の場合は、192.168.99.100なので、これに先ほど指定したポート番号(8000)を指定することでアクセスすることが出来ます。
Docker Toolboxの場合:192.168.99.100:8000

Dockerコマンド解説

先ほど打ったコマンドは以下の通りです。

$ docker run --name nginx_con -p 8000:80 nginx

-pというオプションがポートフォワーディングにあたります。指定方法は簡単で、

-p ローカルPC(ホスト)側のポート番号:コンテナ(ゲスト)側のポート番号

となります。

コンテナ内部でもアクセスしてみる

せっかくなのでコンテナ内部からもアクセスできるか見てみましょう。
別ターミナルを起動し、まずは以下のコマンドでnginxコンテナ内部に入ります。

$ docker exec -it nginx_con /bin/bash
root@6cb84a6dac9a:/#


後はcurl localhost:80と打ちます。コンテナ内部からのアクセスのため、ポート番号は80を指定します。
下記の出力となればOKです。

root@6cb84a6dac9a:/# curl localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

無事コンテナ内部からアクセスできました。

コラム:docker run -it とdocker exec -itの違い

そういえば、コンテナ内部に入る際にコマンドが若干違いましたね。
これの違いはコンテナが起動しているかいないかになります。

コンテナが起動していない場合、docker run -itを、
コンテナが起動している場合、docker exec -it
することで、コンテナ内部でいろいろ操作することが出来るようになります。

ちょっと試してみましょう。適当にnginxのコンテナを起動します。

$ docker run --name nginx_con --rm -d nginx #コンテナ起動 --rm:コンテナ停止後コンテナの自動削除 -d:バックグラウンドで起動
624a440e75a5e525dda9ef8430ab80cb85bfe586d40392d1584f0c02c2e8b905
$
$ docker ps # コンテナが動作しているかを確認
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
624a440e75a5        nginx               "/docker-entrypoint.…"   11 seconds ago      Up 9 seconds        80/tcp              nginx_con
$
$ docker run -it nginx_con /bin/bash # nginx_conに入れるか確認
Unable to find image 'nginx_con:latest' locally
C:\workspace\Docker Toolbox\docker.exe: Error response from daemon: pull access denied for nginx_con, repository does not exist or may require 'docker login': denied: requested access to the resource is denied.
See 'C:\workspace\Docker Toolbox\docker.exe run --help'.
$
$ docker exec -it nginx_con /bin/bash # nginx_conに入れるか確認
root@624a440e75a5:/#

上記はnginxのコンテナを起動し、コンテナ内部に入るまでの一連の流れを示したものです。
docker run -it nginx_con /bin/bash # nginx_conに入れるか確認で、起動したnginx_conrunで入ろうとしていますが、nginx_conというイメージ名が無いよ、というエラーが出ています。

また、起動していないコンテナにexecしてもエラーが出ます。

$ docker ps # 起動しているコンテナの確認
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
624a440e75a5        nginx               "/docker-entrypoint.…"   8 minutes ago       Up 8 minutes        80/tcp              nginx_con
$ docker stop 6 # コンテナの停止 先ほど-dを指定してrunしたため、stopすれば自動削除される
6
$ docker ps -a # コンテナが立ち上がっていないかを確認
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
$ docker exec -it nginx /bin/bash # コンテナが無い状態でexecを実行
Error: No such container: nginx


docker run -itdocker exec -itの違いを覚えておきましょう。

まとめ

今回の記事で取り上げたDocker コマンド一覧です。-d--rmの他にもオプションはたくさんありますが、ハンズオンで少しずつ試すのがいいかと思います。
次回からDockerfileなるものを使ってみます。

やること Dockerコマンド
イメージを探す docker search イメージ名
イメージの一覧表示 docker images
起動していないコンテナのコンテナ操作 docker run -it コンテナ名 イメージ名 コンテナ内で実行するコマンド
起動中のコンテナのコンテナ操作 docker exec -it コンテナ名 イメージ名 コンテナ内で実行するコマンド
コンテナをバックグラウンドで起動 docker run -d イメージ名
コンテナを停止後自動的にコンテナを削除するオプション docker run --rm イメージ名
起動中コンテナの停止 docker stop コンテナ名

参考

dockerでalpine linux ベースのcontainerに入って、shellを使いたいとき。

docker runとdocker execの違いの解説

Dockerを学ぶ第2回~基本的なDockerコマンド~

HTC Advent Calendar 2020の8日目を担当します、kurasherです。

第2回からはDockerの基本コマンドを学んでいきます。Dockerはすでにインストールしているものとして話を進めます。

Dockerをインストールしていない人は、Play with Dockerからでも大丈夫です。

環境

Windows 10 Pro
Docker ToolBox 18.09.1

Windows 10 ProならDocker Desktopがインストール可能ですが、私の場合PCが古いのと、Docker Desktopを起動するとメモリ不足となり、ブラウザが立ち上がらない、つまり調べたいことが全く調べられないという状況になったので、Docker ToolBoxを入れています。

hello-worldからイメージの取得、コンテナの起動、削除までを学ぶ

ここから本格的にDockerコマンドを学んでいきましょう。また、これ以降ではDockerイメージを単にイメージ、Dockerコンテナを単にコンテナと呼ぶことにします。

イメージ一覧の表示:docker images

Dockerを初めて起動した場合、基本的にイメージはありません。が、Dockerを学ぶうちに、いろんなイメージがDocker内に入ってくるかと思います。その際、下記のコマンドでローカルにどんなイメージが入っているかを知ることが可能です。

$ docker images

または

$ docker image ls

2つのコマンドに違いは無く、新しいか古いかの問題だけです。
docker container / image コマンド新旧比較

実行すると以下のように出力されます。

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

イメージが無いのでこのような出力になります。では実際にイメージを取ってきましょう。

イメージの取得:docker pull

イメージはデフォルトでDocker Hubというところから引き出してきます。Docker Hubには様々なイメージが置いてありますので、一度見てみるといいでしょう。

docker pull イメージ名でイメージを取得します。

$ docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete                                                                                                                                             
Digest: sha256:e7c70bb24b462baa86c102610182e3efcb12a04854e8c582838d92970a09f323
Status: Downloaded newer image for hello-world:latest

これでhello-worldのイメージは取得できました。

docker images見てみましょう。

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              bf756fb1ae65        11 months ago       13.3kB

私の場合は、上記のようになっていました。人によってIMAGE IDの値が違うと思いますが問題ありません。
では次にこのイメージをもとにコンテナを起動してみましょう。

コンテナを起動する:docker run

コンテナを起動します。

$ 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/

hello-worldのイメージを起動できました。ちなみに起動中のコンテナを知る場合、docker psまたはdocker container lsで知ることが出来ます。

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

何も出てこないですね。実はhello-worldのイメージは上記の出力が終わると、自動でコンテナが停止します。そのため、上記のコマンドでは何も表示されません。

停止中のコンテナも含めて表示する場合はdocker ps -a またはdocker container ls -aとします。

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
fc4ea375ee85        hello-world         "/hello"            7 minutes ago       Exited (0) 7 minutes ago                       stoic_merkle

IMAGEがhello-worldのものが作られていますね。ちなみにNAMESはコンテナ名を指しますが、何も指定しない場合適当な名前が付くようになっています。

名前を指定する場合は、コンテナを起動する際に、--name コンテナ名を指定します。今回はコンテナ名をhello-world_conとしてみます。concontainerの頭文字です。

$ docker run --name hello-world_con hello-world

これで、docker ps -aとしてみると、

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
2724d910deeb        hello-world         "/hello"            8 seconds ago       Exited (0) 6 seconds ago                        hello-world_con
fc4ea375ee85        hello-world         "/hello"            15 minutes ago      Exited (0) 15 minutes ago                       stoic_merkle

NAMESがhello-world_conのコンテナ名が出来ました。

コラム:あれ?コンテナ起動するの早くね?

hello-world_conというコンテナを起動する際、同じイメージからコンテナを起動しているにも関わらず、1回目よりも2回目の方が早く立ち上がりませんでしたか?
実はこれ、Dockerの特長で、既にあるもの、設定されているものはそのまま使う設定になっています(要はキャッシュを利用している)。そのため、1回目よりも2回目の方が早く立ち上がるようになっています。

停止しているコンテナを削除する:docker rm

今度はコンテナを削除してみましょう。通常はコンテナを起動した場合、コンテナを停止する作業(docker stop コンテナID)が必要ですが、hello-worldの場合、すでに停止しています。そのため、停止する作業は不要です。
以下のコマンドを実行すればコンテナを削除することが出来ます。

$ docker container rm コンテナID

または

$ docker container rm コンテナ名

docker ps -aでコンテナIDやコンテナ名を確認します。NAMESstoic_merkleのものを削除したい場合、

$ docker container rm stoic_merkle

または

$ docker container rm fc4ea375ee85

で削除可能です。

上記コマンドを実行した後に、docker ps -aで確認すると、

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                   PORTS               NAMES
2724d910deeb        hello-world         "/hello"            2 hours ago         Exited (0) 2 hours ago                       hello-world_con

削除されていることが確認できますね。

コラム:ちょっとだけ楽に削除する方法

ちなみに、コンテナIDや、イメージIDは一意なIDです。つまり、IDの区別さえつけば、削除することが可能です。
例えば、NAMEShello-world_conの場合、CONTAINER ID2724d910deebですので、次のように指定して削除可能です。

$ docker container rm 2
2
$
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

削除できていることが確認できましたね。ちょっとしたtipsでした。

イメージを削除する:docker rmi

基本的にはコンテナを削除する場合と同じです。

$ docker rmi イメージ名

または

$ docker rmi イメージID

で削除可能です。また、イメージIDも一意なIDであるため、イメージIDを途中まで指定して削除することも可能です。

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              bf756fb1ae65        11 months ago       13.3kB
$ 
$ docker rmi b #IMAGE IDがbf756fb1ae65であるため、最初のbだけ指定
Untagged: hello-world:latest
Untagged: hello-world@sha256:e7c70bb24b462baa86c102610182e3efcb12a04854e8c582838d92970a09f323
Deleted: sha256:bf756fb1ae65adf866bd8c456593cd24beb6a0a061dedf42b26a993176745f6b
Deleted: sha256:9c27e219663c25e0f28493790cc0b88bc973ba3b1686355f221c38a36978ac63
$
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

まとめ

今回学んだDockerコマンドの一覧です。何回もpullしたり削除したりすることでDockerに慣れていきましょう。

やること Dockerコマンド
イメージの取得 docker pull イメージ名
イメージの一覧表示 docker images
イメージの一覧表示 docker image ls
コンテナの起動 docker run イメージ名
コンテナ名を指定してコンテナを起動 docker run --name コンテナ名 イメージ名
起動中のコンテナの一覧表示 docke ps
起動中のコンテナの一覧表示 docke container ls
停止中のコンテナも含めてコンテナの一覧表示 docker ps -a
停止中のコンテナも含めてコンテナの一覧表示 docker container ls -a
停止中のコンテナの削除 docker container rm コンテナID
停止中のコンテナの削除 docker container rm コンテナ名
イメージの削除 docker rmi イメージID
イメージの削除 docker rmi イメージ名

参考

Play with Docker
docker container / image コマンド新旧比較

Dockerを学ぶ 第1回~Docker概要とHello World~

こんにちは。

HTC Advent Calendar 2020の5日目を担当します。
ONEJAPAN HACKATHONに参加したチームHTCの一人のkurasherです。

私は現在学習中のDockerを書きます。目標としては、Dockerを知らない全くの初心者でも最終的には最低限のDockerコマンドを習得できることとしています。出来得る限り分かりやすく書いていくつもりですので、よろしくお願いいたします。

また、この記事ではDockerについての説明よりDockerがある程度使えるようになることをメインに置きますので、Dockerそのものの理解については他の記事を参照していただきますよう、お願いします。

Docker学習に入る前に

12月3日、Kubernetes 1.20からDockerが非推奨になる理由という記事が出て、「Docker使えなくなるんじゃね?」みたいな話が出ていますが、そんなことはないです。もちろん上の記事も「Docker使えなくなるよ」とは言っていません。

公式:Don't Panic: Kubernetes and Docker
Dockerは非推奨じゃないし今すぐ騒ぐのをやめろ
ここらあたりを読めば分かりますが、普通にDockerを使えます

大して文章も読まずに特徴的な言葉だけを拾って勘違いしてしまう我々に問題があるので、正しい情報を正しく理解する力をつけましょう。

Dockerとは

Dockerは、コンテナ仮想化を用いてアプリケーションを開発・配置・実行するためのオープンソースソフトウェアあるいはオープンプラットフォームである。 (Wikipediaより)

と書いてありました。 この記事ではDockerの理解よりもDockerを使えることを目標にするため、あまり深入りしないようにします。興味ある方は調べてみてください。

Dockerのメリット

とはいえ、あまりに不親切なので、簡単にDockerのメリットだけ触れておきます。 普段の業務における開発では動作環境が重要になってきます。例えば、開発側がMacで最新安定バージョンの言語でアプリを作ったとしましょう。その後、テスト環境で不具合が無いかどうかを調べ、本番環境に移し、正式にリリースします。

しかし、開発環境、テスト環境、本番環境でそれぞれ違う環境だった場合、わざわざ環境を合わせる必要がありますし、せっかく作ったアプリが正常に動作しない可能性があります。

一方、Dockerだとソースコードから開発環境まで含めてすべて同じ環境にすることが出来ます。また、誰でも同じ環境を再現することが出来るため、アプリが動作しないなんてことは無くなります。

DcokerイメージとDockerコンテナ

DcokerイメージとDockerコンテナだけは押さえておきましょう。

Dcokerイメージとは

通称イメージと呼ばれています。Dockerでは作ったものをZipファイルのようにまとめ、Docker Hub(Docker用のGitHubみたいなもの)に上げることで、他の人にも共有することが可能です。
この時のZipファイルみたいなものがDockerイメージにあたります(という風に私は理解しています...)。

Dockerコンテナとは

通称コンテナと呼ばれています。通常、Dockerで何かしらのアプリを作成する場合、Docker Hubから何かしらのDockerイメージを取ってきます。しかし、それだけでは動かず、Dockerイメージを起動することで初めて動作します。
この、Dockerイメージを起動し、実際に動作できるようにしたものがDockerコンテナにあたります(という風に私は理解しています...)。

DockerイメージとDockerコンテナの理解としては、次のような例が分かりやすいかと思います。
ある日、組み立て式のデスクを購入し、組み立て式のデスクが家に届きました。この状態ではまだデスクは使える状態ではありませんが、家にはあります。
この、手元にはあるがまだ使える状態にないのがDockerイメージです。
f:id:kurasher:20201130220520p:plain

一方、段ボールを開け、実際に組み立ててデスクをいつでも使えるようにした状態がDockerコンテナの状態になります。
f:id:kurasher:20201130220617p:plain

ざっと、DockerイメージとDockerコンテナの説明をしました。最初は難しいかもしれませんが、何度もDockerに触れるうちに分かるようになってきますので、分からなかったら分からなかったで次に行きましょう!!

DockerでHello Worldをやってみる

ここからはDockerを実際に動かしてみましょう。

Docker のインストール

下記から各環境に合わせてインストールしてください。

Macの場合はこちらから
https://docs.docker.jp/docker-for-mac/install.html

Windows Pro、Enterprise、Educationはこちらから
https://docs.docker.jp/docker-for-windows/install.html

Windows Homeの場合、Dockerをインストールできない場合があります。その場合は、Docker Toolboxというものがあり、こちらの記事を参考にインストールしましょう。
【初心者】Docker Toolboxのインストール方法(Windows 10 Home Edition)

また、ブラウザ上でDockerを使うことが出来るPlay with Dockerというものもあります。4時間という制限はありますが、Dockerの学習だけならこちらでもいいかと思います。
Play with Docker

Hello Worldをやってみる

今回はHello Worldを試すだけなのでPlay with Dockerを使ってみます。

サイトにアクセスすると以下のような画面が出てきます。Play with Docker以外でもいずれDocker Hubのアカウントが必要になるので作っておきましょう。 f:id:kurasher:20201130220159p:plain

ログインして、Startすると、以下のような画面が出てきます。左側の「+ ADD NEW INSTANCE」をクリックします。 f:id:kurasher:20201201123343p:plain

すると、以下の画面が出てきて、Dockerが使えるようになります。 f:id:kurasher:20201201123525p:plain

では、ターミナルに次のコマンドを打ち込んでみましょう。

$ docker run hello-world

すると、以下のような出力が出てくるかと思います。

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete 
Digest: sha256:e7c70bb24b462baa86c102610182e3efcb12a04854e8c582838d92970a09f323
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/

これで一応、Dockerからhello-worldを起動することが出来ました!
とはいえ、これだけではDockerの全てを把握できるわけではありませんので、次回以降Dockerコマンドについて詳しく見ていくことにします。

終わりに

今回はDockerの概要とHello Worldを試してみました。
次回以降、本格的にDockerで使われるコマンドについて説明します。

統計学基礎vol.27~標本の抽出法~

こうやって統計学の記事を書いていますが、こんだけ続くとはちょっと意外でした。

あ、今回は標本の抽出方法です。

層化抽出法

母集団をあらかじめいくつかの層(グループ)に分け、各層の中から必要な数の調査対象を無作為に抽出する方法。

メリット

  • 母集団内情報の比較を行える
  • 母集団の推測の精度が増す
  • 各層における分布が大きく異なる場合に使える

デメリット

  • 母集団内の構成情報を事前に知っておかなければならない

層化抽出法の例

男女比 7:3の高校で、10人の学生を抽出するとき、男子は7人、女子は3人の比率で抽出する。
(層の大きさに比例させて調査対象を抽出する方法を、特に比例配分法という。)

クラスター抽出法(集落抽出法)

母集団を小集団に分け、その小集団から無作為にいくつか選び、その小集団から全数調査を行う方法。最後は全数調査を行うところが注意点です。

クラスター抽出法の手順

  1. 母集団を、小集団であるクラスター(集落)に分ける
  2. 分けられたクラスターの中から、いくつかのクラスターを無作為抽出する。
  3. それぞれのクラスターにおいて全数調査を行う。

メリット

  • クラスターの情報さえあれば抽出できるため、時間や手間を省ける。

デメリット

  • 同じクラスターに属する調査対象は似た性質を持ちやすく、標本に偏りが生じる可能性がある。

クラスター抽出法(集落抽出法)の例

高校生の平均身長を調査する際に、高校を一つのクラスターと考え、高校の中からランダムに10校選び、その高校の学生全員の身長を測定

多段抽出法

母集団をいくつかのグループに分け、そこから無作為抽出でグループを選び、さらにその中から無作為抽出でいくつかのグループを選び、…という操作を繰り返して、最終的に選ばれたグループの中から調査対象を無作為抽出する方法。

メリット

  • コストを低く抑えられる
  • 抽出効率が高い

デメリット

  • サンプルサイズが小さい場合、標本に偏りが生じる可能性がある

多段抽出法の例

  1. 日本全国から30市区町村を無作為抽出
  2. 抽出された30市区町村の中からそれぞれ5地区を無作為抽出
  3. 抽出された5地区の中からそれぞれ20人を無作為抽出

系統抽出法

通し番号をつけた名簿を作成し、1番目の調査対象を無作為に選び、2番目以降の調査対象を一定の間隔で抽出する方法。

メリット

  • 単純無作為抽出寄り時間やコストがかからない

デメリット

  • 名簿の並び順に何らかの周期があると、標本に偏りが生じる可能性がある。

系統抽出法の例

1000人から50人選ぶ時、はじめに1000人に通し番号を付け、ランダムに選ばれた番号から3人おきに人を抽出

まとめ

抽出方法のまとめです。実際に現場で抽出とかする場合に、思い出せればいいように思います。

用語 意味
層化抽出法 母集団をあらかじめいくつかの層(グループ)に分け、各層の中から必要な数の調査対象を無作為に抽出する方法
比例配分法 層の大きさに比例させて調査対象を抽出する方法
クラスター抽出法(集落抽出法) 母集団を小集団に分け、その小集団から無作為にいくつか選び、その小集団から全数調査を行う方法
多段抽出法 母集団をいくつかのグループに分け、そこから無作為抽出でグループを選ぶ操作を何度か繰り返して抽出する方法
系統抽出法 通し番号をつけた名簿を作成し、1番目の調査対象を無作為に選び、2番目以降の調査対象を一定の間隔で抽出する方法

客観的な基準だけでは語れないモノ

最近、ふと思うことがあったので書いてみました。たいした話ではありません。
(たいした話でもないと言っておきながら、みんなに読んでほしくて記事にするんだから矛盾してますね)

最近の将棋観戦について

将棋のルールとか詳しいことは分からないけど、観戦するのは楽しいから観戦だけしている、いわゆる「観る将」という方々がいます。私ももれなくその一人に入ります(過去最高は将棋道場でいただいた初段程度ですが)。

最近ではそんな観る将の方々にも楽しんでもらえるよう、将棋だけでなく、両対局者の昼食やおやつ、解説者の趣味なども取り上げられています。加えて、いまやプロをも圧倒する実力をもつ将棋ソフトを使用し、現局面をリアルタイムで解析し、どちらがどれくらい優勢かを値で示す評価値や、次の指し手の最善手も出せるようになりました。

評価値の何がいいかというと、客観的に判断できるところです。

将棋の場合、どちらがどのくらい優勢なのかというのはその人の主観で判断するしかありませんでした。つまり、ある人は先手優勢と思っても、ある人からはまだまだ大変なんてこともあるのです。そのため、ある程度棋力がある人でないと正確な形勢判断は難しく、さらにプロでさえも間違うことがあります。
過去には、相手が詰んでいるにも関わらず投了してしまったプロもいるくらいです。

さて、そんな評価値ですが、見える形になったからこそ問題も生まれました。

客観的な基準の悲劇?

2020年11月7日、8日の2日かけて行われた竜王戦七番勝負第3局にて、将棋ソフトは先手優勢で、先手が最善手を指せば勝ち切れるという評価値を出していました。

しかし、その局面で実際に指された手は異なる手。

将棋ソフトが示した最善手ではありませんでした。

そのため、先手は逆転負け。

コメント欄はまぁ大変なことになったのですが(具体的なコメントは控えますが、対局者に敬意を払えないコメントが多かったです)。

評価値という、客観的な基準が出来たおかげでどちらが有利か不利か、指した手が最善手か悪手か、初心者でもプロでも、誰でも分かるようになりました。

一方、客観的な基準ができたゆえに、将棋ソフトが示す最善手と異なる手は悪手だなんだと言われ、対局者に敬意を払えないコメントが出てくるようになりました。

こんなことになるくらいなら、評価値という客観的な基準なんて無くなってしまえばいいのになと思いました。
初心者からすれば、どちらがどれだけ優勢なのかの理解に苦しむことになりますが、両対局者の一緒のおやつを食べてみるなど、それでも楽しめる部分はあるでしょう。

美術、芸術分野に客観的な基準を設けるべきか

客観的な基準が無い分野と言われ、パッと思いつくのは美術、芸術分野でしょうか。

私は絵を描くことが苦手で美術センスなんてものはありません(小学5年生の時に、担任の先生に描いた絵をぼっこぼこに言われて以来、嫌いになったというのもあります)。

数学の問題を解いてくださいと言われれば、解くことが出来ます。

自画像を描いてくださいと言われると、どうすればいいの?と悩み、結果平面の自画像が出来上がります。

数学の問題が解けることを周りの友人からうらやましがられました。

風景画を描くことのできる友人をうらやましく思いました。

数学の問題を見れば、大体どの公式を使えばいいのか予測がつきました。

画家が描いた絵を見て、表面的な考えしか出ず、どこに注目すればよいか分からず深い考察が出来ませんでした。

(稀に勉強もできて、絵も描けるみたいな人がいますよね。小学3年~5年の間、彼女と一緒だったのですが、いいな~、自分もあんな風になれたらなと思いながら見ていました。
自分の主張を通すような子で、小学生にしては妙に大人びた雰囲気があったように思います。お転婆でしたが。)



そして、毎回思うことがあります。

絵を描くときに、絵を見るときに、何か基準みたいなものがあればいいのになと。

そうすれば、きれいな絵が描けるはずです。

絵画を見たときにどこに注目すればよいか分かるはずです。

今までプロしか感じ取れなかった部分も、素人でも理解できます。



しかしながら。

基準があるということは、それを満たさなければ下手と言われます。

どこに注目すべきかが万人共通ゆえに、みんな感じ方は同じになり、独創的な意見は生まれません。

今までに無い、独創的で革新的な絵を描いたとしても、基準に沿っていなければ、プロのくせに下手だと言う人も出てきます。

単に基準を設ければ万事解決とはいかず、幻想に過ぎないかもしれません。

基準が設けられた分野に素人が気を付けるべきことは?

素人でも趣味程度に理解したい、理解してもらいたいと思うのであれば、基準はあってもいいように思います。

しかし、それはあくまで素人でもちょっとだけその分野を理解できるかもしれない基準だということは認識すべきかと思います。加えて、その基準一つだけで我々素人が威張るようなことがあってはいけません。

完全に理解しようとするのならその分野にどっぷりつかり、しっかり勉強すべきです。

一方で、趣味程度でいいなら、参考程度に先のような基準だけで判断してもいいと思います。どちらかというと、客観的な基準が作られたことに問題があるのではなく、客観的な基準だけで判断し、プロに悪態をつく我々に問題があります。その道で活躍されているプロにはしっかりと敬意を払うべきです。

また、ある程度の経験者、プロの域になると玄人ゆえの視点というものが生まれるはずです。
その視点は1日、2日で身につくものではありません。1~2年でも短いでしょう。もしかしたら5年でも短いかもしれません。
その分野に長年いたからこそ培われた視点は、AIと呼ばれる「モノ」が作り出した一つの客観的な基準だけですべて語れるものではありません。

プロにはプロの視点があります。それはたった一つの基準で出来上がっているのではなく、複数の基準が複雑に絡み合ってできたものでしょう。

その視点を知りもしない我々が、どうのこうのと言える立場ではないことは頭に入れておくべきことと思います。(分かりやすい例は、サッカーの試合でプロ選手がゴールを外したときに、「何外してんねん!わしだったら決めてたわ!!」とか言ってそうな方々でしょうか)。

最後に

誰でも理解できそうな客観的な基準は、あくまで素人が少し理解できる基準でしかないこと。
客観的な基準を参考にしつつ、それでもプロへの敬意は忘れないこと。

これら2つは、プロを目指さなくとも、我々がしっかり守るべきことと思います。

一方、本当にその分野を知りたいのであれば、既存の客観的な基準などに頼らず、その分野を実際に死ぬ気で体験してみればよいと思います。
テレビや本などのフィルターを通して知るのは実際の体験ではありません。

見て、聞いて、触れて、感じて。そこで初めてその分野を理解する一歩に踏み込んだと言えるのではないでしょうか?

Docker Toolboxでポートフォワーディングできない!場合の対処法

最近Dockerというものを勉強しており、理屈はどうあれ最低限業務で使えるようになることを目標に頑張っています。

で、ポートフォワーディングというものに引っかかってしまい、解決まで苦労したのでそれの備忘録的なものです。

「Dockerってそもそも何?」って方には全く訳が分からない記事ですので、ある程度Dockerが使え、Docker Toolboxでポートフォワーディングできなくなったときは参考にしてもらえればと思います。

環境

Windows 10 Pro バージョン 1903
Docker Toolbox
Dockerバージョン: 18.09.1
VirtualBox: 6.1.16

ポートフォワーディングについて

IPネットワーク上のある機器が、自らのIPアドレスTCPUDPの特定のポート番号への通信を、別のアドレスの特定のポートへ自動的に転送すること。また、ネットワーク機器などのもつそのような機能。

IT用語辞典 e-Wordsより

Dockerの場合、コンテナ内のサーバにコンテナ外部からアクセスするためには、このポートフォワーディングが必要で、これをしないとコンテナ外部からコンテナ内のサーバにアクセスすることはできません。

やりたかったこと

ひとまず、コンテナ内のサーバにコンテナ外部からアクセスできることを確かめられれば良かったので、サンプル程度のFlaskアプリを使いました。

用意したファイルは以下の3つです。

  1. sample.py
  2. Dockerfile
  3. requirements.txt

sample.pyの中身

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World! from Docker"

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=7000, debug=True)

Dockerfileの中身

FROM python:latest

COPY requirements.txt /usr/src/app/

RUN pip install --upgrade pip

RUN pip install -r /usr/src/app/requirements.txt

COPY sample.py /usr/src/app/

CMD ["python", "/usr/src/app/sample.py"]

requirements.txt

click==6.6
Flask==0.11.1
itsdangerous==0.24
Jinja2==2.8
MarkupSafe==0.23
Werkzeug==0.11.10

実行

イメージの作成

docker build -t flaskimg .

-t:イメージ名とタグの指定。今回で言えば、flaskimgがイメージ名にあたり、タグはつけていません。
タグをつける場合は、

docker build -t イメージ名:タグ Dockerfileのパス

となります。

コンテナの起動

docker run -d --rm --name flaskcon -p 9000:7000 flaskimg

-d:バックグラウンドで起動
--rm:コンテナ停止後、そのコンテナを削除
--name:コンテナ名の指定。この場合はflaskconという名前を付けています。
-p:ポートの設定です。これを指定しないとコンテナ内部のサーバにコンテナ外部からアクセスすることが出来ません。

-p コンテナ外部からのポート番号:コンテナ内部のポート番号

で指定します。

つまり、コンテナ内部では7000番でアクセスでき、コンテナ外部からは9000番でアクセス(http://127.0.0.1:9000)すれば、コンテナ内部のサーバにアクセスできるわけですが....。

f:id:kurasher:20201108114209p:plain


出来ない。なんでや?

試してみたこと1

調べてみると、Docker Toolboxでポートフォワーディングをやる場合、VirtualBoxの方でも設定をいじらないといけないようです。めんどくさい....。
以下の記事を参考にVirtualBoxで設定を変えます。

Docker Toolboxでポートフォワーディング!【Windows 10 Home】

ホストはコンテナ外部から、ゲストはコンテナ内部を指しているので、それぞれ以下のようにポート番号を指定します。

f:id:kurasher:20201108115625p:plain

これでVirtualBoxを再起動し、再度buildし、runして、http://127.0.0.1:9000でアクセスすると、

f:id:kurasher:20201108114209p:plain

出来ない。なんでや?(2度目)

ちなみに、http://127.0.0.1:7000でも無理でした。

試してみたこと2

今度は以下のようにしてみました。

f:id:kurasher:20201108114901p:plain

そのうえで、VirtualBoxを再起動し、再度buildし、runして、http://127.0.0.1:7000でアクセスすると、

f:id:kurasher:20201108121433p:plain

できた。謎。ちなみに、http://127.0.0.1:9000はアクセスできませんでした。

VirtualBoxの設定と、run時の-pのport番号とコンテナ内のsample.pyのポート番号の組み合わせ

上記3つに対し、いろいろ試した結果を下に記します。sample.pyのポート番号は7000で固定です。

表のVBVirtualBoxの略記です。

No VBのhostポート VBのguestポート -p sample.pyのポート コンテナ外部からのアクセス
1 なし なし 9000:7000 7000 127.0.0.1:7000で不可
2 なし なし 9000:7000 7000 127.0.0.1:7000で不可
3 なし なし 7000:9000 7000 127.0.0.1:7000で不可
4 なし なし 7000:9000 7000 127.0.0.1:7000で不可
5 7000 9000 9000:7000 7000 127.0.0.1:7000で可
6 7000 9000 9000:7000 7000 127.0.0.1:9000で不可
7 7000 9000 7000:9000 7000 127.0.0.1:7000で不可
8 7000 9000 7000:9000 7000 127.0.0.1:9000で不可
9 9000 7000 9000:7000 7000 127.0.0.1:7000で不可
10 9000 7000 9000:7000 7000 127.0.0.1:9000で不可
11 9000 7000 7000:9000 7000 127.0.0.1:7000で不可
12 9000 7000 7000:9000 7000 127.0.0.1:9000で不可
13 7000 8888 9000:7000 7000 127.0.0.1:7000で不可
14 7000 8888 9000:7000 7000 127.0.0.1:9000で不可
15 7000 8888 8888:7000 7000 127.0.0.1:7000で可
16 7000 8888 8888:7000 7000 127.0.0.1:9000で不可
17 7000 8888 8888:7000 7000 127.0.0.1:8888で不可

No1~No4を見る限り、VirtualBoxのポートの設定は絶対に必要と言えます。

それ以外で、アクセスできる設定の共通点を絞り出すと、
VBhostと、-pの右側コンテナ内のサーバのポート番号(今回で言えば、sample.pyのポート番号)、コンテナ外部からアクセスする場合のポート番号同じもの
であることが必要そうです。

加えて、No13の結果も含めて考えると、上記の条件に、
VBguest-pの左側同じ
じゃないといけないみたいです。

いろいろ面倒だなぁ...。

結論

上記をいろいろ考えるとめんどくさいことこの上ないので、以下のようにコンテナ外部からのポート番号をコンテナ内部のポート番号と同じにした方が楽ですね。
-pで指定するときにコンテナ内部のポート番号がどっちに来るかわからなくなりそうですが。

VBのhostポート VBのguestポート -p sample.pyのポート コンテナ外部からのアクセス
7000 7000 7000:7000 7000 127.0.0.1:7000



ちなみに、コンテナ内部のポート番号(今回で言えば、sample.pyのポート番号)を変更すると、いきなりつながらなくなるので注意です。

VBのhostポート VBのguestポート -p sample.pyのポート コンテナ外部からのアクセス
7000 7000 7000:7000 8888 127.0.0.1:7000で不可
7000 7000 7000:7000 8888 127.0.0.1:8888で不可

何にせよ、Docker Toolboxを使う場合は要注意です。

統計学基礎vol.26~全数調査と標本調査~

統計学ばっか上げてんじゃねーよ(# ゚Д゚)」


私のブログを見ていただいている友人からのコメントで、彼としては技術的なことや、作ってみたとかのプロトタイプを取り扱ってほしいんだそうです。

確かに最近統計学が多いな~とは思ってはいました。まぁ、そんなん無視して今回も統計記事ですが...。

気が向いたら統計学以外の何かを上げようと思います。気が向いたらね。

全数調査

調査対象となる母集団をすべて調べること。

例としては、国勢調査が挙げられます。

母集団すべてを調査するわけですからかなり時間がかかります。となると、調査対象から一部だけ取り出して調べる方法が考えられます。

標本調査

調査対象となる母集団の一部を取り出して調べること。

工場での抜き取り調査などが標本調査にあたります。例えば、1万個作成したうち100個を調査し、平均をとるなどして予め決められた基準を満たすかどうかを調べ、


100個中99個が基準を満たすなら、作成された1万個のうち99%が基準を満たす


なんてことが言えるわけです。

抽出のいろいろ

一言に標本抽出と言っても、いろいろな抽出方法があります。順に紹介します。

単純無作為抽出法

母集団から「完全に」「ランダムに」標本を抽出すること。
この抽出では、母集団の中の要素が標本として選ばれる確率は各々等しいという前提条件があり、乱数などで標本を抽出する方法がある。

例えば、ある要素だけものすごく出にくいみたいな前提は仮定していないということです。

復元抽出法

一度抽出された標本を母集団に戻す抽出方法。
調査対象が重複されて標本に含まれる可能性があります。袋の中に赤いボールと白いボールを入れて、1個ボールを取り出して戻すみたいな問題に近いですね。

非復元抽出法

一度抽出された標本は、母集団の中に戻さない抽出方法。
一度抽出された調査対象は、重複して標本に含まれることはありません。これも先に上げた例のように、今度はボールを戻さない問題に近いですね。

コラム:標本の大きさと標本数

標本の大きさと標本数って同じじゃないの?と思うかもしれませんが、違います。
例で理解してみましょう。

日本人から100人を抽出し、アンケートを行う調査を5回繰り返す。
この時、100人が標本の大きさ、サンプルサイズ、5回が標本数、サンプル数と言われます。

ここで、サンプルが「標本」、「群」という意味を持つことを考えれば、

サンプルは、ひとまとまりの観測データ

といえます。つまり、サンプル数はひとまとまりの観測データの数と言えます。


一方、標本の大きさ、サンプルサイズは、1サンプル自体の大きさを表すことになります。
図にすれば以下のようになります。

f:id:kurasher:20201102005319p:plain

まとめ

用語 意味
全数調査 調査対象となる母集団をすべて調べること
標本調査 調査体調となる母集団の一部を取り出して調べること
単純無作為抽出法 母集団から完全に、ランダムに標本を抽出すること
復元抽出法 一度抽出された標本を母集団に戻す抽出方法
非復元抽出法 一度抽出された標本は、母集団の中に戻さない抽出方法
サンプルサイズ 1サンプル自体の大きさ
サンプル数 ひとまとまりの観測データ(サンプル)の数

おそらく、次も統計学の記事ですかね...。