見出し画像

【Dockerによるコンテナ仮想化】CLIとCompose - Springboot3 第12回


1.はじめに


こんにちは、今日は最近、いろいろ現場に要求される技術であるDocker(ドッカー)について勉強します。もしも、アプリケーションの環境差異や依存関係の問題に頭を抱えているなら、その解決策を提供します。Dockerは「コンテナ仮想化」技術を活用し、アプリケーションとその依存関係をコンテナと呼ばれる軽量で独立した単位に包み込みます。このおかげで、どんな環境でも同じようにアプリケーションを実行でき、開発から本番環境へのデプロイがより簡単かつ一貫性があります。

二日前実装した自動動画制作機で作った4分ぐらいの簡単な説明映像を聞いてみましょう。(英語で作られてTOEIC聴解試験みたいですね)
要は、CLI(1コンテナ)、 Compose(複数コンテナ)、Orchestration(複数のホスト)です。この記事ではCLIとComposeまで勉強します!

Dockerのシステム的位置は
OSとアプリケーションの間です。


Dockerの流れ
  1. 現プロジェクトのdockerファイルを作成します。

  2. 現在のプロジェクトのビルドでドッカーイメージを作成します。

  3. 現プロジェクトのドッカーイメージをドッカーハブにPushします。

  4. ドッカーハブからドッカーイメージをPullします。

  5. 各端末でドッカーイメージをRunしてコンテナ化して実行します。


2.CLIによりコンテナ仮想化1: Springboot App



構築順序

1.プロジェクト作成

https://start.spring.io/
依存関係設定後、プロジェクトをダウンロードします。
Intellijでダウンロードしたプロジェクトを開きます。
Controllerを作成して "/docker" URIを取得して
文字列を返す関数を作ります。
アプリケーションを実行させる。
URLを入力すると、
文字列値が表示されます。


2.ドッカーファイル生成

Dockerファイルリファレンスを参照します。
まず、右側の'Maven'をクリックしま。
'Lifecycle' の 'clean' と 'package' をクリックします。
最後に、上部の矢印をクリックしてビルドします。
ビルド後、「springboot-docker-demo-0.0.1-SNAPSHOT.jar」確認
プロジェクト内にDockerfileというファイルを作ります。
最初の文字は大文字で、必ず「Dockerfile」という名前にします。
ドッカーハブに接続してopenjdkを探します。
OpenJDKはもうすぐサポートが終了するので、
他の代替イメージを探す必要があります。
ここではeclipse-temurinを使います。
(*でも、以後は設定問題でopenjdk:17に戻りました。)
Dockerfile内に入力するコードです。
FROM eclipse-temurin:17

LABEL maintainer="java.net@gmail.com"

WORKDIR /app

COPY target/springboot-docker-demo-0.0.1-SNAPSHOT.jar /app/spring-boot-docker-demo.jar

ENTRYPOINT ["java", "-jar", "springboot-docker-demo.jar"]
  1. FROM eclipse-temurin:17: このコマンドは基本的なDockerイメージを定義します。eclipse-temurinはAdoptOpenJDKが提供する非公式のOpenJDKリリースであり、:17はJDK 17バージョンを使用することを示しています。

  2. LABEL maintainer="java.net@gmail.com": このコマンドはDockerイメージにメタデータを追加します。java.net@gmail.comはイメージを管理する人またはチームの連絡先情報を示しています。

  3. WORKDIR /app: このコマンドは作業ディレクトリを/appに設定します。以降のコマンドはこのディレクトリを基準に実行されます。

  4. COPY target/springboot-docker-demo-0.0.1-SNAPSHOT.jar /app/spring-boot-docker-demo.jar: このコマンドはローカルマシンのtarget/springboot-docker-demo-0.0.1-SNAPSHOT.jarファイルをDockerイメージの/app/spring-boot-docker-demo.jarパスにコピーします。

  5. ENTRYPOINT ["java", "-jar", "springboot-docker-demo.jar"]: このコマンドはコンテナが起動されるときに実行される必要があるコマンドを設定します。ここではSpring Bootアプリケーションを実行するためにjava -jar springboot-docker-demo.jarを使用しています。

 

3.ドッカーイメージのBUILD/RUN

「Docker Desktop」を起動後、
「docker build -t springboot-docker-demo .」コマンドを入力
うまくいきますね!
「docker images」コマンドで確認
「:0.1.RELEASE」でtag nameを指定できます。
「docker images」コマンドで確認

** 実行がうまくいかない場合は、イメージを削除して再試行してください。もし、「in user(dangling)」というメッセージが出たら、コマンドウィンドウに 「docker system prune -a」 と入力すると全て削除されます。

**ここでIntellijのバージョンがdockerのプラグインのバージョンと合わなかったのでかなり苦労しました。eclipse-temurinではなく、openjdk17に合わせました。 openjdk17はセキュリティの問題で推奨されないそうですが、この記事では実習のために仕方なくopenjdk17を使いました。


openjdk17に切り替えた後、
「docker run -p 8081: 8080 -d springboot-docker-demo」入力!うまくいきますね!
docker run -p 8081: 8080 -d springboot-docker-demo

「-d」というオプションコマンドを説明します。
実行方式に関するコマンドで、実行方式はフォアグラウンドモードとバックグラウンドモードの二つがあります。

フォアグラウンドモード(Foreground Mode)

基本的にドッカーコンテナはフォアグラウンドモードで実行されます。このモードでは、コンテナの実行ログがターミナルに出力され、コンテナが実行中、ターミナルはそのコンテナの制御を占有します。ユーザーが特定のキーを押すまでコンテナは継続的に実行されます。

バックグラウンドモード (Background Mode)

「-d」または「-detach」オプションを使うと、Dockerコンテナをバックグラウンドモードで実行することができます。このモードでは、コンテナの実行ログがターミナルに表示されず、バックグラウンドで実行されます。ユーザーは他の作業をしたり、ターミナルを終了することができます。

バックグラウンドモードで実行した後、
「docker logs -f ****」コマンドで実行内容を確認することができます。

docker logs -f ****
作業の都合上、バックグラウンドモードで実行し、
ログを実行させて確認する方が良いです。
docker ps
docker stop ****
ドッカーコンテナの実行を中断する方法はstopを使うことです。 プロセス番号(4桁くらいでいい)を入力します。

4.ビルドしたドッカーイメージをドッカーハブにPUSH

ログイン、Tag、Push
docker login
docker tag spring-docker-demo ****/spring-docker-demo:0.1.RELEASE
docker push ****/spring-docker-demo:0.1.RELEASE
「https://hub.docker.com/repositories/」に生成完了。


5.ドッカーハブからドッカーイメージPULL

ドッカーハブのTAGで名前確認
docker pull ****/spring-docker-demo:0.1.RELEASE
「docker pull ****/spring-docker-demo:0.1.RELEASE」入力
うまくいきますね!


3.CLIによりコンテナ仮想化2: MySQLとSpringboot



1.MySQLイメージをPULL/RUN

次はMysqlドッカーのイメージをPullしてみましょう。下記のコマンド入力し、バックグラウンドで実行します。

docker pull mysqldb
docker run -p 3307:3306 --name localhost -e MYSQL_ROOT_PASSWORD=**** -e MYSQL_DATABASE=**** -e MYSQL_USER=**** -e MYSQL_PASSWORD=**** -d mysql:latest
強調された部分は自分のアカウントとパスワード入力。

「-d」バックグラウンドモードで実行されていて、「docker logs -f ****」コマンドで実行内容を確認することができます。

docker logs -f localhost


Dockerネットワーク
あるコンテナと別のコンテナを通信させるためには、同じDockerネットワークにデプロイする必要があります。

「 docker network create springboot-mysql-net」を入力
「 docker network ls」を入力し、インストール完了確認

Dockerネットワークとしてspringbok-mysql-netを作成しました。ドライバはBridgeです。


SELECT user, host FROM mysql.user;
CREATE USER '****'@'localhost' IDENTIFIED BY '****';
GRANT ALL PRIVILEGES ON *.* TO '****'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;

DBアカウントがrootしかなくて
MySQL Workbenchで上記のコマンドを入力し、
新しいアカウントを作った。


MySQLを
docker run --name mysqldb --network springboot-mysql-net -e MYSQL_ROOT_PASSWORD=**** -e MYSQL_DATABASE=employee_db -d mysql

このコマンドを実行すると、Dockerは "mysqldb" という名前のコンテナを作成し、指定されたオプションに従ってMySQLが実行されます。データベースとネットワークに関する設定は、イメージを実行する際に構成され、これによりアプリケーションとデータベース間で通信が可能になります。

  • --name mysqldb: 実行されるコンテナの名前を指定します。ここでは "mysqldb" と指定されています。

  • --network springboot-mysql-net: コンテナが接続されるネットワークを指定します。"springboot-mysql-net"という名前のDockerネットワークにコンテナを接続します。

  • -d: コンテナをバックグラウンドで実行します。つまり、実行後もシェルを占有せず、他のコマンドを入力できます。

  • mysql: 使用するイメージの名前です。ここでは、公式のMySQLイメージを使用しています。


docker ps
docker logs -f 「process_id」

「docker ps 」プロセスのIdを照会し、
docker logs -f 「process_id」 で実行内容を確認。

ドッカーでDBにアクセスする

docker exec -it [process_id] bash
mysql -u root -p
「show databases;」を入力すると、
一覧が表示されます。


まとめ1: pull mysql, network create, run mysqldb
まとめ2:exec, db アクセス


2.Dockerfileの作成

Springbootのプロジェクトをビルドします。
jarファイル生成確認。
プロジェクトの中にDockerfile生成。
下記のコード入力。
FROM openjdk:17

LABEL mentainer="abc@gmail.com"

WORKDIR /app

COPY target/springboot-restful-webservices-0.0.1-SNAPSHOT.jar /app/springboot-restful-webservices.jar

ENTRYPOINT ["java", "-jar", "springboot-restful-webservices.jar"]


3.プロファイルの実装とDockerイメージのビルド

src/main/resources/application.propertiesで「spring.profiles.active=docker」設定。
src/main/resources/application-docker.properties
このパスにドッカー設定ファイルを作ります。
ここは 「localhost」ではなくて、「//mysqldb:3306/」です。
appication.properties
spring.datasource.url=jdbc:mysql://localhost:3306/user_management
spring.datasource.username=root
spring.datasource.password=1234

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto=update

spring.profiles.active=docker


application-docker.properties
注意点!
application-docker.proeprtiesに入れるdbのパスワードは

最初にmysqlコンテナを動かす時設定したrootアカウントのパスワードと同じです。ここで迷うとかなり時間を無駄にする可能性があるので注意しましょう。
spring.datasource.url=jdbc:mysql://mysqldb:3306/employee_db
spring.datasource.username=root
spring.datasource.password=1234

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto=update
プロジェクトの再ビルドです。
「springboot-restful-webservices」のビルドがうまくいかない場合はテストをスキップしていないからです。
上部の円の中に斜線が引かれたアイコンをクリックして
ビルドする必要があります。
DockerファイルからDockerイメージのビルド成功


*もし、MySQLのImageを間違ってビルド、実行したら、コンテナを止めて、削除し、再ビルドします。

コンテナ中止、削除、再ビルド、実行


4. SpringBootのDockerイメージ実行・APIテスト

ついに、「springboot-restful-webservices」を実行します!!下記のコマンドをPowershellに入力します。

docker run --network springboot-mysql-net --name springboot-mysql-container -p 8080:8080 -d springboot-restful-webservices
docker logs -f [process_id]
 PostmanでCreat APIテスト
ユーザー情報が格納された。
削除もテストします。
格納されたユーザー情報が削除された。


4.Composeにより複数のコンテナ仮想化


Docker Composeの実行例
「docker compose up」コマンドが核心。
別々にコンテナ仮想化をしたら、時間コストがかかります。
それで、Docker Composeを用いたら、数のコンテナ仮想化をよりしやすくなります。
Compose実行のために、コンテナを削除、イメージも削除
プロジェクトに「docker-compose.yml」を作成します。
version: "3.8"

services:
  mysqldb:
    container_name: mysqldb
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: 1234
      MYSQL_DATABASE: employee_db
    networks:
      springboot-mysql-net:

  springboot-restful-webservices:
    container_name: springboot-restful-webservices
    build:
      context: ./
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    depends_on:
      - mysqldb
    networks:
      springboot-mysql-net:
    restart: on-failure

networks:
  springboot-mysql-net:
  1. version: "3.8": Docker Composeファイルのバージョンを指定します。

  2. services: 複数のサービスを定義します。

    • mysqldb: MySQLデータベースサービスを定義します。

      • container_name: コンテナの名前を指定します。

      • image: 使用するイメージを指定します。ここでは公式のMySQLイメージを使用しています。

      • environment: 環境変数を設定します。ここではMySQLルートユーザーのパスワードとデータベース名を設定しています。

      • networks: サービスが属するネットワークを指定します。

    • springboot-restful-webservices: Spring Boot Webサービスを定義します。

      • container_name: コンテナの名前を指定します。

      • build: Dockerfileを使用してイメージをビルドします。

      • ports: ホストとコンテナ間のポートマッピングを設定します。

      • depends_on: 他のサービスに依存していることを指定します。ここではmysqldbに依存しています。

      • networks: サービスが属するネットワークを指定します。

      • restart: コンテナの再起動ポリシーを設定します。

  3. networks: 使用するネットワークを定義します。

    • springboot-mysql-net: サービスが属するネットワークです。

バックグラウンドで実行するようにし、
ログを見ます。
POST API Test成功
GET API Test成功
DELETE API Test成功


5.最後に


DockerのCLIとComposeを通じて、MySQLとSpringbootアプリを実行してみますた。今日、使ったコマンドをまとめてみました。

# Docker CLI コマンド
docker pull イメージ名:タグ                           # イメージのダウンロード
docker run [オプション] イメージ名:タグ                # コンテナの実行
docker ps                                            # 実行中のコンテナのリスト表示
docker ps -a                                         # 停止したコンテナのリスト表示
docker exec [オプション] コンテナ名 コマンド            # コンテナ内でコマンドを実行
docker build [オプション] パス                         # イメージのビルド
docker logs [オプション] コンテナ名                    # ログの表示
docker rm [オプション] コンテナ名                      # コンテナの削除

# Docker Compose コマンド
docker-compose up                                    # Docker Composeアプリケーションの実行
docker-compose up -d                                 # バックグラウンドでアプリケーションを実行
docker-compose ps                                    # コンテナおよびネットワークの確認
docker-compose down                                  # アプリケーションの停止
docker-compose logs [サービス名]                      # ログの確認
docker-compose up --build                            # ビルドおよび実行
docker-compose up [サービス名]                        # 特定のサービスだけを実行
docker-compose config                                # Docker Composeファイルの構文の確認

上記のコマンドでイメージのビルド、イメージのPULL、イメージをコンテナで実行までしますた。CLI は迅速な開発およびテストシナリオで素早く使用できます。Compose は複雑なアプリケーションを効果的に管理するのに役立ちます。いろいろ目的にあたって使いましょう!

エンジニアファーストの会社 株式会社CRE-CO
ソンさん



【参考】



この記事が気に入ったらサポートをしてみませんか?