【Docker】コンテナと他のPCとのPing通信を実現する方法

## はじめに

Dockerはコンテナ仮想化技術として非常に便利ですが、Dockerコンテナは通常、ホストOSとは独立したネットワーク環境に閉じ込められています。そのため、Dockerコンテナが外部ネットワークや他のPCと通信できるようにするためには、ネットワーク設定を適切に行う必要があります。

本記事では、Dockerコンテナと他のPCとの間でPing通信を行うための主要な方法を紹介し、それぞれのメリット・デメリットを比較します。その後、最も適切な方法を選んで、実際にUbuntuコンテナを立ち上げ、他のPCとPing通信を行うサンプルを解説します。

---

## Dockerのネットワーク設定

Dockerコンテナは、デフォルトでは `bridge` モードという仮想ネットワークを使用します。このモードでは、コンテナは独立したIPアドレスを持ち、ホストOSや外部ネットワークとは隔離されています。外部と通信するためには、ポート転送やネットワーク設定を変更する必要があります。

Dockerでは、以下のようなネットワークモードがあります：

1. **bridge（デフォルト）**
   - コンテナとホストが異なるIPネットワークにあり、コンテナ間は通信できるが、外部ネットワークと直接通信するにはポート転送が必要。
   
2. **host**
   - コンテナがホストOSのネットワークスタックをそのまま利用する。ホストと同じIPアドレスを共有するため、ネットワークの設定がシンプルになります。
   
3. **none**
   - コンテナはネットワーク接続を持たない。完全にネットワークから隔離された状態です。

4. **custom bridge network**
   - ユーザーが独自にネットワークを定義し、複数のコンテナ間で通信可能にすることができます。

---

## 主要な方法の比較

Dockerコンテナと他のPCとのPing通信を行うための主要な方法を以下の表で比較します。

| 方法                          | メリット                                                       | デメリット                                                     | 使用シーン                                                      |
|-------------------------------|---------------------------------------------------------------|---------------------------------------------------------------|---------------------------------------------------------------|
| **ホストネットワークモード (`--network host`)** | - コンテナがホストと同じネットワークを使うため、設定が簡単。<br>- 外部PCとの通信も簡単。  | - ホストのネットワーク設定に依存し、コンテナの独立性が失われる。<br>- セキュリティリスクが高くなる。 | - ホストとコンテナが同じネットワークにある必要がある場合。<br>- 高速な通信が必要な場合。 |
| **ポート転送 (`-p`)**          | - 複雑なネットワーク設定なしで簡単に外部と通信可能。<br>- 必要なポートだけを公開できる。 | - 公開したポートだけが通信可能。<br>- 複数のサービスが必要な場合に管理が面倒。 | - 外部アクセスが特定のサービスに限られる場合。<br>- ホストのIPをそのまま使いたい場合。 |
| **カスタムブリッジネットワーク** | - コンテナ同士の通信が簡単。<br>- ネットワークの管理が柔軟。       | - 外部との通信設定に追加の作業が必要。<br>- ポート転送と合わせて使う必要がある。 | - 複数コンテナ間で通信が必要な場合。<br>- 低レベルなネットワーク管理が必要な場合。 |
| **none モード**                | - 完全に隔離されたネットワーク環境。<br>- セキュリティが最強。   | - 外部との通信が一切できない。<br>- 通常は必要ない。          | - セキュリティを最優先したい場合。<br>- 通信が不要な場合。 |

最も簡単で汎用的な方法としては、**ホストネットワークモード (`--network host`)** が挙げられます。これを使うと、コンテナはホストOSのネットワークスタックを直接使用するため、他のPCとのPing通信がシンプルに実現できます。ただし、セキュリティに関して注意が必要です。

---

## チュートリアル

ここでは、`--network host` を使ってUbuntuコンテナを立ち上げ、他のPCとPing通信を行う方法を実際に試してみます。さらに、`docker-compose` を使った方法も紹介します。

### 事前準備

まず、ネットワーク周りのコマンドをコンテナ起動時にインストールするため、`Dockerfile`を作成しておきます。

```dockerfile
# M1 MacのみFROMの記述が必要
FROM --platform=linux/amd64 ubuntu:latest

# RUNコマンドは、コンテナ作成時に自動で実行するコマンドを指定
RUN apt update -y
RUN apt install -y sudo make curl vim iperf3 iproute2 iputils-ping

# fogeというユーザを作成、fogefogeというPWを設定
RUN useradd -m -s /bin/bash foge
RUN echo "foge:fogefoge" | chpasswd

# sudoでroot権限のコマンドを実行できるように指定
RUN gpasswd -a foge sudo

# コンテナを指定したユーザで実行（rootユーザ以外で実行したい）
USER foge

# ワークディレクトリを設定
WORKDIR /home/foge
```
次に、イメージを作成するためにbuildします。Dockerfileを置いたディレクトリに移動して、以下のコマンドを実行します。

```bash
docker build . -t ubuntu_image
```

イメージができていることを確認します。

```bash
docker images
```

### Chapter 1.   `--network host` を使ってPing通信を行う

#### 1. **Ubuntuコンテナをホストネットワークモードで起動する**

以下のコマンドを使って、UbuntuのDockerコンテナを起動します。`ubuntu_image` イメージを使ってコンテナを起動し、ホストOSのネットワークモードを使用します。

```bash
docker run -it -d --network host --name test-ubuntu ubuntu_image
```
起動したDockerコンテナに入ります。

```bash
docker exec -it test-ubuntu bash
```

#### 3. **コンテナ内でPingを実行する**

コンテナが起動したら、コンテナ内で以下のコマンドを使って他のPCにPingを送信します。

```bash
ping <他のPCのIPアドレス>
```

例えば、他のPCのIPが `192.168.1.100` の場合：

```bash
ping 192.168.1.100
```

これで、他のPCとPing通信が成功するはずです。

---

### Chapter 2.   `docker-compose` を使ってPing通信を行う

`docker-compose` を使うと、複数のコンテナやネットワーク設定を一元管理することができます。以下では、`docker-compose` を使用して、コンテナをホストネットワークモードで起動し、他のPCとのPing通信を実現します。

#### 1. **`docker-compose.yml` の作成**

   まず、以下の内容で `docker-compose.yml` ファイルを作成します。ここでは、Ubuntuベースのコンテナをホストネットワークモードで起動します。

   ```yaml
   version: '3.8'

   services:
     ubuntu-ping:
       image: ubuntu:20.04
       container_name: ubuntu-ping
       network_mode: host   # ホストのネットワークを使う
       tty: true            # コンテナ内でインタラクティブに作業できるようにする
       command: bash
       stdin_open: true
       restart: always
   ```

#### 2. **`docker-compose` でコンテナを起動**

上記の `docker-compose.yml` が同じディレクトリに保存されていることを確認したら、以下のコマンドを実行してコンテナを立ち上げます。

```bash
docker-compose up
```

コンテナが起動したら、コンテナ内でPingを実行します。

#### 3. **コンテナ内でPingを実行**

`docker-compose up` で起動したコンテナに接続し、Pingを実行します。

```bash
docker exec -it ubuntu-ping bash
ping <他のPCのIPアドレス>
```

他のPCのIPアドレス（例えば `192.168.1.100`）に対してPingが成功するはずです。

---

## おわりに

Dockerコンテナと他のPCとのPing通信を行う方法を紹介しました。最も簡単で汎用的な方法は、`--network host` オプションを使うことで、コンテナがホストのネットワークスタックをそのまま利用することです。ただし、セキュリティに関して注意が必要です。

また、`docker-compose` を使うことで、複数のコンテナを簡単に管理し、ネットワーク設定を一元化することができます。この知識を活用して、Dockerコンテナを使ったネットワーク通信の理解を深めてください。