遅くともやりたい！Docker初心者が頑張って基礎をまとめる



# はじめに
本当に今更ながらDockerに入門したので、学んだことをメモもかねてまとめていきます！


TypeScriptを勉強していた時に、
「Docker使って環境作ればDockerの勉強もできて最高なんじゃ...？」
と思い入門。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265446/886336bd-fe9c-783a-b5c6-85cb23b8d032.png)

# そもそもDockerとは？
難しく言えば、Docker社が提供する「コンテナ型仮想化技術」 を実現するプロダクト...
ざっくり言えば、コンテナという技術を使ってみんなで同じ環境を簡単に使えるようにしよう！というものみたいです。

例えば複数人で開発を行う場合、どの言語・ライブラリをインストールするのか、またそのバージョンはいくつなのかを一つ一つ確認しなければいけません。
どこかが違うと、「このマシンでは動作するが、他のマシンでは動作しない」という問題が発生することがあるからです。

そんな時、Dockerを使っていれば、すべてのマシンで完全に同一の環境を再現できます。
何か変更や追加があった場合もDockerイメージというものを更新すればすべての環境を最新に更新できる、という優れものみたい。


# Dockerで環境を作るための流れ
いきなり手順に入るとわかりにくかったので、簡単な流れを説明します。

1. Dockerfileの作成
    -  どんな環境を作るか定義したファイル（イメージ作成の手順的な感じ）
2. Dockerイメージの作成
    - Dockerfileをビルドすることで作成されるもの
    - コンテナの実行に必要な全てのファイルを含む読み取り専用のテンプレート
3. Dockerコンテナを作成
    - Dockerイメージ実行することで作成される
    - これが作成された環境

Dockerイメージと、Dockerコンテナの違いが最初よくわからなかったのですが、クラスとインスタンスの関係性に例えるとわかりやすかったです。
Dockerイメージ：「クラス」に相当し、その設計図（定義）を提供する
Dockerコンテナ：「インスタンス」に相当し、その設計図を元に作成され、実行されるもの

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265446/e9d21a69-cd5e-f711-7c4b-f133eb3c2390.png)


# 実際に動かしてみる
それでは実際に動かしてみます
あくまで、自分が環境を作ったときに触ったコマンドだけなので、網羅はしていないしこれが最適解ではないかもしれないです（もし間違っていたら教えてください...）。

## Dockerをインストールする
まずはインストール。
[Dockerの公式ウェブサイト](https://www.docker.com/products/docker-desktop/)からインストーラをダウンロードし、指示に従ってインストールします。
手順は下記の記事を参考にさせていただきました（ありがとうございます）。
[Docker for Windows のセットアップ](https://qiita.com/gate9/items/7820fea4017e5ef9db97)


インストールが成功したかどうかを確認するために、コマンドラインから`docker --version`を実行します。これにより、インストールされたDockerのバージョンが表示されていれば成功です。

```
docker --version
```

## Dockerfileを作成する
Dockerfileは、Dockerイメージの作成手順を定義するテキストファイルです。
今回はTypeScriptを勉強したかったので、Node.jsの環境作る場合の基本的なDockerfileです。

他の言語の環境を作る際は、調べてみてください。

```Dockerfile
# ベースとなるイメージを指定
FROM node:14

# ワーキングディレクトリを設定
WORKDIR /usr/src/app

# ライブラリをインストール
RUN npm install -g typescript
```

## Dockerイメージを作成する
Dockerfileがあるディレクトリに移動し、`docker build`コマンドを実行してDockerイメージを作成します。
以下の例では、イメージにmy_node_appという名前を付けています。
```
docker build -t my_node_app .
```

Dockerイメージが正しく作成されたか、以下のコマンドで確認できます。
```
docker images
```

## Dockerイメージを実行してDockerコンテナを作成する
作成したDockerイメージを実行してコンテナを作成します。
`docker run`コマンドを使用します。

```
docker run my_node_app
```

<details><summary>【参考】コンテナ内のディレクトリをホストのディレクトリにマッピングする方法</summary>

ホスト：/home/user/my_node_app
コンテナ：/usr/src/app
```
docker run -v /home/user/my_node_app:/usr/src/app my_node_app
```

これにより、ホストマシンの/home/user/my_node_appディレクトリの内容がコンテナ内の/usr/src/appに反映され、またその逆も可能となります。この機能は、コンテナ内で行った変更をホスト側にも反映させたい場合や、ホスト側のファイルをコンテナ内で利用したい場合などに便利になります。

:::note warn
ただし、ボリュームマウントは、コンテナのファイルシステムとホストのファイルシステムの間で直接ファイルを共有するため、セキュリティ面で注意が必要です。不適切なマウント設定は、ホストマシンに悪影響を及ぼす可能性があります。
:::

---

</details>

Dockerコンテナが正しく動作しているかは、以下のコマンドで確認できます。
```
docker ps
```

これで、Dockerコンテナ内にNode.jsとTypeScriptの開発環境が作成できました！
この環境は、同じDockerfileを使用すればどのPCでも再現可能です。

## 作った環境でHello, Worldしてみる
すでにDocker上でNode.jsとTypeScriptの環境ができていると思います。

早速Hello, Worldしてみましょう。
今回は、/usr/src/appディレクトリ内にtest.jsというファイルを作成し、その中に以下のようなコードを記述します。

```
echo 'console.log("Hello, World!");' > test.js
```
その後、以下のコマンドで実行。
```
node test.js
```

これで、"Hello, World!"というメッセージが表示されれば、正しく実行できています！！！
この環境でいっぱい勉強できますね！！

おつかれさまでした！

## コンテナ・イメージを削除する
このままコンテナを生成しまくっていたらメモリに限界がきます。

`docker ps`で削除したいコンテナIDを確認して、以下のコマンドでコンテナを削除します。

```
docker rm 【削除したいコンテナのdocker id】
```

またイメージも以下のコマンドで削除できます。

```
docker rmi 【削除したいimageのimage id】
```
一括削除したい場合は以下のコマンドでできます（再ビルドを繰り返したときなどに便利）
```
docker image prune
```

:::note warn
削除しようとしているイメージがコンテナで使用されている場合は削除できないので注意です。
その時は、以下のコマンドでまずはコンテナを停止しましょう。
```
docker stop 【削除したいコンテナのdocker id】
```
:::

# 【おまけ】DockerHubを使う！
[Docker Hub](https://hub.docker.com/)は、Dockerイメージを公開、共有、配布するためのクラウドベースのレジストリサービスです。

<details><summary>Docker Hubでできること</summary>

1. **イメージのホスティングと配布**
    - Docker Hubは、自分が作成したDockerイメージをアップロード（push）して公開する場所として機能します。また、他のユーザーが作成し公開したイメージをダウンロード（pull）して使うこともできます。

2. **公式イメージ**
    - Docker Hubには多数の公式Dockerイメージが公開されています。これらは各種プログラミング言語やデータベース、その他のサービスを簡単に使用するためのもので、誰でも利用することができます。

3. **自動ビルドと統合**
    - Docker Hubはソースコード管理サービス（例えばGitHub）と統合でき、リポジトリにあるDockerfileの更新をトリガーに自動的にDockerイメージをビルド・更新する機能を提供しています。

4. **プライベートリポジトリ**
    - デフォルトではDockerイメージは公開されますが、プライベートリポジトリを使用すれば特定のユーザーだけがアクセスできるようにすることも可能です。これは商用利用や機密データを含むイメージの管理に有用です。
---
</details>

今回は、Docker Hubに自分が作成したDockerイメージをアップロード（push）して使ってみます。

## Docker Hubのアカウント作成
アカウント作成はDocker Hubの[公式ウェブサイト](https://hub.docker.com/)から行えます。

## ローカルマシンでログイン
ローカルのマシンでDockerを実行し、作成したアカウントでログインします。コマンドラインから次のコマンドを実行します。
```
docker login
```
このコマンドを実行すると、ユーザー名とパスワードを入力するように求められます。

## Dockerイメージにタグを付ける
これは`docker tag`コマンドを使います。タグは<docker-hub-username>/<repository-name>:<tag>の形式で指定します。

```
docker tag <existing-image> <docker-hub-username>/<repository-name>:<tag>
```

## Dockerイメージをアップロードする
これは docker push コマンドを使います。
```
docker push <docker-hub-username>/<repository-name>:<tag>
```

## DockerHubからコンテナを作成する
`docker run`コマンドを使います。まず、イメージ名とタグを正しく指定することが重要です。イメージ名は通常、username/repositoryの形式で、タグはコロン（:）の後に付けます。

例えば、DockerHub上にmyusername/myimage:1.0というイメージがあると仮定しましょう。これをローカルマシン上で実行するには次のコマンドを実行します。

```
docker run -d myusername/myimage:1.0
```

これで違う環境からでも、自分の作ったDockerイメージを使ってコンテナを作成することができます！！
出先用ノートPCでも勉強できる...


# 最後に
今後学んだことや、気がついたことは追記していく予定です。
もし間違っていることや、こうしたほうがいいよ！ということろがあればコメントもらえるとうれしいです！