6
4

Docker 環境で Spring Boot Webサービスを起動する

Last updated at Posted at 2023-03-05

Docker 環境で Spring Boot Webサービスを起動する

こんにちは、@studio_meowtoon です。今回は、WSL Ubuntu 24.04 の Docker 環境で Spring Boot Web アプリケーションをコンテナーとして起動する方法を紹介します。
spring-boot_on_docker.png

目的

Windows 11 の Linux でクラウド開発します。

こちらから記事の一覧がご覧いただけます。

実現すること

ローカル環境の Ubuntu の Docker 環境で、Dockerfile からビルドした Spring Boot Web サービスのカスタムコンテナーを起動します。

JAR ファイル形式のアプリをコンテナーとして起動

実行環境

要素 概要
terminal ターミナル
Ubuntu OS
Docker コンテナー実行環境

Web サービス コンテナー

要素 概要
app-hello-spring-boot カスタムコンテナー
JVM Java 実行環境
app.jar Java アプリケーション
tomcat Web サーバー

Spring Boot では、コマンド簡単にコンテナイメージを作成できる機能があります。しかし、この記事では Dockerfile を使用してコンテナイメージをビルドすることで、Docker の基礎的な使い方を学習することを目的としています。ご注意ください。

技術トピック

Dockerfile とは?

こちらを展開してご覧いただけます。

Dockerfile

Dockerfile は、Docker コンテナーを構築するためのテキストファイルです。Docker コンテナーはアプリケーションやサービスを実行するための環境を含む軽量でポータブルな仮想化ユニットです。

キーワード 内容
スクリプト形式 Dockerfile はシンプルなスクリプト形式で記述されるため、コンテナーのビルドプロセスを自動化することが容易です。
レイヤー構造 Docker イメージは Dockerfile の各命令が実行される際にレイヤーとして生成され、再利用やキャッシュが可能な構造となっています。
バージョン管理 Dockerfile はテキストベースであるため、コードと同様にバージョン管理システムで管理しやすいです。
ポータビリティ Dockerfile により、アプリケーションとその依存関係が1つのコンテナイメージにパッケージ化されるため、異なる環境間での移植性が高まります。
自動化と効率化 Dockerfile を使用することで、アプリケーションのビルドや環境構築を自動化できます。これにより、手動での作業時間やヒューマンエラーが減り、開発・デプロイプロセスが効率的になります。
再現性 Dockerfile はビルド手順を完全に定義するため、異なる環境で同じアプリケーションを再現できます。これにより、開発、テスト、本番環境間での一貫性が確保されます。
環境の分離 Docker コンテナーはホストシステムから分離されるため、アプリケーションの依存関係やライブラリの衝突を回避し、より安全な環境で実行できます。
拡張性 Dockerfile を使用することで、カスタムイメージを作成できます。このため、特定のニーズに合わせてカスタマイズされたコンテナイメージを容易に作成できます。

開発環境

  • Windows 11 Home 23H2 を使用しています。

WSL の Ubuntu を操作しますので macOS の方も参考にして頂けます。

WSL (Microsoft Store アプリ版) ※ こちらの関連記事からインストール方法をご確認いただけます

> wsl --version
WSL バージョン: 2.2.4.0
カーネル バージョン: 5.15.153.1-2
WSLg バージョン: 1.0.61

Ubuntu ※ こちらの関連記事からインストール方法をご確認いただけます

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04 LTS
Release:        24.04
Codename:       noble

Java JDK ※ こちらの関連記事からインストール方法をご確認いただけます

$ java -version
openjdk version "11.0.24" 2024-07-16
OpenJDK Runtime Environment (build 11.0.24+8-post-Ubuntu-1ubuntu324.04.1)
OpenJDK 64-Bit Server VM (build 11.0.24+8-post-Ubuntu-1ubuntu324.04.1, mixed mode, sharing)

Maven ※ こちらの関連記事からインストール方法をご確認いただけます

$ mvn -version
Apache Maven 3.8.7
Maven home: /usr/share/maven
Java version: 11.0.24, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64

Docker ※ こちらの関連記事からインストール方法をご確認いただけます

$ docker --version
Docker version 27.0.3, build 7d4bcd8

この記事では基本的に Ubuntu のターミナルで操作を行います。Vim を使用してコピペする方法をはじめて学ぶ人のために、以下の記事で手順を紹介しています。ぜひ挑戦してみてください。

作成する Web アプリケーションの仕様

No エンドポイント HTTPメソッド MIME タイプ
1 /api/data GET application/json

/api/data というエンドポイントに対して HTTP GET リクエストを送信すると、JSON データがレスポンスされるシンプルな Web サービスを実装します。
{"message":"Hello World!"}

Hello World を表示する手順

Spring Boot Web サービスの作成

こちらの関連記事で手順がご確認いただけます。

プロジェクトフォルダーに移動

プロジェクトフォルダーに移動します。
※ ~/tmp/hello-spring-boot をプロジェクトフォルダーとします。

$ cd ~/tmp/hello-spring-boot
構成を単純にする為に、全ての要素をアプリケーションクラス記述した例

コントローラークラスを削除して、アプリケーションクラスを修正します。

$ rm src/main/java/com/example/springboot/controller/HelloController.java
$ vim src/main/java/com/example/springboot/Application.java

ファイルの内容

Application.java
package com.example.springboot;

import java.util.Map;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
@RequestMapping("/api")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @GetMapping("/data")
    public Map<String, String> getData() {
        Map<String, String> map = Map.of("message", "Hello World!");
        return map;
    }
}

アプリのビルド

Java アプリをビルドします。
※ target/app.jar が作成されます。

$ mvn clean package

ここまでの手順で、ローカル環境の UbuntuJAR ファイル形式のアプリをビルドすることができました。

コンテナイメージの作成

Dockerfile を作成します。

$ vim Dockerfile

ファイルの内容

Dockerfile
# from the base image of a jdk 11 container on Ubuntu 20.04.
FROM adoptopenjdk/openjdk11:x86_64-ubuntu-jdk-11.0.18_10-slim

# create a work dir.
WORKDIR /app

# copy a jvm app.
COPY target/*.jar app.jar

# open port 8080 for a jvm app.
EXPOSE 8080

# startup a jvm app.
ENTRYPOINT ["java","-jar","app.jar"]
説明を開きます。

Dockerfile は、コンテナイメージをビルドするために必要な指示を記述したファイルです。

今回の例では以下のようなステップを実行します。

命令 内容
FROM ベースとなるコンテナイメージを指定します。この場合は、Ubuntu の slim バージョンのイメージを使用しています。
WORKDIR コンテナー内で作業するディレクトリを指定します。ここでは、/app ディレクトリを作成しています。
COPY ホストマシンからコンテナー内にファイルをコピーします。target/*.jar の部分は、target ディレクトリにあるすべての .jar ファイルを指定しています。また、app.jar という名前でコンテナー内にコピーされます。
EXPOSE コンテナーが使用するポートを指定します。ここでは、8080 ポートを指定しています。
ENTRYPOINT コンテナーが起動する際に実行されるコマンドを指定します。この場合は、java -jar app.jar が実行されます。

このように Dockerfile を記述し、docker build コマンドでビルドすることで、コンテナイメージを作成できます。

Docker デーモンを起動します。

$ sudo service docker start
 * Starting Docker: docker    [ OK ]

Docker 環境をお持ちでない場合は、以下の関連記事から Docker Engine のインストール手順をご確認いただけます。

コンテナイメージをビルドします。

$ docker build \
    --no-cache \
    --tag app-hello-spring-boot:latest .
説明を開きます。

docker build コマンドは、現在のディレクトリにある Dockerfile を使用して、app-hello-spring-boot という名前のコンテナイメージをビルドします。ビルドされたイメージは、Docker ホスト上のローカルリポジトリに保存されます。. は、現在のディレクトリをビルドコンテキストとして使用することを指定します。

コンテナイメージを確認します。

$ docker images | grep app-hello-spring-boot
REPOSITORY              TAG       IMAGE ID       CREATED          SIZE
app-hello-spring-boot   latest    39115028afa6   12 seconds ago   390MB
説明を開きます。

docker images コマンドは、コンテナイメージのリストを表示します。grep コマンドは、指定された文字列を含む行をフィルタリングします。

ここまでの手順で、ローカル環境の Docker にアプリのカスタムコンテナイメージをビルドすることができました。

コンテナーを起動

ローカルでコンテナーを起動します。
※ コンテナーを停止するときは ctrl + C を押します。

$ docker run --rm \
    --publish 8080:8080 \
    --name app-local \
    app-hello-spring-boot
説明を開きます。

docker run コマンドで、app-hello-spring-boot というコンテナイメージから、app-local という名前のコンテナーを作成し、ホストの 8080 ポートとコンテナーの 8080 ポートをマッピングします。つまり、ホストの 8080 ポートからアクセス可能なコンテナーが作成されます。

ここまでの手順で、ローカル環境の Docker でアプリのカスタムコンテナーを起動することができました。

コンテナーの動作確認

別ターミナルから curl コマンドで確認します。

$ curl -v http://localhost:8080/api/data -w '\n'

出力

* Host localhost:8080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8080...
* Connected to localhost (::1) port 8080
> GET /api/data HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.5.0
> Accept: */*
>
< HTTP/1.1 200
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Fri, 09 Aug 2024 23:17:58 GMT
<
* Connection #0 to host localhost left intact
{"message":"Hello World!"}

ここまでの手順で、ターミナルに {"message":"Hello World!"} と表示され、JSON データを取得することができました。

コンテナーの状態を確認してみます。

$ docker ps
CONTAINER ID   IMAGE                   COMMAND               CREATED         STATUS         PORTS                                       NAMES
377111ffea02   app-hello-spring-boot   "java -jar app.jar"   4 minutes ago   Up 3 minutes   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   app-local
説明を開きます。

docker ps コマンドは、現在実行中のコンテナーの一覧を表示します。実行中のコンテナーの情報には、コンテナーID、コンテナー名、使用しているイメージ、ポートマッピング、作成された時間、状態などが含まれます。

コンテナーに接続

別ターミナルからコンテナーに接続します。

$ docker exec -it app-local /bin/bash
説明を開きます。

docker exec コマンドで、コンテナー app-local に対して、対話的な bash シェルでコンテナー内部にログインします。-i-t のオプションは、対話的な操作が可能な状態を作り出します。/bin/bash は、bash シェルを起動するためのコマンドです。

コンテナーに接続後ディレクトリを確認します。
※ コンテナーから出るときは ctrl + D を押します。

# pwd
/app
# ls -lah
total 17M
drwxr-xr-x 1 root root 4.0K Aug  2 00:00 .
drwxr-xr-x 1 root root 4.0K Aug  2 09:07 ..
-rw-r--r-- 1 root root  17M Aug  1 23:46 app.jar

top コマンドで状況を確認します。

top - 10:49:52 up  1:32,  0 users,  load average: 0.01, 0.04, 0.01
Tasks:   3 total,   1 running,   2 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   7763.1 total,   6218.8 free,    668.9 used,    875.5 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   6859.1 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
    1 root      20   0 6504924 253188  20960 S   0.3   3.2   0:08.18 java
   52 root      20   0    7244   3816   3264 S   0.0   0.0   0:00.01 bash
   61 root      20   0    9072   3564   3060 R   0.0   0.0   0:00.05 top

コンテナーの情報を表示してみます。

# cat /etc/*-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.6 LTS"
NAME="Ubuntu"
VERSION="20.04.6 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.6 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

このコンテナーは Ubuntu をベースに作成されています。つまり、Ubuntu と同じように扱うことができます。

まとめ

WSL Ubuntu の Docker 環境で、Dockerfile からビルドした Spring Boot Web サービスのカスタムコンテナーを起動することができました。

クラウド開発においては、Dockerfile の理解は重要です。自動ビルドツールもありますが、手動で書く必要があるケースもあります。Ubuntu を使うと Linux の知識も身に付きます。最初は難しく感じるかもしれませんが、徐々に進めていけば自信を持って書けるようになります。

どうでしたか? WSL Ubuntu で、Spring Boot Web アプリケーションを Docker 環境でコンテナーとして手軽に起動できます。ぜひお試しください。今後も Java の開発環境などを紹介しますので、ぜひお楽しみにしてください。

推奨コンテンツ

関連記事

ネイティブイメージビルドと比較してみましょう!

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4