サクッとDockerを使ってみる


# Dockerとは？
Dockerとは、コンテナと呼ばれる単位でアプリケーションをまとめて実行できるプラットフォームです。
コンテナ型の仮想化は、アプリケーションとその依存関係をまとめて実行するための軽量な仮想化技術です。
ホストOS上にDockerが動作しており、その上にコンテナが載るイメージです。
開発環境をコンテナとして用意しておけば、ホストOSが異なっていたりしてもDockerが環境の差異を吸収してくれるため、開発環境の再現性が高まります。
これによって、開発者は各々のPC環境を気にすることなく、少しのコマンドを実行するだけで環境を整えることができるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661573/a896757d-3404-442d-af84-23018b4aebfa.png)

# 実際に使ってアプリを作ってみる
練習として、Dockerで構築した環境を使ってシンプルなデモアプリを作成しました。
表示された画像にマウスで点を打って、その位置の物体に色を塗るだけの簡単な画像系AIアプリです。
![image-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661573/ce56dc2e-2a8d-4d68-8745-e5d15bbdfd49.png)

手順は以下です。
1. 環境構築
    - Dockerのインストール
    - Docker imageの作成
    - コンテナの作成
2. コーディング、githubにアップロード
3. ゼロから環境構築～アプリを動かすまでを確認

## 1. 環境構築
### Dockerのインストール
[公式サイト](https://docs.docker.com/get-started/get-docker/)からDocker Desktopをダウンロードします。

ターミナルで`docker --version`を実行してバージョンが表示されればOK。

### Dockerイメージの作成
コンテナを作る前にDockerイメージというコンテナの設計書みたいなものを作る必要があります。
Dockerイメージを作るには、必要なパッケージ等をインストールするためのコマンドを書いたDockerfileを作成する必要があります。
Dockerfileは以下のような感じで記述します。
```
# Docker Hubからubuntuのイメージを取得
# Docker HubはDockerの公式レジストリで、イメージを公開・共有できる
# gpuを使うために、nvidiaのcudaイメージを使用
FROM nvidia/cuda:12.1.1-cudnn8-runtime-ubuntu22.04

# 非対話モード（aptでエラー出さないように）
ENV DEBIAN_FRONTEND=noninteractive

# 必要なパッケージをインストール（ここでは簡単にpythonとpipとgitだけ）
# apt cleanでキャッシュを削除
# 容量を小さくするため、基本的にキャッシュは残さない
RUN apt update && apt install -y \
    wget \
    python3 \
    python3-pip \
    git \
&& apt clean


# 作業ディレクトリの指定
WORKDIR /workspace

# ホストのカレントディレクトリをコンテナの作業ディレクトリにコピー
# Docker Desktopは裏でLinuxの仮想マシンを動かしているので、
# 作業ディレクトリはLinuxのファイルシステムで管理される
COPY . /workspace

# 必要なパッケージをインストール
RUN pip install -r requirements.txt
RUN git clone https://github.com/facebookresearch/sam2.git
RUN cd sam2 && pip install . && cd ..

# AIモデルのダウンロード
RUN wget https://dl.fbaipublicfiles.com/segment_anything_2/092824/sam2.1_hiera_tiny.pt -O sam2/checkpoints/sam2.1_hiera_tiny.pt
```
次に、`docker build`コマンドでDockerイメージを作成します。
```
docker build -t my-image .

# imageが作られたか確認
docker images
```
`-t`はimageの名前をつけるオプション。
最後の`.`はDockerfileがあるディレクトリのパスを指定。

### コンテナの作成
Dockerイメージを作ってしまえば、あとは`docker run`でコンテナを立ち上げるだけです。
```
docker run --gpus "device=0" -it --name my-container my-image /bin/bash

# カレントディレクトリを確認
# Dockerfileで指定した作業ディレクトリにいるはず
pwd
```
`--gpus "device=0"`でAIを使うためのGPUを指定する。
`-it`がないとコンテナの中に入れないので必須。
`--name`は作成するコンテナ名のオプション。
`/bin/bash`は中でbashを起動するための記述。

## 2. コーディング・githubにアップロード
割愛します。
https://github.com/kujitama/my-docker-test

## 3. ゼロから環境構築してアプリを動かしてみる
最後に、環境構築してアプリを動かすまでどのくらいの手間になるのか確認してみました。
手順と実行したコマンドは以下です。
1. githubからクローンしてくる
2. 環境構築（イメージとコンテナの作成）
3. アプリ実行
```
git clone https://github.com/kujitama/my-docker-test.git
docker build -t my-image .
docker run --gpus "device=0" -it --name my-container my-image /bin/bash
streamlit run main.py
```
アプリ実行まで4行でできるので、そこそこ楽でした。
何より、コマンドを実行するだけなら知見がなくても問題ない、というのがメリットとして大きいと感じます。
もっと大きなプロジェクトをチームで開発していく場合には、より恩恵が大きくなっていくと思います。

# Docker 基本コマンドまとめ
最後に、Dockerの基本的なコマンド操作を軽くまとめておきます。

## イメージ操作

| コマンド例                                   | 説明                                           |
|----------------------------------------------|------------------------------------------------|
| `docker build -t my-image .`                 | Dockerfileからイメージをビルド（`-t`で名前付け） |
| `docker images`                              | イメージ一覧を表示                              |
| `docker rmi my-image`                        | イメージを削除                                  |
| `docker pull ubuntu:22.04`                   | Docker Hubなどからイメージを取得                |
| `docker tag my-image my-image:1.0`           | イメージにタグを付ける                          |
| `docker save -o image.tar my-image`          | イメージをファイルとして保存                    |
| `docker load -i image.tar`                   | ファイルからイメージを読み込み                  |

---

## コンテナ操作
コンテナIDはコンテナ名でも可

| コマンド例                                   | 説明                                           |
|----------------------------------------------|------------------------------------------------|
| `docker run -it ubuntu bash`                 | コンテナを起動して中に入る（対話モード）        |
| `docker run -d --name web my-image`          | バックグラウンドでコンテナを起動               |
| `docker ps`                                  | 実行中のコンテナ一覧を表示                      |
| `docker ps -a`                                | すべてのコンテナ一覧（停止中含む）              |
| `docker stop コンテナID`                     | コンテナを停止                                  |
| `docker start コンテナID`                    | 停止中のコンテナを起動                          |
| `docker restart コンテナID`                  | コンテナを再起動                                |
| `docker rm コンテナID`                       | コンテナを削除                                  |
| `docker exec -it コンテナID bash`            | 実行中のコンテナに接続（bash起動）              |
| `docker logs コンテナID`                     | コンテナのログを見る                            |
| `docker cp コンテナID:/path/file.txt ./`     | コンテナからホストへファイルをコピー            |

---

## ボリューム・ファイル共有

| コマンド例                                   | 説明                                           |
|----------------------------------------------|------------------------------------------------|
| `docker run -v $(pwd):/app my-image`         | ホストのカレントディレクトリを `/app` にマウント |

---

## システム管理

| コマンド例                                   | 説明                                           |
|----------------------------------------------|------------------------------------------------|
| `docker system df`                           | 使用中のリソース容量を表示                      |
| `docker system prune`                        | 未使用リソース（イメージ・コンテナ等）を一括削除 |
| `docker image prune -a`                      | 未使用のすべてのイメージを削除                  |
| `docker container prune`                     | 停止済みコンテナを削除                          |

---

## 確認系

| コマンド例                                   | 説明                                           |
|----------------------------------------------|------------------------------------------------|
| `docker version`                             | Dockerのバージョン情報を表示                   |
| `docker info`                                | Dockerの詳細設定やリソース状況を表示           |

---

## 各種オプション

| オプション | 内容                                      |
|------------|-------------------------------------------|
| `-i`       | 標準入力を有効にする（対話モード向け）     |
| `-t`       | 仮想端末を割り当て（端末らしい出力）       |
| `-v`       | ホストとコンテナ間のディレクトリ共有        |
| `-d`       | コンテナをバックグラウンドで起動            |
| `--rm`     | コンテナ終了時に自動で削除                   |