Dockerはじめてガイド：Mac/Windows/Ubuntu対応 初心者向けセットアップ＆基本操作まとめ

# 🚀 はじめに

この記事では，これからDockerを使って開発を始めたい方向けに，

- OS別インストール方法（Mac，Windows，Ubuntu対応）
- Dockerfileやdocker-composeの記述方法
- 画像・コンテナ操作の基本と応用
- コンテナ開発環境の整備（VS Code連携）
- Docker Hubでの公開・共有方法

などを**一気通貫で解説**します．  
最初はこれを覚えておけば問題ないです．

# 🧭 目次

## 初級編
1. 🛠 Dockerのインストール & 初期設定
2. 🧾 Dockerfile / .dockerignore / docker-compose.yml の書き方
3. 📦 イメージの基本操作
4. 🚢 コンテナの基本操作
5. 🧑‍💻 VS Codeでのコンテナ開発

## 応用編
6. 🏷 イメージのタグ操作と保存・読み込み
7. ☁️ Docker Hubへのアップロードと管理

# 🛠 1. Dockerのインストール & 初期設定

## 🍎 Mac
- [Docker Desktop for Mac](https://www.docker.com/products/docker-desktop/) をダウンロード＆インストール

## 🪟 Windows
- WSL2の有効化 & Docker Desktopインストール  
  公式ガイド: [Windowsでのセットアップ](https://docs.docker.com/desktop/install/windows-install/)

## 🐧 Ubuntu
```bash
sudo apt update
sudo apt install docker.io -y
sudo systemctl enable --now docker
```

ユーザを`docker`グループに追加（sudo不要化）:
```bash
sudo usermod -aG docker $USER
newgrp docker
```

Docker起動確認：
```bash
docker --version
docker run hello-world
```

docker-composeのインストール：
```bash
sudo curl -L "https://github.com/docker/compose/releases/download/v2.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
```

# 🧾 2. Dockerfile / .dockerignore / docker-compose.yml の書き方

## 🔨 Dockerfileの基本構成
以下にDockerfileでよく使うコマンド一覧を示し，最後に実際のDockerfile例を示します．  
最初は軽く読み流す程度で良いです．

### FROM：ベースイメージの指定（必須）
DockerFileの一番最初に1行だけ記述  
例：
```Dockerfile
FROM ubuntu:22.04
FROM python:3.11-slim
FROM node:18-alpine
```

- [Docker Hub](https://hub.docker.com/) で公式やverifiedイメージを検索
    - 開発用途に応じて適切なベースを選ぶ

#### 📌 代表的なベースイメージの使い分け例：
- `ubuntu`：汎用的なLinux環境．何をするか未定でとりあえず環境を整えたいときに便利
- `python`：Pythonの実行環境を簡単に整えたいとき．`-slim`は不要なツールを省いた軽量バージョン
    - 他にも`python:3.11`, `python:3.11-alpine`, `python:3.11-bullseye`などがある
- `node`：Node.jsベースでWeb開発を行いたい場合に．`-alpine`は非常に軽量で本番環境向けにもよく使われる

### RUN：ビルド時のコマンド実行
`RUN` は Docker イメージのビルド中に一度だけ実行されるシェルコマンドです．パッケージのインストールやファイル操作など，環境構築に必要な処理を記述します．

#### ✅ よくある使い方（基本）

```Dockerfile
RUN apt update
RUN apt update && apt install -y curl git
RUN pip install -r requirements.txt
```

- `&&` でまとめると，**中間レイヤーの数が減って**ビルドが速くなり，キャッシュも効きやすくなります．

#### ✅ 複数行に分けたいとき（可読性のため）

```Dockerfile
RUN apt update && \
    apt install -y \
    curl \
    git \
    unzip
```

- `\`（バックスラッシュ）と改行を使って，**見やすく整形**できます．
- `--no-cache-dir` は一時ファイルを残さないオプション（コンテナサイズ削減に有効）

### COPY：ローカルファイルのコピー
```Dockerfile
COPY . /app
COPY requirements.txt /app/
```

### ADD：COPY＋α（tar展開やURL対応）
```Dockerfile
ADD archive.tar.gz /app/
ADD https://example.com/data.csv /data.csv
```

### WORKDIR：作業ディレクトリ指定
シェルでの`cd`コマンドに相当，カレントディレクトリを変更できる．
```Dockerfile
WORKDIR /app
```

### ENV：環境変数の設定
```Dockerfile
ENV TZ=Asia/Tokyo
ENV NODE_ENV=production
```

### EXPOSE：使用予定ポートの宣言
```Dockerfile
EXPOSE 3000
```

### VOLUME：永続化ポイント
コンテナ内の指定したパスを，ローカルのどこかにマウントして，コンテナが削除された後も残るようにできる．  
後述する`docker-compose.yml`にも同様に`volumes:`の設定が可能で，そちらにマウント先を明示的に書いた場合は`compose`側が優先されます．  
そのため，`Dockerfile`で `VOLUME`を書かなくても問題ないケースがほとんどです．  
例：
```Dockerfile
VOLUME /var/lib/mysql
```

### CMD：コンテナ起動時コマンド
コンテナが起動されたときにデフォルトで実行されるコマンドを指定します．  
通常は`Dockerfile`の最後に1行だけ記述します（複数指定しても最後のものだけが有効です）．
```Dockerfile
CMD ["node", "app.js"]
CMD ["python3", "main.py"]
```

### ENTRYPOINT：`CMD`より強制力ある起動処理
コンテナ起動時に常に実行されるコマンドを固定する命令です．  
`CMD`と同様，`Dockerfile`に複数書いても最後の1つだけが有効になります．
```Dockerfile
ENTRYPOINT ["python3", "main.py"]
```

#### 🆚 `CMD`との違い

`CMD` は「**何も指定がなければこれを実行してね**」という**デフォルトの起動コマンド**を定義します．  
一方で `ENTRYPOINT` は「**必ずこれを実行する（上書き不可）コマンド**」を定義します．


#### 🧪 実行例

`CMD`の場合：
```Dockerfile
CMD ["echo", "hello"]
```

```bash
docker run myimage           # → echo hello
docker run myimage echo bye       # → echo bye（上書きされる）
```

---

`ENTRYPOINT`の場合：
```Dockerfile
ENTRYPOINT ["python3", "app.py"]
```

```bash
docker run myimage           # → python3 app.py
docker run myimage bye       # → echpython3o app.py bye（後ろに追加される）
```

---

`CMD`と`ENTRYPOINT`の組み合わせ（最も実用的）：
```Dockerfile
ENTRYPOINT ["echo"]
CMD ["hello"]
```

```bash
docker run myimage           # → echo hello
docker run myimage bye       # → echo bye
```

#### ✅ 結論

- `CMD`：**柔軟性重視**．ユーザーが自由に上書きしたいとき向き
- `ENTRYPOINT`：**固定実行重視**．CLIなどで処理を必ず実行したいときに最適
- **最もよく使われるのは `ENTRYPOINT` + `CMD` の組み合わせ**．


### ⏰ タイムゾーン設定例（Ubuntu）
```Dockerfile
ENV TZ=Asia/Tokyo
RUN apt update && \
    DEBIAN_FRONTEND=noninteractive apt install -y tzdata && \
    ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && \
    dpkg-reconfigure -f noninteractive tzdata
```

### 💡 実用Dockerfile例：Flask API
```Dockerfile
# Python 3.11 の軽量バージョン（不要なパッケージが削られた）をベースに使用
FROM python:3.11-slim

# タイムゾーンを日本時間（Asia/Tokyo）に設定
ENV TZ=Asia/Tokyo

# 作業ディレクトリを /app に設定（以降のCOPYやRUNの基準パスになる）
WORKDIR /app

# 依存関係ファイルだけを先にコピー（Dockerのレイヤーキャッシュを活用するため）
COPY requirements.txt .

# Pythonパッケージを一括インストール（キャッシュを残さずコンテナを軽く保つ）
RUN pip install --no-cache-dir -r requirements.txt

# プロジェクトの全ファイルをコンテナにコピー（例: app.py, templates/, static/ など）
COPY . .

# Flaskのデフォルトポート（5000番）を外部公開（任意）
EXPOSE 5000

# エントリポイントを flask に固定（CMDはその引数として渡る）
ENTRYPOINT ["flask"]

# デフォルト引数を設定（上書き可）
CMD ["run", "--host=0.0.0.0", "--port=5000"]
```

## 🙈 .dockerignore：ビルド時に無視するファイルを指定する設定ファイル

`.dockerignore` は，`Dockerfile`と同じディレクトリに置き，コンテナのビルド時に **イメージに含めたくないファイル・ディレクトリを除外**するための設定ファイルです．  
これは `.gitignore` に似ていますが，Dockerにおいては **イメージのサイズ・セキュリティ・ビルド速度**に大きく影響します．

### ✅ なぜ重要？

- **不要なファイル**（ログ・一時ファイル）がイメージに含まれない
- **秘密情報**（`.env`, `credentials.json` など）をうっかり含めないようにできる
- **ビルドが高速化**する（送信対象のビルドコンテキストが軽くなる）



### 📝 基本的な書き方の例

```dockerignore
# Pythonキャッシュや中間ファイル
__pycache__/
*.py[cod]

# 環境ファイル（秘密情報）
.env
credentials.json

# ビルド・仮想環境
dist/
build/
venv/

# Git関連
.git
.gitignore

# エディタやOSの一時ファイル
.vscode/
.idea/
.DS_Store
*.swp
```

### ⚠️ `.env` や `.git` を除外する理由

- `.env` や `credentials.json` は，APIキーやトークンが入っていることが多く，**Dockerイメージに焼き付くと非常に危険です**．
    - イメージファイルを他人に配布しない，かつローカルで自分しか使わないのであればコンテナに入れても問題ないです．
    - 後述する`docker-compose.yml`を使えば環境変数も使えるため，原則コピーしないようにしてください．
- `.git` は大量の不要ファイルを含み，**イメージ肥大化とビルド遅延の原因**になります．
    - それでも必要であれば，`Dockerfile`に`git init`等の`.git`情報を再構成する処理を入れる設計にすることで，安全に最小限のGit情報だけを扱うことが可能です．

### ✅ まとめ

| 対象ファイル     | `.dockerignore` に含めるべき？ | 理由                                               |
|------------------|-------------------------------|----------------------------------------------------|
| `.env`           | ✅ 原則含める                   | 認証情報が含まれるため危険．実行時に渡すべき．     |
| `.git/`          | ✅ 原則含める                   | サイズ肥大・ビルド遅延防止．       |
| `.vscode/`, `.DS_Store` | ✅ 含める               | エディタ・OS依存の不要ファイル                    |

`.dockerignore` はセキュリティ・効率・安定性を保つために極めて重要な設計要素です．  
「入れる・入れない」は**運用設計に基づいて明確に判断しましょう**．

## 🧩 docker-compose.yml の構成と役割

`docker-compose.yml`は，複数の Docker コンテナ（サービス）をまとめて構築・起動・管理するための設定ファイルです．通常の`docker run`では1つずつ手動で起動しますが，Compose を使えばネットワークやボリューム，依存関係まで含めて一括管理できます．

### 🔍 主な構成要素

| キー           | 説明                                                                 |
|----------------|----------------------------------------------------------------------|
| `version`      | Composeファイルのバージョン（一般的に `3.8` 以上を推奨）            |
| `services`     | 起動するコンテナ群の定義                                             |
| `image`        | 使用するDockerイメージを指定                   |
| `container_name` | ビルド後のコンテナ名を指定
| `build`        | ローカルのDockerfileのパスを指定                       |
| `ports`        | ホストとコンテナのポートマッピング                                  |
| `volumes`      | コンテナの永続化またはコード同期設定                                 |
| `environment`  | 環境変数の設定（`.env` ファイルとも連携可能）                        |
| `networks`     | 複数コンテナ間でネットワークを管理                  |
| `depends_on`   | 起動順の制御                                                         |
| `tty`          | teletypewriter略，コンソールを使えるようにする       |

#### 🧩 `version`
```yaml
version: '3.8'
```
- Composeファイルの仕様バージョン
- `3.8` 以上が推奨．最新の機能が使用可能

#### 🧩 `services`
```yaml
services:
  frontend:
    ...
```
- 起動するアプリケーションごとのコンテナ定義ブロック
- それぞれに `build`, `ports`, `volumes` などを記述

#### 🧩 `image`
```yaml
image: client-image
```
- 使用するDockerイメージを指定．次の2種類の使い方がある
  - `docker pull` したイメージファイル名の指定
  - ローカルのDockerfileをビルドしたときのイメージファイル名の指定

#### 🧩 `container_name`
```yaml
container_name: client
```
- ビルド時のコンテナ名を明示的に指定
- CLI操作時やログの識別に便利

#### 🧩 `build`
```yaml
build:
  context: ./client
  dockerfile: Dockerfile
```
- Dockerfileのパスとビルド対象ディレクトリを指定

#### 🧩 `ports`
```yaml
ports:
  - "5001:5173"
```
- ホスト⇔コンテナ間のポート転送
- `"ホストポート:コンテナポート"` の形式

#### 🧩 `volumes`
```yaml
volumes:
  - ./client:/app
  - /app/node_modules
```
- ホストとコンテナ間のファイル同期または永続化
- `node_modules` などはホストに影響させないための無視ボリュームとしても使える

#### 🧩 `environment`
```yaml
environment:
  - FLASK_ENV=development
  - API_KEY=${API_KEY}
```
- コンテナ内に渡す環境変数
- `.env` ファイルから自動展開可能

#### 🧩 `networks`
```yaml
networks:
  - web-app-network
```
- 複数のコンテナを同一ネットワークに配置して通信を可能にする
- 名前解決（例：`http://backend:3000`）ができるようになる

#### 🧩 `depends_on`
```yaml
depends_on:
  - backend
```
- 起動順制御（例：backendを先に起動）
- コンテナの"準備完了"は保証されない点に注意

#### 🧩 `tty`
```yaml
tty: true
```
- 仮想端末（TTY）を割り当てる
- ログ表示の整形や対話的CLI操作で有効

### ✅ 基本構成の例

```yaml
# Composeファイルのバージョン指定（3.8は安定して使いやすい）
version: '3.8'

services:
  # フロントエンドサービスの定義
  frontend:
    image: client-image  # ビルド後のイメージ名として使用
    container_name: client  # 実行中のコンテナに付ける名前
    build:
      context: ./client       # Dockerfile のあるディレクトリを指定
      dockerfile: Dockerfile  # 使用するDockerfile名（省略可能だが明示している）
    ports:
      - "5001:5173"           # ホスト5001 → コンテナ5173
    volumes:
      - ./client:/app         # クライアントソースをコンテナにマウント（ホットリロード対応）
      - /app/node_modules     # node_modules をホスト側と分離（競合防止）
    networks:
      - web-app-network       # backendと同じネットワークで通信可能にする
    depends_on:
      - backend               # backendを先に起動してからfrontendを起動
    tty: true                 # 仮想端末を割り当て（ログ整形やbashでの操作用）

  # バックエンドサービスの定義
  backend:
    image: server-image
    container_name: server
    build:
      context: ./server
      dockerfile: Dockerfile
    ports:
      - "3001:3000"
    volumes:
      - ./server:/server
    networks:
      - web-app-network
    tty: true

# コンテナ間通信のための共通ネットワークを定義
networks:
  web-app-network:
    driver: bridge            # Docker標準のブリッジネットワークドライバ
```

# 📦 3. イメージの基本操作

## 🔧 単体の `Dockerfile` を使う場合（手動ビルド）

- **Dockerfile からイメージをビルドして使うケース**
- 自分で `docker build` を使ってイメージを作成する．

```bash
# ✅ 例：Dockerfileがあるディレクトリで
docker build -t myimage:latest .
```

- `myimage:latest` という名前でイメージが作成される

### ⚠️ docker-compose使用時

> **docker-composeを使う場合，通常は `docker build` は不要**

- `docker-compose.yml` に `build:` セクションがある場合は，コンテナのビルド時に**イメージの作成と起動がまとめて行われる**ため，**個別に `docker build` する必要はありません**．

## 🔁 イメージプル（公開済みのイメージを使う場合）

```bash
docker pull ubuntu:22.04  # ✅ 例：Docker Hub から ubuntu イメージを取得
```

- これは公式イメージなどを使う例
  - ローカルにない場合は自動でpullされるのでやらなくても良い

## 🧾 イメージの確認と削除

```bash
docker images         # ✅ ローカルにあるイメージを一覧表示
docker rmi myimage    # ✅ 特定のイメージを削除
```

- `rmi` は "remove image" の略
- イメージ名 or イメージID　を指定して削除
- 不要になったイメージや中間イメージを削除することで容量節約

# 🚢 4. コンテナの基本操作

## 🔧 単体の `docker` コマンドを使ってコンテナビルドする場合

- コンテナ生成＆起動（初回や更新時）：
  ```bash
  docker run {イメージ名}
  ```

## `docker run`のオプション

| オプション      | 用途例                                   | 備考                              |
|------------------|--------------------------------------------|-----------------------------------|
| `-d`             | Webサーバー，バックエンドAPIなど         | バックグラウンドで常駐実行       |
| `-d`なし         | デバッグ・実行中ログを見たい場合         | フォアグラウンド実行              |
| `--rm`           | テストスクリプト，バッチ処理など         | 終了と同時に自動削除される       |
| `-it`            | `bash` などの対話シェルを起動したい場合   | 対話操作が可能になる             |
| `--name`         | 固定名で操作しやすくする                  | `docker exec`, `logs` などに便利 |
| `-v`             | ローカルのコードやデータを反映させたいとき| 開発中にホットリロードが便利     |
| `-p`             | ブラウザからアクセスしたいWebアプリ       | ポートを忘れるとアクセスできない |
| `--gpus`  | CUDA等でGPUをコンテナに使わせたいとき         | 特になし |

---

### `-d`：バックグラウンド（デタッチ）モード
- **意味**：コンテナをバックグラウンドで起動する（ログが端末に出力されない）
- **用途**：WebサーバーやAPIなど，常駐サービスを動かしたいとき
- **確認方法**：`docker ps` で起動中のコンテナを確認

```bash
docker run -d myimage
```

#### 👇 使うべきとき
- 開発中に常駐サーバーを立てる
- ログはあとから `docker logs` で見る

#### ❌ 使わないとき（-d なし）
- フォアグラウンドで動くので，**ログをリアルタイムで見たいときや対話操作したいときに便利**
- `CTRL+C` で終了できる

---

### `--rm`：コンテナ自動削除
- **意味**：コンテナが終了したら自動的に削除される
- **用途**：一時的なテストやデータの不要なワンショット処理

```bash
docker run --rm myimage
```

#### 📌 特徴
- `docker ps -a` でコンテナが残らない
- 一時的な用途には便利だが，ログやデータが必要な場合は注意

---

### `-it`：対話モード＋仮想端末
- `-i`（interactive）：標準入力を開いたままにする
- `-t`（tty）：仮想端末を割り当てる（見やすい出力になる）
- **用途**：コンテナの中に入って操作したいとき（bashやshなど）

```bash
docker run -it myimage
```

---

### `--name`：コンテナに名前を付ける
- **意味**：自分で指定した名前で扱える．これをつけなかった場合ランダムなコンテナ名になる．
- **利点**：`docker exec` や `docker logs` の対象として名前指定しやすい

```bash
docker run --name mycontainer myimage
```

---

### `-v`：ボリュームマウント（ファイル共有）
- **意味**：ホストのディレクトリとコンテナ内をリンク
- **用途**：開発中のコードをリアルタイムで反映させたいとき

```bash
docker run -v $(pwd):/app myimage
```

---

### `-p`：ポートマッピング
- **形式**：`ホストポート:コンテナポート`
- **用途**：ローカルPCからブラウザ経由でコンテナ内サービスにアクセスする場合

```bash
docker run -p 8080:80 myimage
```

---

### `--gpus`：ホストのGPUをコンテナで利用する
- **意味**：NVIDIA GPU をコンテナに割り当てるオプション
    - **指定方法**：`---gpus all`: すべてのGPUを使う，`--gpus '"device=0"'`: GPU 0番を使う，`--gpus 1`: 任意の一つのGPUを割り当てる
- **用途**：CUDAベースのAI処理や機械学習ライブラリ（PyTorch, TensorFlow等）を使用する際に必須

```bash
docker run --gpus all myimage
```

---

### 実際のオプションの使用例：
```bash
docker run --rm -it --name mycontainer myimage
```

## 📋 コンテナ一覧の確認

- "-a" オプションを付けると停止中のコンテナも表示
- "ps" と "container ls" は同じ意味（表現違い）

```bash
docker ps
docker ps -a
docker container ls
docker container ls -a
```

## 🔁 コンテナの起動・停止・再起動・削除
- `start`：2回目以降のコンテナ起動時などに使用
```bash
docker start mycontainer
docker stop mycontainer
docker restart mycontainer
docker rm mycontainer
```

## 🖥️ コンテナに接続する（中に入る）

```bash
docker exec -it mycontainer bash
```

- `bash` の代わりに `sh` や `zsh` も可（Alpineなら `sh`）

## 🔧 コンテナの名前を変更する

```bash
docker rename oldname newname
```

## 🔄 ファイルのコピー（ホスト⇔コンテナ間）

```bash
docker cp local.txt mycontainer:/app/
docker cp mycontainer:/app/output.txt .
```

## ⚠️ docker-compose使用時の違い・補足

### ✅ 起動・停止・再起動・削除（複数コンテナ対応）

- イメージのビルド＆起動（初回や更新時）：
  ```bash
  docker-compose up --build
  ```

- 起動：
  ```bash
  docker-compose up
  ```

- バックグラウンドで起動：
  ```bash
  docker-compose up -d
  ```

- 停止・再起動：
  ```bash
  docker-compose down
  ```

- 再起動（状態保持）：
  ```bash
  docker-compose restart
  ```

### ✅ コンテナ接続・操作（名前の注意）

- `container_name:` を指定していない場合，自動で `プロジェクト_サービス名_番号` の形式になる
- 例：
  ```bash
  docker exec -it myproject_backend_1 bash
  ```

  または `container_name: my-backend` を指定していれば：

  ```bash
  docker exec -it my-backend bash
  ```

### ✅ ファイル転送も共通

- `docker cp` は compose のコンテナ名でも同じように使える：

```bash
docker cp .env my-backend:/app/.env
```

## ✅ まとめ：docker vs docker-compose

| 操作内容       | docker単体                               | docker-compose使用時              |
|----------------|-------------------------------------------|-----------------------------------|
| 起動           | `docker run`                             | `docker-compose up`              |
| 停止・削除     | `docker stop`, `docker rm`                | `docker-compose down`            |
| 接続           | `docker exec -it コンテナ名 bash`         | 同上（名前の構造に注意）         |
| 再起動         | `docker restart コンテナ名`                | `docker-compose restart`         |
| ファイル転送   | `docker cp`                               | 同上                              |

# 🧑‍💻 5. VS Codeでのコンテナ開発

- 拡張機能「Remote - Containers」インストール
- `.devcontainer` フォルダ作成
- 起動: `F1 → Remote-Containers: Open Folder in Container`

<!-- ## Git/GitHub連携と開発環境構築
VS Codeでのコンテナ開発時に，Gitを使いたい場合
- Dockerfile
  ```Dockerfile
  RUN sudo apt update && \
      sudo apt install git -y && \
      git init && \
      git config --global user.name "あなたのユーザー名" && \
      git config --global user.email "あなたのメールアドレス"
  ``` -->

# 🏷 6. イメージのタグ操作と保存・読み込み

- タグ設定：
  ```bash
  docker tag myimage:latest myimage:v1.0
  ```

- コンテナ → イメージ化：
  ```bash
  docker commit mycontainer myimage:custom
  ```

- イメージ → tarファイル保存：
  ```bash
  docker save -o myimage.tar myimage
  ```

- tarファイル → イメージ読込：
  ```bash
  docker load -i myimage.tar
  ```

# ☁️ 7. Docker Hub連携

- ログイン：
  ```bash
  docker login
  ```

- アップロード：
  ```bash
  docker tag myimage username/myimage
  docker push username/myimage
  ```

- ログアウト：
  ```bash
  docker logout
  ```

# ✅ まとめ

Dockerを用いた開発は，環境構築を自動化し，再現性のある開発を可能にします．  
まずは初級編の操作に慣れ，必要に応じて応用編の内容に進んでいきましょう．