Dockerで複数のポートを公開する
1. 概要
アプリケーションをドッキングするときは、通常、1つのポートを公開する必要があります。 アプリケーションはそのポートを使用して、他のコンテナーまたは外部と対話します。 1つのポートでは不十分な場合があります。 他の目的を果たすために、1つ以上の追加のポートが必要になる場合があります。 たとえば、Spring Bootアプリケーションでは、アクチュエータを使用してアプリケーションを監視するための管理エンドポイントを公開するための個別のポートが必要です。
この記事では、公開する複数のポートを宣言する方法と、上記を実現するために公開されたポートをホストコンピューターのポートにバインドする方法について説明します。
2. ポートの宣言
最初に、公開するポートを宣言する必要があります。Dockerイメージの構築中にこれを行うことができます。 イメージに基づいてコンテナを実行しているときにポートを宣言することもできます。 それをどのように行うか見てみましょう。
サンプルのSpring Bootアプリケーションの例– my-appから始めます。 記事全体を通して、同じ例を使用して概念を理解します。 このアプリケーションには、「Hellobuddy」を返すGETエンドポイントが1つだけあります。 また、Springアクチュエータが有効になっています。 アプリケーションはポート8080で実行され、管理エンドポイントはポート8081で実行されます。 したがって、アプリケーションがローカルコンピューターで実行されている場合、次のコマンドが機能します。
$ curl http://localhost:8080
Hello buddy
$ curl http://localhost:8081/actuator/health
{"status":"UP"}
2.1. Dockerfileでの宣言
アプリケーションmy-appは、エンドポイントを8080と8081の2つのポートで公開するため、Dockerfileで両方のポートを公開する必要があります。 。 DockerfileのEXPOSE動詞はポートを公開します:
FROM openjdk:8-jdk-alpine
EXPOSE 8080
EXPOSE 8081
ARG JAR_FILE=target/my-app-0.1.jar
ADD ${JAR_FILE} my-app.jar
ENTRYPOINT ["java","-jar","/my-app.jar"]
ただし、このDockerfile を使用してイメージをビルドする場合:
$ docker build -t my-app:latest .
Dockerfile の作成者は、コンテナーが実行されるネットワークを制御できないため、これは実際にはポートを開きません。 むしろ、EXPOSEコマンドはドキュメントとして機能します。 これにより、コンテナーを実行する人は、アプリケーションと通信するために、コンテナーのどのポートをホストコンピューターに公開する必要があるかを理解します。
このポートで通信するためのプロトコル– TCPまたはUDP –を指定することもできます。
EXPOSE 8080/tcp
EXPOSE 8081/udp
何も指定しない場合は、デフォルトでTCPを使用します。
このコマンドは、次の範囲のポート宣言もサポートします。
EXPOSE 8000-8009
上記のコマンドは、アプリケーションが通信のために8000から8009までの10個のポートを開く必要があることを示しています。
2.2. dockerrunコマンドでの宣言
DockerfileでEXPOSEコマンドを使用して、1つのポート8080のみを公開するmy-appのDockerイメージがすでにあると仮定します。 ここで、他のポート8081を公開する場合は、実行コマンドとともに–exposeパラメーターを使用する必要があります。
$ docker run --name myapp -d --expose=8081 my-app:latest
上記のコマンドは、イメージmy-appからmyappという名前のコンテナーを実行し、ポート8080とともに8081を公開します。 これは、次を使用して確認できます。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2debb3c5345b my-app:latest "java -jar /my-app.j…" 5 seconds ago Up 3 seconds 8080-8081/tcp myapp
このパラメーターはホストコンピューターのポートのみを公開し、公開しないことを理解することが重要です。より明確に理解するために、以下を実行してみましょう。
$ docker port myapp
ホストコンピューターでポートが開かれてマップされていないため、これは何も出力しません。 したがって、コンテナ内で実行されていても、アプリケーションにアクセスすることはできません。
$ curl http://localhost:8080
curl: (7) Failed to connect to localhost port 8080: Connection refused
同じ方法で、さまざまなポートを公開することもできます。
$ docker run --name myapp -d --expose=8000-8009 my-app:latest
3. ポートの公開
ドッキングされたアプリケーションのポートを公開する方法はすでに学習しました。 それでは、それらを公開します。
3.1. 実行コマンドでの公開
前のセクションのmy-appイメージの例を再利用してみましょう。 Dockerfile で公開されている2つのポート– 8080と8081があります。 このイメージに基づいてコンテナを実行している間、 -P引数を使用して、公開されているすべてのポートを一度に公開できます。
$ docker run --name myapp -d -P myApp:latest
上記のコマンドは、ホストコンピューターで2つのランダムなポートを開き、Dockerコンテナーのポート8080および8081にマップします。 ある範囲のポートを公開した場合も同じように動作します。
マップされたポートを確認するには、次を使用します。
$ docker port myapp
8080/tcp -> 0.0.0.0:32773
8081/tcp -> 0.0.0.0:32772
これで、ポート 32773、を使用してアプリケーションにアクセスでき、32772を介して管理エンドポイントにアクセスできます。
$ curl http://localhost:32773
Hello buddy
$ curl http://localhost:32772/actuator/health
{"status":"UP"}
ランダムなポートを割り当てる代わりに、-pパラメーターを使用してホストコンピューターの特定のポートを選択する場合があります。
$ docker run --name myapp -d -p 80:8080 my-app:latest
上記のコマンドは、ポート 8080 のみを公開し、ホストサーバーのポート80にマップします。 コンテナの外部からアクチュエータのエンドポイントにアクセスできるようにはなりません。
$ curl http://localhost:80
Hello buddy
$ curl http://localhost:8081/actuator/health
curl: (7) Failed to connect to localhost port 8081: Connection refused
複数のポートマッピングを公開するには、-pパラメーターを複数回使用します:
$ docker run --name myapp -d -p 80:8080 -p 81:8081 my-app:latest
このようにして、コンテナのどのポートが外部に開くかを制御することもできます。
3.2. docker-composeで公開
docker-compose でアプリケーションを使用する場合、docker-compose.ymlファイルで公開する必要のあるポートのリストを提供できます。
version: "3.7"
services:
myapp:
image: my-app:latest
ports:
- 8080
- 8081
このセットアップを起動すると、ホストサーバーのランダムなポートに指定されたポートが割り当てられます。
$ docker-compose up -d
Starting my-app_myapp_1 ... done
$ docker port my-app_myapp_1
8080/tcp -> 0.0.0.0:32785
8081/tcp -> 0.0.0.0:32784
ただし、ポートの特定の選択肢を提供することは可能です。
version: "3.7"
services:
myapp:
image: my-app:latest
ports:
- 80:8080
- 81:8081
ここで、80と81はホストマシンのポートであり、8080と8081はコンテナポートです。
4. 結論
この記事では、Dockerコンテナで複数のポートを公開および公開するさまざまな方法について説明しました。 公開が実際に何を意味するのか、またコンテナとホストコンピュータ間のポートの公開を完全に制御する方法を見てきました。