Docker備忘録

# Docker備忘録

## ***カーネルについて***

> カーネル（kernel）とは、オペレーティングシステム（OS）の基本機能の役割を担うソフトウェアを指す。

## ***Dockerを使用するメリット***

- DockerではホストOSのカーネルを使う　→ （仮想環境に比べて）処理にかかるコストが低い
- PCに直接インストールしないのでosを汚さない
- Dockerファイルをもとにインフラを構築できるので、設定が簡単
- アプリの動作に必要なライブラリやパッケージがまとめられているので、異なるosやマシンでも動作する（ポータビリティが高い）

## ***コンテナイメージ***

- 基本的なアプリ、ソフトウェア、実行システム、実行コマンド、メタ情報が含まれている。
- イメージを元にコンテナを作成する
- コンテナ自体を他の環境に配布できないが、イメージは配布が可能。
- 一つのイメージから複数のコンテナを作成できる。

## ***レジストリ***

- インターネット上にコンテナイメージが集められた場所のことを指す。（DockerではDocker Hub（公式）が有名）
- 基本的にはレジストリにあるイメージをそのまま使うかカスタマイズして使う。
- レジストリからイメージを取得することをpullと呼ぶ
- レジストリにイメージを登録することをpushと呼ぶ
- Dockerファイルを使ってイメージを構築することをbuildと呼ぶ
- 自分の作成したい環境に合わせてバージョンを選ぶことができる。（バージョンはタグとして付与されている。

## ***コンテナのライフサイクル***

- 「作成」「実行」「停止」「削除」
- Dockerではコンテナの状態を変化させるのに、dockerコマンドを使う。  

```sh
docker container create
docker container run
```

- なぜコンテナは作っては削除するのか？作成したコンテナを変更して使い続けるより、削除して作り直すほうが手間がかからないから。

## ***Dockerのアーキテクチャ***

- Dockerはクライアント・サーバーシステム  

> ※下記の３つの要素で構成される。  

1. Dockerクライアント　→ Dockerを操作するには、Dockerを操作するサーバーに対してリクエストを発行する。（ターミナルやシェルから）
1. Dockerデーモン　→ クライアントからのリクエストを受け取るのは、Dockerデーモンと呼ばれるソフトウェア（RestAPI)
1. レジストリ　→ イメージはDocke Hubなどのレジストリからプルする。

## ***AppleシリコンMacでDockerを使うときの注意点***

- AppleシリコンMacはARMアーキテクチャを使用する。
- AppleシリコンMacでIntelアーキテクチャ用のイメージを使おうとした場合は、対象のイメージがARMアーキテクチャ用でなはいことを表す下記のエラーが発生する

```text
「no matching manifest for linux/arm64/v8 in the manifest list entires」  
「WARNING: The requested image’s platform (linux/amd64)
does not match the detected host platform (linux/arm64/v8) and no specific platform was requested」
```

- 以上より、Docker Hubの「OS／ARCH」列を参照し、linux/arm64/v8が表示されていることを確認して使用する。
- AppleシリコンでDockerを使うにはRosetta2(AppleシリコンでIntelアプリケーションを使用することができるソフトウェア）をインストールしておく。  

```sh
software update ―install-rosetta
```

## ***Docker Desktopの使い方***

- よく使う３つのタブ

1. Containers 作成済みのコンテナが一覧で表示される。
1. Images 取得済みのイメージが一覧で表示される。
1. Volumes 作成済みのボリュームが一覧で表示される。（ボリュームとはコンテナのデータを保存する場所のこと）

## ***Dockerコマンドの基本***

```sh
docker 対象 操作 -オプション　パラメータ -オプション　パラメータ
```

## ***ターミナル便利なコマンド***

```sh
cd ~ ホームディレクトリに戻る
cd ../　一つ前のディレクトリに戻る
cd Tab押下　カレントディレクトリにあるディレクトリを順番に挿入する
clear ターミナルの表示ををクリアする
```

## ***Apacheのコンテナを作成する***

- コンテナを作成する（コンテナ名を「apache01」ポート番号を「8080:80」に指定した場合）

```sh
docker container run ―name apache01 -p 8080:80 -d httpd
```

- コンテナを停止する

```sh
docker container stop apache01
```

> ※Docker Desktop上では停止中は アイコンはExitedとなりグレー色になる

- コンテナを削除する

```sh
docker container rm apache01
```

> docker container run だと複数のコンテナを作成する際に手間がかかる（毎回記入すると保守的に良くない）
> そこでDocker Compose（ドッカーコンポーズ）というソフトウェアを使ってよく使うコマンドやオプションをまとめておく。

## ***Docker Compose***

- 一度に複数のコンテナを作成・実行できるソフトウェア
- docker composeコマンドを使う
- Docker Composeでコンテナを作成するには、YAMLファイルでどういうコンテナを作成するかを定義する
- Docker ComposeにおけるYAMLのデフォルトの名前はcompose.yaml
- Docker Compose作成の３ステップ

1. 作成したいコンテナの情報を整理する
2. Docker Composeファイルを作成する
3. コマンドを使ってコンテナを作成・実行する

> ※Docker Composeには現行であるV2バージョンを使う

## ***Docker Compose作成***

- プロジェクトに使われるカレントフォルダー名には何のコンテナ・環境なのかがわかりやすい名前を付けておく。  例）apache
- YAMLファイルを記述する
- ターミナルでcompose.yamlファイルがあるディレクトリに移動
- コマンドを実行する  
  （ローカルに対象のイメージが存在しない場合はイメージをプルしてから、コンテナを作成・実行する）  
  -dオプションはコンテナをバックグラウンドで実行させるオプション。続けて捜査を行いたい場合は付与しておく

```sh
docker compose up -d
```

- コンテナが作成されたかを確認する

```sh
docker container ls
```

  出力に「STATUS　→ UP」と表示されていれば、コンテナが実行されている。  

- すべてのコンテナを一覧表示

```sh
docker container ls -a
```

- Docker Composeのプロジェクトを一覧表示

```sh
docker compose ls
```

- コンテナを停止する

```sh
docker compose stop
```

- 作成済みのコンテナを起動する

```sh
docker compose start
```

## ***Docker Composeファイルの構文***

```yaml
services:
  web:
    image: httpd:2.4
    ports:
    - "8080:80"
networks:
  netweb01:
volumes:
  volweb01:
```

1. services&nbsp;&nbsp;コンテナの定義を書くところ。複数のコンテナを作りたいときは、servicesはいかにコンテナの定義を複数書く。
2. コンテナ名&nbsp;&nbsp;コンテナの名前を記述する
3. image&nbsp;&nbsp;使用するイメージの名前を書く。
4. ports&nbsp;&nbsp;Dockerとホストとコンテナのポート番号の紐付けを書く  

> ※ ホストのポート番号：コンテナのポート番号を指定する際は文字列で記載する必要がある 例) "8080:80"
> ※ services 意外にもコンテナで使うネットワークを設定する「netwoks」やデータの保存に関して設定する「volumes」などの大項目がある。

## ***コンテナ内へファイルをコピーする***

- 修正したプログラムを反映したり設定ファイルを差し替えたりする場合、cpコマンドを実行する。

```sh
docker compose cp ホストファイルパス　コンテナ名：コンテナ内のファイルパス
```

- コンテナ内のファイルをDockerホストにコピーする

```sh
docker compose cp コンテナ名：コンテナ内のファイルパス　ホストのファイルパス

docker compose cp web:/usr/local/apache2/htdocs/index.html .
```

## ***コンテナを使い終わったら***

- 検証のたびに新しいコンテナを作るなど要領を占有しがち
- 不要になったら都度、削除する習慣をつける

```sh
docker compose down
```

- オプション一覧
  - --rmi  イメージを削除。「all」を指定した場合は、サービスで使うすべてのイメージを削除。「local」を指定した場合は、カスタムタグがないイメージだけを削除
  - -v  Docker　Composeファイルの「Volumes」に記載したボリュームと、コンテナにアタッチされた匿名ボリュームを削除
  - --remove-orphans  Docker Composeファイルで定義されていないコンテナも削除  

> ※コンテナを削除するとデータも削除される。docker compose cpコマンドで、コンテナ内へコピーしたファイルも、合わせて削除される。

### コンテナを削除する方法

- compose.ymlのあるディレクトリに移動
- コンテナを削除する

```sh
docker compose down
```

- 削除されたことを確認する

```sh
docker container ls
```

- プロジェクトが削除されたことを、確認する

```sh
docker compose ls
```

- コンテナを作成するためのテンプレートである「イメージ」も合わせて削除する

```sh
docker compose down --rmi all
```

> ※実行した際に「Error response from daemon: conflict: unable to remove repository reference ${CONTAINER_NAME} is using its referenced image ~」というエラーが表示されたら、そのイメージを使用しているコンテナが他にもあるということ。対象のコンテナを削除してから、再実行する

- imageが削除されたことを確認する

## ***MariaDBコンテナを構築する***

- データベースにはユーザー名やパスワード等の設定が必要。コンテナを作る際も同様
- コンテナ技術では、パラメータをコンテナに設定したり、コンテナ間で値を受け渡したりするのに、環境変数がよく使われる。
- どんな環境変数が用意されているのかを調べるには、そのイメージのドキュメントを参照する必要がある。
- コンテナに環境変数を設定するには、Docker Composeファイルの「services」で「environment」という項目を記述する

  - MARIADB_ROOT_PASSWORD　ルートユーザーのパスワード
  - MARIADB_DATABASE データベース名
  - MARIADB_USER  データベースのユーザー名
  - MARIADB_PASSWORD  データベースのパスワード

- カレントフォルダー「mariadb」を作成する
- compose.yamlを作成する

```yaml
services:
  db:
    image: mariadb:10.7
    environment:
      MARIADB_ROOT_PASSWORD: rootpass
      MARIADB_DATABASE: testdb
      MARIADB_USER: testuser
      MARIADB_PASSWORD: testpass
    volumes:
      - db-data:/var/lib/mysql
volumes:
  db-data:
```

- compose.yamlを配置した階層でコマンドを実行する

```sh
docker compose up -d
```

> コンテナが作成されると「Container[コンテナ名] Started」というログが表示される

## ***コンテナ内でコマンドを実行する***

- コンテナ内のディレクトリを確認したり、コンテナにソフトウェアをインストールしたりする場合はコンテナ内でコマンドを実行する。

- 方法１

```sh
docker compose exec コンテナ名　コンテナで実行したいコマンド
```

  mariadbコンテナ内でバージョンを調べる

```sh
docker compose exec db mariadb --version
```

> ※ ホストではなくコンテナ内のmariadbのバージョンを確認できる

- 方法２
シェルを使用する（シェルとは受け取ったコマンドをカーネルに伝えるプログラムのこと）要はコマンドを実行できるインターフェース  
bash(Bourne Again Shell)最もスタンダードなLinuxの標準シェル  
bashと呼ばれるシェルを使うには、「docker compose exec」コマンドで、「/bin/bash」を指定する。  

```sh
docker compose exec コンテナ名 /bin/bash
```

- 作成したdbコンテナ内でシェルを起動する

```sh
docker compose exec db /bin/bash
```

- バージョンの確認

```sh
mariadb --version
```

- MariaDBに標準で搭載されているCLIを起動する

```sh
mariadb -u testuser -D testdb -p
```

> ※ シェルを起動しておくと、複数の操作を連続して行いやすくなる。コンテナ内でコマンドを何度も実行したい場合や、初期設定が必要なコマンドを実行する場合は、シェルを起動してみる。  
MariaDBのCLIを終了するには「\q」、execで立ち上げたシェルを終了するには「exit」を入力する。

- 使い終わったコンテナを停止させる

```sh
docker compose stop
```

- 不要な場合はコンテナを削除する

```sh
docker compose down
```

## ***WordPress - MariaDBコンテナの構築***

- DockerHubのURL  
[Wordpress](http://hub.docker.com/_wordpress)
[Mariadb](http://hub.docker.com/_/mariadb)

- WordPressイメージの主な環境変数
  - WORDPRESS_DB_HOST: 接続先コンテナ名
  - WORDPRESS_DB_USER:　接続先のデータベースのデータベース名
  - WORDPRESS_DB_PASSWORD:　接続先のデータベースのユーザ名
  - WORDPRESS_DB_NAME:　接続先のデータベースのパスワード

- プロジェクトに使われるカレントフォルダー「wordpress」の作成

- Docker Composeファイルの作成

```yaml
services:
  db:
    image: mariadb:10.7
    environment:
      MARIADB_ROOT_PASSWORD: rootpass
      MARIADB_DATABASE: wordpress
      MARIADB_USER: wordpress
      MARIADB_PASSWORD: wordpress
    volumes:
      - db-data:/var/lib/mysql
  wordpress:
    image: wordpress:6.0
    depends_on:
      - db
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
    ports:
      - "8080:80"
    volumes:
      - wordpress-data:/var/www/html
volumes:
  db-data:
  wordpress-data:
  ```

> portsでdockerホストのポート番号とコンテナのポート番号を紐づけている

```sh
depends_on:　（コンテナの依存関係を設定する項目）
 - db
 ```

depends_onによりMariaDBコンテナ、WordPressコンテナの順に作成される。
wordpressのenvironmentにはmariadbの設定を記述する。

- コンテナの作成

```sh
docker compose up -d
```

- コンテナの削除

```sh
docker compose down
```

> ※ 柔軟な設計にするため、実際にはmariadbとwordpressのコンテナはそれぞれ単独で作成する。
> 機能ごとに１コンテナになるようにする。

## ***データの永続化***

- ボリュームを使う  
Dockerが管理する記憶領域にエータを永続化する仕組み。  
バインドマウントよりデータの移行やバックアップが容易。  
コンテナを削除しても、ボリュームさえ残しておけば、再度コンテナを作成した際にそのボリュームをマウントすれば、データを利用できる。  
Docker Composeファイルのservices下のvolumesに記載すると、対象のコンテナがボリュームで永続化される。

```yaml
services:
  コンテナ名:
    image: 使用するイメージ名
    volumes:
     - 「volumes」に定義したボリューム名:コンテナ内のパス
volumes:
  ボリューム名
  ```

- バインドマウントを使う  
ホストOSのフォルダーやファイルをマウントする仕組み。  
データを変更する際は、ホストOSのファイルを直接変更することで、コンテナ内にも自動で反映される。  
変更の頻度が高いデータに向いている。ホストマシンによってフォルダー構成は異なる可能性があるので、汎用的ではない。

```yaml
services:
  コンテナ名:
    image: 使用するイメージ名
    volumes:
      - ホストOSのフォルダー:コンテナ内のパス
```

> ※ 公式では、ボリュームの使用が推奨されている。

- バインドマウントにしたWordPressコンテナを作成する

```yaml
services:
  db:
    image: mariadb:10.7
    environment:
      MARIADB_ROOT_PASSWORD: rootpass
      MARIADB_DATABASE: wordpress
      MARIADB_USER: wordpress
      MARIADB_PASSWORD: wordpress
    volumes:
      - db-data:/var/lib/mysql
  wordpress:
    image: wordpress:6.0
    depends_on:
      - db
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
    ports:
      - "8080:80"
    volumes:
      - ./html:/var/www/html
volumes:
  db-data:
```

- コンテナの作成

```sh
docker compose up -d
```

- バインドマウントのためのWord Pressのファイルがホストのフォルダーに作成される

## ***Flaskコンテナを構築する***

Flask　PythonのWebフレームワーク

- Flaskの環境構築手順

1. Pythonをインストール
1. 「pip install flask」コマンドでFlaskをインストール
1. Flaskで動作させるプログラムを作成
1. 「flask run」コマンドを実行して、Flaskに組み込まれているWebサーバーを実行。Flaskのコンテナを作るには、Pythonのイメージに対して、上記の手順を行う必要がある。

> ソフトウェアのインストールやファイルのコピーを行ったイメージを作りたい場合は、Docker Fileを使う。
> ※ Docker Fileとは、どんなイメージを作るのか記述するテキストファイルのこと

- 必要なファイルの作成（flaskフォルダー内）

```text
.
├── Dockerfile
├── compose.yaml
└── src
    └── app.py
```

app.py

```python
 from flask import Flask

 app = Flask(**name**)

 @app.route('/')
 def hello_flask():
     return 'Hello Flask!'
```

「どんなイメージを作りたいのか整理する」  

- 「pip install flask」コマンドを実行してFlaskをインストールする
- 「app.py」をコンテナ内へコピーする
- 「flask run --host=0.0.0.0」コマンドを実行して、Flaskに組み込まれているWebサーバーを実行

Dockerfile

```text
FROM python:3.10  #①イメージの指定
WORKDIR /usr/src/app  #②作業ディレクトリの指定
RUN pip install flask==2.1.0  #③イメージのビルド時にコマンドを実行
CMD ["flask", "run", "--host==0.0.0.0"]   #④コンテナの起動時にコマンドを実行
```

```yaml
compose.yaml
services:
  web:  #コンテナの名前
    build: .
    environment:
      FLASK_ENV: development  #環境変数名
    ports:
      - "5000:5000" #ポート番号
    volumes:
      - ./src:/usr/src/app  #ボリューム
```

> 「build」に 「.」 を書くとカレントフォルダーにあるDockerfileを使ってイメージが作成される。  
> Flaskでプログラムの即時反映をするには、環境変数「FlasK_ENV」を「development」にする  
> ポート番号には、Flaskのデフォルトポート番号の「５０００」を指定する  
> プログラムに変更がしやすいように、app.pyを格納した「src」フォルダーと、コンテナ内の「/usr/src/app」をバインドマウントに設定する。

- コンテナの作成
docker compose up -d

- イメージの再ビルド

```sh
docker compose build
```

- イメージの再ビルド（キャッシュを使わない）

```sh
docker compose build --no-cache
```

## ***Dockerのネットワーク***

- Dockerのネットワークを一覧表示する

```sh
docker network ls
```

- Dockerの３つのデフォルトネットワーク
  - bridge　コンテナ間、コンテナ外と通信できるネットワーク
  - Host　Dockerホストのネットワークをそのまま使う
  - none  コンテナ間、コンテナが最も通信できない

## ***YAMLファイル　ルール***

- 行頭にハイフンがある場合次のハイフンが現れるかインデントが戻るまで配列の１要素として扱う。