DockerでAWSのEC2上に分析環境を作る

#はじめに
Docker初心者がUdemyの講座「米国開発者がゼロから教えるDocker講座」を受講して学んだ、EC2上にデータ分析環境を作成する方法について、自分で見返すためにも簡単にまとめたものになります。


**バージョン**
・Docker：20.10.8

#Dockerの基礎知識
**・Dockerを使用するメリット**
環境の構築や共有の手間を減らせることが、メインのメリットのようです。
実際、各自が使用しているPCなどに、一から必要なライブラリをインストールして、バージョンを合わせて。。とやっていくのは大分手間がかかりそうです。
Dockerでは、Docker imageさえ共有してしまえば簡単に環境を共有することができます。

**・コンテナ作成までの流れ**
実際に運用するのは作成したコンテナ中ということになりますが、他者と共有するのはそれを作成する元となる、Docker imageやDockerfileになります。下図にdockerにおける作業の大雑把な流れを示しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/863646/01b08cab-2b9f-8c6b-29c6-7c7c6329a402.png)



**・EC2上にDocker imageを作成(共有)する方法**
EC2上にDocker imageを作成(共有)する方法としては、大きく三つあるようです。

▷Docker imageをDocker hubにpushし、そのimageをEC2にpullする。
▷DockerfileをEC2上に送り、EC2上でbuildする。
▷Docker imageをtarファイルにしてEC2上に送る。

三つ目についてはDocker imageのファイルが重くなるため、あまりインターネットを介したやりとりには向いておらず、ローカルで共有する際に使うようです。
今回は一つ目の手法で行いました。

#DockerでEC2上にデータ分析環境を作成する
anacondaをインストールし、jupyter labを立ち上げてくれるデータ分析環境を作成します。
流れとしては、
1.DockerfileからDocker imageをbuild
2.Docker hubにDocker imageをpush
3.AWS ec2にDocker imageをpull
4.Docker runを実行しDocker imageからコンテナを作成

## **●Dockerfileを作成⇨Docker imageをbuild**
Docker imageの元となるDockerfileを作成します。テキストエディタであれば何でも良いかと思います。**Dockerfileのファイル名については、「Dockerfile」が良いかと思います。それ以外の名前の場合は、buildする際に、-f ＜ファイル名＞　のオプションでDockerfileの名前を指定する必要があります。**
下記に今回使用したDockerfileのコマンドを記載しています。

**FROM**
基本的にDockerfileの一番最初に記載し、ベースとなるimageを決定する。ほとんどのケースでOSを指定することになるらしく、今回はubuntuを指定している。
**RUN**
LINUXのコマンドを実行する。
今回は最初にapt-getのアップデートと、sudo,wget,vimのインストールを行なっている。
2回目のRUNでは、wgetでAnacondaインストーラのダウンロード、shでインストーラの実行、rmでインストーラの削除を行なっている。
**WORKDIR**
RUNを実行する場所を変えることができる。今回はルート直下ではなくopt内にanacondaをインストールするため、/optに移動している。パッケージをインストールする際、optにインストールするのは割と定番の流れらしい。
**ENV**
環境変数を設定することができる。パスを通すときによく使用する模様。
今回は、anacondaのパスを通している。
**CMD**
コンテナのデフォルトで実行されるdockerコマンドを指定でき、基本的にDockerfileの最後に記載する。
今回はjupyter labをローカルホストに起動するためのコマンドを指定しています。
※jupyter lab起動時のコマンドについては[こちらの記事][link-1]が分かりやすかったです。
[link-1]:https://qiita.com/ao_log/items/5438f2aaf5c2b46d2ccb
*Dockerfileの作成*

```docker
FROM ubuntu:latest
RUN apt-get update && apt-get install -y \
    sudo \
    wget \
    vim
WORKDIR  /opt
RUN wget https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh && \
    sh /opt/Anaconda3-2019.10-Linux-x86_64.sh -b -p /opt/anaconda3 && \
    rm -f Anaconda3-2019.10-Linux-x86_64.sh
ENV PATH /opt/anaconda3/bin:$PATH

RUN pip install --upgrade pip
WORKDIR /

CMD ["jupyter", "lab", "--ip=0.0.0.0", "--allow-root", "--LabApp.token=''"]
```

Dockerfileを作成したら、コンソールでbuildします。
今回はファイル名「Dockerfile」で作成したため、-fの指定なしでbuildします。
anacondaという名前のimageをbuildします。

*docker build -t イメージ名 Dockerfileのディレクトリ*

```console
docker build -t anaconda .
```


特にエラーが無ければdocker imagesを実行して下記のようにimageができているかと思います。
*docker images*

```
REPOSITORY                     TAG       IMAGE ID       CREATED        SIZE
anaconda                       latest    f211111117   3 weeks ago    3.42GB
```

## **●Docker imageをDocker hubにpushする**
次にこのimageをDocker hubにpushします。

**・Docker hub上にリポジトリを作成**
pushする前に、Docker hub上にpush先となるリポジトリを作成しておく必要があります。
https://hub.docker.com/
こちらのDocker hubのページにログインして最初のページに出てくる「Create Repository」ボタンで、適当な名前のリポジトリを作成します。基本的に一つのリポジトリに対し、一つのimageを格納する形になるようです（ただし一つのimageに対して複数のタグを作成可能）。

**・pushする**
作成したリポジトリにimageをpushするのですが、pushするimageの名前は、**「Dockerに登録したユーザー名/さっき作成したリポジトリ名」**である必要があります。そこで、さっき作成したimageの名前を変更します。

*docker tag 変更前のimage名 変更後のimage名*

```
docker tag anaconda ユーザー名/リポジトリ名
```
これでpushできるようになったので、pushします。
*docker push image名*

```
docker push ユーザー名/リポジトリ名
```

これで、Docker hubのリポジトリ上にimageがpushできました。

##●aws ec2にDocker imageをpull
ec2上にubuntuのインスタンスを立て、dockerをダウンロードします。

インスタンス上で下記を実行

```
sudo apt-get update
sudo apt-get install docker.io
sudo gpasswd -a ubuntu docker
```
これで、インスタンス上でdockerが使用できるようになりました。
あとはDocker hub上から、imageをpullしてくるだけです。

*docker pull image名*

```
docker pull ユーザー名/リポジトリ名
```

これでec2上にdocker imageを共有することができました。

##●Docker imageをrunし、jupyter labを立ち上げる。
それでは、コンテナをrunします。

runする際に使用したオプションを記載します。
**--rm**
コンテナ使用後に自動で削除される
**-v ホストのディレクトリパス:コンテナ内のディレクトリパス**
ホストのディレクトリと、コンテナのディレクトリをマウントできる。
**-p ホストのポート:コンテナのポート**
ホストのポートとコンテナのポートを接続する。

*docker run --rm -v ~/mouted:/work -p 8888:8888 image名*

```
docker run --rm -v ~/mounted:/work -p 8888:8888 ユーザー名/リポジトリ名
```

上記を実行し、jupyter labが立ち上がります。
実際にブラウザで下記のURLを入力し、接続してみます。
*ec2のパブリックアドレス:8888*


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/863646/8b71c60e-9a7f-f729-3198-903f8902ebf6.png)



開きました！
今回はworkディレクトリにマウントしたため、workディレクトリ内で作業すれば、ホスト側のディレクトリでも反映されます。