Docker-DevContainerチートシート


## 概要

Docker でイメージを取得・ビルドし、コンテナを効率良く運用するまでの基本操作をまとめました。併せて **DevContainer** を使った VS Code 連携のポイントも載せています。「環境構築で毎回ググるのは面倒」という方は備忘録にどうぞ。

# 目次

1. [イメージを作成 / 取得](#1-イメージを作成--取得)
2. [コンテナを起動](#2-コンテナを起動)
3. [コンテナを使用](#3-コンテナを使用)
4. [ライブラリの追加インストール](#4-ライブラリの追加インストール)
5. [Docker Compose で複数コンテナを連携](#5-docker-compose-で複数コンテナを連携)
6. [開発ワークフロー](#6-開発ワークフロー)
7. [コンテナの削除](#7-コンテナの削除)
8. [イメージの削除](#8-イメージの削除)
9. [フェーズごとのアクセス範囲](#9-フェーズごとのアクセス範囲)
10. [なぜ Ubuntu イメージ？](#10-なぜ-ubuntu-イメージ？)
11. [Dockerfile と devcontainer.json の違い](#11-dockerfile-と-devcontainerjson-の違い)
12. [remoteUser:"vscode" とは](#12-remoteuservscode-とは)
13. [DevContainer の定義](#13-devcontainer-の定義)

---

## 1. イメージを作成 / 取得 / コンテナの起動

Docker の「イメージ」とは、アプリケーションを動かすために必要な環境一式（OS、ライブラリ、設定など）をパッケージ化したものです。料理で例えると「レシピ」のようなもので、このレシピを元に実際の「料理（コンテナ）」を作ります。

### 1-1. DockerHub からイメージを Pull（Dockerfile 不使用）

**使うケース**

- 公式または信頼できるイメージがすでに存在する
- 学習・検証・一時利用など

```bash
# Anaconda ベースの最新イメージを取得
$ docker pull continuumio/anaconda3

# コンテナを起動して使う（-it: 対話式, --rm: 終了時に削除）
$ docker run -it --rm continuumio/anaconda3 /bin/bash
```

**Tips**

- `docker pull` でイメージをダウンロードしますが、実は `docker run` で自動的にダウンロードもされるので、すぐに使いたい場合は `docker run` だけでも OK です
- `-it` は「インタラクティブ＋ターミナル」の略で、コンテナ内でコマンドを実行できるようになります
- `--rm` をつけると、コンテナを停止した時に自動的に削除されるので、お試し用途には便利です

今回はお試しで DockerHub から Anaconda イメージを持ってきます。

- tag 省略＝ latest。
- latest は毎回中身が変わるので、チーム共有なら バージョンタグを固定。
- docker pull のあとは そのまま run で使える

**注意**  
`latest` タグは「最新版」を意味しますが、時期によって内容が変わってしまいます。チーム開発では `continuumio/anaconda3:2023.09` のように具体的なバージョンを指定することをお勧めします。

### 1-2. Dockerfile を使ってビルド（カスタム環境）

**使うケース**

- 必要なソフトウェアや設定を追加したい
- 環境のカスタマイズが必要（例：パッケージの追加）
- チームで同じ環境を再現したい（Infrastructure as Code）

例：Anaconda ベースに vim を追加したい

```dockerfile
# ベースイメージとしてAnacondaを指定
FROM continuumio/anaconda3

# 必要なパッケージの追加
RUN apt-get update && apt-get install -y vim

# 作業ディレクトリの指定（任意）
WORKDIR /workspace
```

```bash
# イメージをビルド（-t: イメージ名）
$ docker build -t my-anaconda .

# ビルドしたイメージでコンテナを起動
$ docker run -it --rm my-anaconda
```

**Tips**

- Dockerfile は「どんな環境を作るか」の設計図です
- `RUN` 命令は、イメージを作る時に 1 回だけ実行されます
- `&&` でコマンドを繋ぐと、1 つのレイヤーで済むため効率的です
- `.` は「現在のディレクトリ」を意味し、Dockerfile がある場所を指します

## 2. コンテナを起動

初回は _docker run_ でイメージからコンテナを生成・起動します。

```bash
$ docker run -p <ホストポート>:<コンテナポート> \
           -v <ホストDIR>:<コンテナDIR> \
           -it -w <コンテナDIR> \
           --name <コンテナ名> <イメージ名> /bin/bash
```

**オプション説明**

- **-p** : ポートマッピング（例：`-p 8080:80` でホストの 8080 番ポートをコンテナの 80 番に転送）
- **-v** : ボリュームマウント（共有フォルダ）
- **-it**: 対話モード＋ TTY（コンテナ内でコマンドを実行できるように）
- **-w** : 作業ディレクトリを指定（コンテナ起動時にどのフォルダから始めるか）
- **--name** : コンテナに任意の名前を付与（後で管理しやすくなります）

**実用例**

```bash
# Python開発環境の例
$ docker run -p 8888:8888 \
           -v $(pwd):/workspace \
           -it -w /workspace \
           --name my-python-env \
           python:3.9 /bin/bash
```

**Tips**

- 既にホスト側ポート 3000 が占有されていると "address already in use" というエラーが出るので、3001 とかに設定すると良いかと思います。
- 終了は exit ではなく docker stop <コンテナ名> 推奨らしいです。（exit だと bash だけ落ちてプロセス残る）。
- `$(pwd)` は「現在のディレクトリ」を自動で取得するコマンドです（PowerShell では `${PWD}` を使用）

**よくあるエラー**

- `docker: Cannot connect to the Docker daemon` → Docker Desktop が起動していない可能性があります
- `port is already allocated` → 指定したポートが既に使用されています。別のポート番号を試してください
- `no such file or directory` → マウントしようとするホスト側のディレクトリが存在しません

---

## 3. コンテナを再起動

Docker コンテナは一度作って終了しても、もう一度使い回すことができます。以下では、すでに作成したコンテナを「再起動」「中に入って操作」「停止」する方法を紹介します。

```bash
# 停止中コンテナを起動（2回目以降）
$ docker start -ai <コンテナ名>

# 起動中コンテナに接続
$ docker exec -it <コンテナ名> /bin/bash

# コンテナを停止
$ docker stop <コンテナ名>
```

**コマンド説明**

- `start`: 停止中のコンテナを起動。
- `-a`: コンテナの出力（標準出力）をターミナルに表示。
- `-i`: 標準入力を受け付ける（対話モードで操作できる）。
- `exec`: 起動中のコンテナ内で新しいコマンドを実行

**Tips**

- `docker run` は新しいコンテナを最初から作るコマンド。
- `docker start` は既存のコンテナを再起動するコマンドです。
- コンテナの状態は `docker ps -a` で確認できます（`-a` で停止中も含めて表示）

**使い分けのポイント**

- **初回**: `docker run` でコンテナを作成＋起動
- **2 回目以降**: `docker start` で既存のコンテナを再起動
- **別ターミナルから接続**: `docker exec` で起動中コンテナに追加接続

---

## 4. ライブラリの追加インストール

コンテナ内で作業していると、「追加のライブラリも必要」ということがよくあります。ここでは追加インストールの方法を説明します。

### パターン 1 : **DockerHub** のイメージを拡張（簡易）

- `docker-compose.yml` に追加サービスやパッケージを書いておく。

### パターン 2 : **Dockerfile** に追記（本番）

- テストで入れたライブラリが便利なら Dockerfile に `RUN apt-get …` や `RUN pip install …` を追記して再ビルド。
- **ポイント** : 実行中コンテナに手動で `pip install` しても、コンテナを消すと消えるので _ビルド時_ に入れておく。

**実践例**

```dockerfile
# Dockerfile
FROM python:3.9

# 基本的なパッケージをまとめてインストール
RUN apt-get update && apt-get install -y \
    vim \
    git \
    curl \
    && rm -rf /var/lib/apt/lists/*

# Pythonライブラリをインストール
COPY requirements.txt .
RUN pip install -r requirements.txt

WORKDIR /workspace
```

**Tips**

- `requirements.txt` に Python ライブラリをまとめて書いておくと管理が楽です
- `&& rm -rf /var/lib/apt/lists/*` はキャッシュを削除してイメージサイズを小さくするためのおまじないです
- パッケージは関連するもの同士をまとめて 1 つの `RUN` 命令で入れると効率的です

---

## 5. Docker Compose で複数コンテナを連携

実際の開発では、Web アプリケーション + データベース + キャッシュサーバーなど、複数のサービスを連携させることが多い（らしい）です。Docker Compose を使うと、これらを一括で管理できます。

```bash
# docker-compose.yml と同じ階層で
$ docker compose up
```

- 複数サービス (db、app、nginx など) を一括起動＆ネットワーク自動構築。

**実用例**

```yaml
# docker-compose.yml
version: "3.9"
services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/workspace
    depends_on:
      - db
    environment:
      - DATABASE_URL=postgresql://user:password@db:5432/myapp

  db:
    image: postgres:13
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:
```

**Tips**

- `depends_on` でサービスの起動順序を制御できます
- `volumes` を使ってデータベースのデータを永続化できます
- `docker compose down` で全サービスを一括停止できます
- `docker compose logs` で全サービスのログを確認できます

---

## 6. 開発ワークフロー

実際の開発では「どこで何をするか」を明確にしておくと混乱しません。以下の役割分担がおすすめです。

| フェーズ           | やる場所                    | 理由                                                |
| ------------------ | --------------------------- | --------------------------------------------------- |
| **編集**           | ホスト PC (VS Code)         | コンテナ内は vim 程度。GUI エディタ拡張はホストが楽 |
| **実行 / 検証**    | コンテナ                    | 依存が隔離されており、ホストを汚さない              |
| **パッケージ追加** | コンテナ (mamba / npm など) | プロジェクトローカルに閉じ込められる                |

> **マウント必須** : コンテナを削除してもコードが消えないよう `-v` でホスト ディレクトリ を共有。

**ワークフロー例**

1. ホスト PC の VS Code でコードを書く
2. コンテナ内で `python app.py` などを実行してテスト
3. 必要に応じてコンテナ内で `pip install` や `npm install`
4. うまくいったら Dockerfile に反映して環境を固定

**Tips**

- ファイルの編集はホスト側で、実行はコンテナ内で、というのがいいのかなと思います。
- VS Code の Remote-Containers 拡張を使うと、この境界を意識せずに開発できます
- 重要なファイルは必ずボリュームマウントして、コンテナを削除してもデータが残るようにしましょう

---

## 7. コンテナの削除

使わなくなったコンテナは削除してディスク容量を節約しましょう。ただし、削除前に必要なデータがボリュームマウントで保存されているか確認してください。

```bash
# 稼働中確認
$ docker ps
# 停止済みも含め確認
$ docker ps -a
# コンテナ削除
$ docker rm <コンテナ名>
# 強制削除
$ docker rm -f <コンテナ名>
```

**Tips**

- `docker ps` では起動中のコンテナのみ表示されます
- `docker ps -a` で停止中のコンテナも含めて全て表示されます
- 起動中のコンテナは先に `docker stop` で停止してから削除しましょう
- `docker rm -f` は強制削除ですが、データが失われる可能性があるので注意が必要です

**便利コマンド**

```bash
# 停止中のコンテナを一括削除
$ docker container prune

# 使用していないコンテナ、イメージ、ネットワークを一括削除
$ docker system prune
```

---

## 8. イメージの削除

使わなくなったイメージも削除してディスク容量を節約できます。ただし、そのイメージを使用しているコンテナがある場合は、先にコンテナを削除する必要があります。

```bash
# イメージ一覧
$ docker images
# イメージ削除
$ docker rmi <イメージ名>
# 強制削除
$ docker rmi -f <イメージ名>
```

**Tips**

- `docker images` でローカルにあるイメージの一覧を確認できます
- 使用中のイメージは削除できないので、先に関連するコンテナを削除しましょう
- `docker image prune` で使用していないイメージを一括削除できます

**注意点**  
イメージを削除すると、再度必要になった時に DockerHub からダウンロードし直す必要があります。頻繁に使うイメージは残しておいた方が良いかと思います。

---

## 9. フェーズごとのアクセス範囲

Docker では「いつ」「どこに」アクセスできるかが決まっています。これを理解しておくと、ファイルが見つからないエラーを避けられます。

| フェーズ       | アクセスできる範囲           | 外部ファイルにアクセスするには？     |
| -------------- | ---------------------------- | ------------------------------------ |
| `docker build` | **ビルドコンテキスト内のみ** | コンテキストを指定 or ファイルを移動 |
| `docker run`   | **基本はコンテナ内のみ**     | `-v` でホスト DIR をマウント         |

**実例で理解**

```bash
# プロジェクト構造
my-project/
├── Dockerfile
├── src/
│   └── app.py
└── data/
    └── config.json

# ビルド時：my-project ディレクトリ内のファイルにアクセス可能
$ docker build -t myapp .

# 実行時：基本的にコンテナ内のファイルのみ。外部アクセスにはマウントが必要
$ docker run -v $(pwd)/data:/data myapp
```

**Tips**

- ビルド時に必要なファイルは、Dockerfile と同じディレクトリかその配下に置きましょう
- 実行時にホストのファイルにアクセスしたい場合は、必ずボリュームマウント（`-v`）を設定しましょう
- `.dockerignore` ファイルを作ると、ビルド時に不要なファイルを除外できます

---

## 10. なぜ Ubuntu イメージ？

「なぜわざわざ Docker で Ubuntu を使うの？」という疑問をお持ちの方向けに、メリットを整理しました。

| 利点                           | 説明                                         |
| ------------------------------ | -------------------------------------------- |
| **軽量な仮想環境がすぐ使える** | 仮想マシンより高速・低コストで Ubuntu を起動 |
| **環境構築を自動化 & 再現**    | Dockerfile 1 枚で同じ環境を何度でも生成      |
| **安全なテスト**               | ホスト OS を汚さず動作検証・依存確認         |
| **共有しやすい**               | CI/CD やチームで同一ベースを使い回せる       |

**具体的なメリット**

- **クリーン環境**: 実験的なパッケージをインストールしてもホスト OS に影響しません
- **環境リセット**: 環境が壊れても `docker run` で即座に新しい環境を用意できます
- **バージョン管理**: 異なるプロジェクトで異なるバージョンの言語やライブラリを併用できます

**Tips**

- 本格的な開発では Ubuntu よりも alpine（軽量 Linux）を使うことも多い（らしい）です

---

## 11. Dockerfile と devcontainer.json の違い

Docker を使った開発で混乱しやすいのが、これら 2 つのファイルの役割の違いです。簡単に言うと「環境の設計図」と「開発ツールの設定」という違いがあります。

| 項目             | **Dockerfile** (環境の設計図)       | **devcontainer.json** (開発の設定)           |
| ---------------- | ----------------------------------- | -------------------------------------------- |
| 目的             | **OS レベル**の環境構築             | VS Code での **使い方** を定義               |
| 内容             | ベース OS、ライブラリ、環境変数など | どの Dockerfile を使うか、拡張機能、ポート等 |
| イメージとの関係 | イメージそのものをビルド            | そのイメージの **利用方法** を制御           |
| 開発者設定       | 記述しない                          | フォーマッタ、ポート、起動コマンドなど       |
| 共有             | ビルド済みイメージを共有            | `.devcontainer` ごとリポジトリ共有           |

**実例で理解**

```dockerfile
# Dockerfile（環境を作る）
FROM node:16
RUN apt-get update && apt-get install -y git
WORKDIR /workspace
COPY package.json .
RUN npm install
```

```json
// devcontainer.json（VS Codeでの使い方を決める）
{
  "name": "Node.js Dev Container",
  "dockerFile": "Dockerfile",
  "forwardPorts": [3000],
  "extensions": ["ms-vscode.vscode-typescript-next", "esbenp.prettier-vscode"],
  "settings": {
    "editor.formatOnSave": true
  }
}
```

**Tips**

- Dockerfile は「何がインストールされているか」を定義
- devcontainer.json は「VS Code でどう使うか」を定義
- チーム開発では両方をバージョン管理に含めることで、全員が同じ環境・設定で開発できます

---

## 12. remoteUser:"vscode" とは

Linux システムでは「root」（管理者ユーザー）がいますが、開発作業では権限を制限した一般ユーザーを使う方が安全です。

- 多くの Dev Container ベースイメージには **`vscode`** ユーザーが同梱。
- "remoteUser": "vscode" を書くことで、root でなく _一般ユーザー_ として作業。

**なぜ重要か**

- **セキュリティ**: root ユーザーは何でもできてしまいるため、誤操作のリスクが高い
- **ファイル権限**: root で作成したファイルは、ホスト側で編集できない場合がある
- **開発慣行**: 本番環境でも一般ユーザーで動かすのが標準的（らしいです）

```json
// devcontainer.json での指定例
{
  "name": "Python Dev Container",
  "image": "mcr.microsoft.com/vscode/devcontainers/python:3.9",
  "remoteUser": "vscode"
}
```

## 13. DevContainer の定義

DevContainer は、Docker の技術を使って「どこでも同じ開発環境」を簡単に実現する仕組みです。VS Code と組み合わせることで、チーム全員が同じ環境で開発できます。

DevContainer は **Docker + VS Code** で再現性ある開発環境を即座に用意する仕組みです。
最低限そろえるファイルは次の 2 つ。

1. **Dockerfile** : OS やライブラリのインストールを記述
2. **devcontainer.json** : VS Code での拡張・ポート・コマンドを記述

```text
.devcontainer/
├─ Dockerfile        # ベースイメージやRUNコマンド
└─ devcontainer.json # エディタ設定, forwardPorts 等
```

**最小構成の例**

```json
// .devcontainer/devcontainer.json
{
  "name": "My Dev Container",
  "dockerFile": "Dockerfile",
  "workspaceFolder": "/workspace",
  "mounts": ["source=${localWorkspaceFolder},target=/workspace,type=bind"],
  "forwardPorts": [8000],
  "extensions": ["ms-python.python"]
}
```

```dockerfile
# .devcontainer/Dockerfile
FROM python:3.9
RUN apt-get update && apt-get install -y git vim
WORKDIR /workspace
```

**Tips**

- `.devcontainer` フォルダをプロジェクトのルートに作成します
- VS Code で「Reopen in Container」を選ぶだけで環境が立ち上がります
- チームメンバーは `git clone` した後、同じように「Reopen in Container」するだけで同じ環境を利用できます

**DevContainer の威力**

- **環境構築**: 「README 通りにやったけど動かない」がなくなります
- **複数プロジェクト**: 異なるプロジェクトで異なるバージョンの言語/ライブラリを切り替え可能
- **CI/CD との統合**: 開発環境と本番環境の差異を最小化

---

### おわりに

これで Docker コンテナの基本操作から DevContainer 連携までサクッと振り返れます。
環境構築でハマったらぜひ参照してみてください！

### 参考にさせていただいた記事一覧

非常にわかりやすい内容のものばかりで初心者の頃にお世話になりました。ありがとうございます！
https://qiita.com/etaroid/items/b1024c7d200a75b992fc
https://qiita.com/michiru-miyagawa/items/fb41563df9dc98fdf549
https://qiita.com/Sicut_study/items/4f301d000ecee98e78c9

---