Docker コンテナ内で動作する Web サーバにホスト OS からアクセスするには : ポートフォワーディング

Docker 基礎。

外部から Docker コンテナ内にアクセスするには、ポートフォワードの設定が必要になる。原理はシンプルなので、順を追って説明する。

目次

そもそもポートフォワーディングとは

そもそもポートフォワーディングとは何か。これはネットワーク用語の一つで、あるポート宛に届いた通信 (パケット) を、予め設定していた別の機器に転送する機能のこと。

Docker の場合は、コンテナ内の環境はデフォルトでは閉じられており、ホスト OS や外部の PC からはアクセスできない状態にある。

そこで、ホスト OS のあるポートから、Docker コンテナ内で開いているポートに向けて、通信を転送してやるための設定が必要になるワケだ。

Docker コンテナ内に置く Web サーバの設定

それでは、Docker 内部からホスト OS に向けて、順に話を広げて説明しよう。

まずは、Docker コンテナ内で稼動させる Web サーバの設定だ。

例えば Node.js Express サーバを使っていたとして、8080 ポートを使う設定にしていたとする。

const express = require('express');
const app = express();

const port = 8080;
app.listen(port, () => {
  console.log('Server Started');
});

ローカル開発環境で npm start してこのサーバを起動した時は、curl http://localhost:8080/ でアクセスできるのは分かるだろう。

次に、Dockerfile を書いて、Docker コンテナにこの資材を置いた場合。

  1. 1つのターミナルで、docker run でコンテナを起動し、Express サーバを起動させておく。
  2. 別のターミナルで、同じコンテナのシェルにログインしてみる。docker exec -it 【コンテナ ID】bash といった具合だ。
  3. ログインしたシェル内で、curl http://localhost:8080/ と叩けばアクセスできる。

コレは、ローカル開発環境で試していたことを、Docker コンテナ内でやっているだけ。

しかし、ホスト OS から curl http://localhost:8080/ と叩いても、反応は得られない。この、ホスト OS と Docker コンテナ間を「ポートフォワード」してやる必要がある。

Docker コンテナの特定ポートを開放するには : EXPOSE 命令

Docker コンテナの特定のポートを開放するには、Dockerfile を書く時に EXPOSE 命令というモノを書いてやる必要がある。

# Dockerfile に以下のように書くと、Docker コンテナの 8080 ポートを公開できる
EXPOSE 8080

ホスト OS からポートフォワードする

EXPOSE 命令を書いて Docker イメージをビルドして、それを単に docker run しただけでは、ホスト OS から接続できない。docker run する際に -p (--publish) オプションを指定する必要がある。

# Docker コンテナ側は 8080 ポートを公開している
# ココに対して、ホスト OS の 3000 ポートを紐付ける場合
$ docker run -p 3000:8080 【Docker イメージ名】

-p オプションの後ろは 【ホスト OS のポート】:【Docker コンテナが公開しているポート】 と書いて、ホスト OS のポートを紐付けてやる。

このようにすると、ホスト OS からは http://localhost:3000/ でアクセスできるようになる。コレがポートフォワーディングだ。

当然、以下のようにホスト OS で同じポートを使用してやれば、

$ docker run -p 8080:8080 【Docker イメージ名】

ホスト OS からも http://localhost:8080/ でアクセスできるようになる。