Docker使っていてのあるあるが、「そのコンテナ何が動いてる?」とcomposeファイルを確認したくなりますが、そもそも何処に置いたっけ?となってしまいます。そんな時に活躍するのがこれです。
Powershell版
docker inspect my-java-api | Select-String "working_dir"
work >> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
79052e8700f7 eclipse-temurin:21-jdk "/__cacert_entrypoin…" 2 weeks ago Up 17 minutes 0.0.0.0:9090->8080/tcp, [::]:9090->8080/tcp my-java-api
a53ffca99512 redmine:latest "/docker-entrypoint.…" 2 weeks ago Up 17 minutes 0.0.0.0:7070->3000/tcp, [::]:7070->3000/tcp redmine-61-redmine-1
9387191388e8 postgres:14 "docker-entrypoint.s…" 2 weeks ago Up 17 minutes 5432/tcp redmine-61-db-1
work >> docker inspect my-java-api | Select-String "working_dir"
"com.docker.compose.project.working_dir": "C:\\docker-disk\\java-api",
work >>
compose.yaml
以下内容をcompose.yamlファイルに書き込む
services:
java-api:
# Java 21 の実行環境(JRE)の公式イメージ
image: eclipse-temurin:21-jdk
container_name: my-java-api
ports:
- "9090:8080" # [手元のPCのポート] : [JAR内のアプリが待ち受けるポート]
volumes:
# 手元の apps フォルダを、コンテナ内の /app フォルダにマウント
- ./apps:/app
working_dir: /app
# コンテナが起動したときに実行するコマンド(JARを起動する)
#command: java -jar sample-api.jar
# Java21の機能で、ソースコードをダイレクトに実行!
command: java sample-api.java
restart: always
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
public class SampleApi {
public static void main(String[] args) throws IOException {
// すべてのIP(0.0.0.0)からのアクセスを8080ポートで待ち受け
HttpServer server = HttpServer.create(new InetSocketAddress("0.0.0.0", 8080), 0);
server.createContext("/sample-api", new HttpHandler() {
@Override
public void handle(HttpExchange exchange) throws IOException {
// 1. アクセスしてきた相手のIPアドレスを取得
String remoteAddress = exchange.getRemoteAddress().toString();
// 2. 現在時刻
String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
// 3. レスポンス文字列の組み立て(診断レポート風)
StringBuilder sb = new StringBuilder();
sb.append("=========================================\n");
sb.append(" CONNECTION TEST: SUCCESS !!! \n");
sb.append("=========================================\n");
sb.append("Time: ").append(now).append("\n");
sb.append("Your Remote IP: ").append(remoteAddress).append("\n");
sb.append("Request Method: ").append(exchange.getRequestMethod()).append("\n");
sb.append("-----------------------------------------\n");
sb.append("Received HTTP Headers:\n");
// 4. 受け取ったリクエストヘッダーをすべて列挙
for (Map.Entry<String, List<String>> header : exchange.getRequestHeaders().entrySet()) {
sb.append(" ").append(header.getKey()).append(": ").append(header.getValue()).append("\n");
}
sb.append("=========================================\n");
String response = sb.toString();
byte[] bytes = response.getBytes(StandardCharsets.UTF_8);
// ヘッダー設定(テキスト形式、UTF-8)
exchange.getResponseHeaders().set("Content-Type", "text/plain; charset=UTF-8");
exchange.sendResponseHeaders(200, bytes.length);
try (OutputStream os = exchange.getResponseBody()) {
os.write(bytes);
}
}
});
server.setExecutor(null);
System.out.println("Enhanced Connectivity Test Server started on port 8080");
server.start();
}
}
