我使用Docker创建了一个可进行远程调试的Nginx,Spring Boot和MySQL开发环境

导言

最近我正在用Spring Boot开发网站。因为我想要像之前发布的那篇文章中一样的开发环境,所以进行了一些调查。这次我会以几乎相同的格式来写作。

行为环境

OSmacOS Catalina 10.15.5Dockerdocker desktop community 2.3.0.3 (45519)Spring Tool SuiteVersion: 4.5.1.RELEASE

Spring Boot项目

我希望使用InteliJ + Kotlin + gradle,不过我打算在当前所处的环境中进行类似的配置。
我认为这种组合在现代Java中已经减少了。

    • Spring Boot 2.2

 

    • Java OpenJDK 11

 

    • STS 4

 

    Maven 3.6.3

构建图像

構成の図解.png

创建以下容器。

    • MySQL

ホストOSのMySQL Workbenchでアクセスできる(localhost:3306)

Spring Boot

ホストOSのブラウザでアクセスできる(localhost:8080)
STS(Eclipse)からリモートデバッグできる(localhost:5005)

Nginx

HTTPSでアクセスできる(https://devnokiyo.example.com)
ただし、GitHubにソースコードを公開する関係で自己署名SSL証明書)

当然,容器之间也会进行通信。

构成

我在GitHub上进行了公开,同时请您参阅。
与前述的文章类似,我将Docker相关的内容与只想管理持久化的内容分开了两个目录。
接下来,会陆续出现文件和其解释。如果您是“想要让GitHub上的代码动起来”的人,请直接跳到这里。

$ tree
├── README.md
├── docker                          # DockerやDocker Compose
│   ├── containers                   # 各コンテナ(イメージ)
│   │   ├── mysql                     # MySQL 5.7
│   │   │   ├── Dockerfile             # MySQL 5.7のDockerファイル
│   │   │   ├── initialize_data.sql    # 初期セットアップでユーザとサンプルデータを作成するスプリプト
│   │   │   └── my.cnf                 # 初期セットアップで反映するmy.cnf
│   │   ├── nginx                     # Nginx 1.19.0
│   │   │   ├── Dockerfile             # NginxのDockerファイル
│   │   │   └── nginx.conf             # 初期セットアップで反映するnginx.conf
│   │   └── spring                    # OpenJDK 11 (Spring Boot構築用)
│   │       └── Dockerfile             # Spring Boot構築用のDockerファイル
│   ├── docker-compose.yml          # Docker Composeファイル
│   └── environments                # 環境変数定義 
│       ├── common.env               # 各コンテナ共通
│       └── db.env                   # DB接続用MySQL関連
└── volumes                         # 永続化するリソース
    ├── app                          # Spring Bootのプロジェクト (以下、特筆点するディレクトリ/ファイルのみコメント)
    │   ├── .m2                       # Mavenのローカルリポジトリ
    │   ├── mvnw                      # Maven Wrapper 今回はこれを使ってSpring Bootを起動する
    │   └── src                        # ソースコード
    │       └── main
    │           └── resources            # この配下にstaticディレクトリを作成しない (静的ファイルはNginxで返す)
    ├── db                           # MySQLのデータ このディレクトリは最初は無し
    └── web                          # Nginxのファイル
        ├── ssl                       # SSL証明書
        │   ├── privkey.pem            # 秘密鍵
        │   └── server.crt             # サーバー証明証
        └── static                    # 静的ファイル置き場

Compose文件

version: '3'
services:                                          # 各コンテナ(サービス)
  db:                                               # MySQLのコンテナ 「db」と命名
    build: containers/mysql                          # Dockerファイルのパス
    env_file:                                        # 環境変数
      - ./environments/common.env                     # 各コンテナ共通
      - ./environments/db.env                         # DB接続用MySQL関連
    volumes:                                         # 永続化
      - ../volumes/db/data:/var/lib/mysql             # MySQLのデータ
    ports:                                           # 開放ポート
      - 3306:3306                                     # ホストOSのWorkBenchでDBを参照する目的
  app:                                              # Spring Bootのコンテナ 「app」と命名
    build: containers/spring                         # Dockerファイルのパス
    env_file:                                        # 環境変数
      - ./environments/common.env                     # 各コンテナ共通
      - ./environments/db.env                         # DB接続用MySQL関連
    # 実行するコマンド(後述)
    command: ./mvnw clean spring-boot:run -Dspring-boot.run.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=*:5005"
    volumes:                                         # 永続化
      - ../volumes/app:/app                           # Spring Bootのプロジェクト
      - ../volumes/app/.m2:/root/.m2                  # Mavenのローカルリポジトリ
    ports:                                           # 開放ポート
      - 8080:8080                                     # ホストOSからNginxを通さずTomcatを直接参照する目的
      - 5005:5005                                     # IDEでリモートデバッグする目的
    depends_on:                                      # 起動する順番
      - db                                            # 「db」の後で起動
  web:                                              # Nginxのコンテナ 「web」と命名
    build: containers/nginx                          # Dockerファイルのパス
    env_file:                                       # 環境変数
      - ./environments/common.env                    # 各コンテナ共通
    volumes:                                        # 永続化
      - ../volumes/web/static:/usr/share/nginx/www/  # 静的ファイル (Spring Bootプロジェクトのresouce/staticには配置しない)
      - ../volumes/web/ssl:/etc/nginx/cert/          # SSL証明書
      - ../volumes/web/log:/var/log/nginx/           # Nginxのログ
    ports:                                          # 開放ポート
      - 443:443                                      # HTTPS この開発環境はHTTPSのみ想定
    depends_on:                                     # 起動する順番
      - app                                          # 「app」の後で起動

MySQL容器

Docker文件

# MySQL 5.7
FROM mysql:5.7

# 初期セットアップで利用するmy.cnfをイメージへコピー
# アーカイブを展開する必要などが無ければADDで無くてCOPYで良い。
COPY my.cnf /etc/mysql/conf.d

# 初期セットアップで実行したいスクリプトをイメージへコピー
COPY initialize_data.sql /docker-entrypoint-initdb.d

复制文件的概要

ホストイメージ概要docker/containers/mysql/my.cnf/etc/mysql/conf.d/文字コードdocker/containers/mysql/initialize_data.sql/docker-entrypoint-initdb.d/Spring Bootアプリ向けDBアカウント/サンプルデータ

使用Docker Comopse设定的环境变量。

TZ=Asia/Tokyo
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=spring
MYSQL_PASSWORD=spring

使用Docker Compose进行的持久化配置

ホストコンテナ概要volumes/db/data/var/lib/mysqlMySQLのデータ

应用程序(Spring Boot)容器

Docker 文件

FROM openjdk:11

# 永続化でマウントされるパスをワーキングディレクトリに指定
WORKDIR /app

通过Docker Compose设置的环境变量

TZ=Asia/Tokyo
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=spring
MYSQL_PASSWORD=spring

通过Docker Compose进行配置的持续化

ホストコンテナ概要volumes/app//appSpring Bootのプロジェクト
GitHubに公開しているものは予めサンプルアプリが入っています)volumes/app/.m2/root/.m2Mavenのローカルリポジトリ
./mvnw cleanを実行するとプラグイン/ライブラリなどを毎回ダウンロードしてしまうことを防ぎます。

Docker Compose 的指令

关于这个命令,我稍微做一下补充说明。

./mvnw clean spring-boot:run -Dspring-boot.run.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=*:5005"
コマンド概要./mvnwJava -jarによる起動は開発中のコードが更新されたときの自動リロードが無効になってしまうので、Mavenで起動することにしました。Maven WrapperがあればMavenをインストールする必要がないので、mvnwを採用しました。address=*:5005JDWPのポートを指定しますが、 ホストOSからコンテナへアクセスするには*:5005とする必要があります。ポート番号しか書いていないネット情報が多いのでご注意ください:skull_crossbones::skull_crossbones:

网页(Nginx)容器

Docker文件

FROM nginx:1.19.0

# 初期セットアップで反映するファイルをコピー
COPY nginx.conf /etc/nginx/conf.d/app.conf
CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf

复制文件的概要

ホストイメージ概要docker/containers/nginx/nginx.conf/etc/nginx/conf.d/app.conf後述

网络服务器的配置

我认为没有什么复杂的设置,我简单地补充一下。
我在GitHub上公开的内容使用的是自签名SSL证书(也被称为“自制证书”),其域名为“*.example.com”。在我的环境中,我使用Let’s Encrypt的SSL证书。

server {
  listen 443 ssl;
  server_name devnokiyo.example.com;

  ssl_certificate     /etc/nginx/cert/server.crt;
  ssl_certificate_key /etc/nginx/cert/privkey.pem;
  ssl_prefer_server_ciphers on;

  access_log /var/log/nginx/access.log;
  error_log  /var/log/nginx/error.log;

  root /app/public;
  try_files $uri /;
  client_max_body_size 10m;
  error_page 404             /404.html;
  error_page 505 502 503 504 /500.html;

  location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-CSRF-Token $http_x_csrf_token;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_pass http://app:8080;
  }

  # Spring Bootの静的ファイルはNginxで返す。
  location ~* .*\.(jpg|gif|png|css|js|ico|svg) {
      root /usr/share/nginx/www;
      access_log off;
  }
}

使用Docker Compose设置的环境变量

TZ=Asia/Tokyo

通过Docker Compose进行永久性配置

ホストコンテナ概要volumes/web/static//usr/share/nginx/www/静的ファイルvolumes/web/ssl//etc/nginx/cert/SSL証明書volumes/web/log//var/log/nginx/ログ

来试一试吧!

使用Docker Compose进行启动

因为每个文件的说明已经结束了,所以我们将运行并确认它们。

    1. 从GitHub下载整个文件。

 

    1. 移动到docker目录。

 

    1. $ cd docker

 

    1. 构建文件。(首次运行可以直接启动)

 

    1. $ docker-compose build –no-cache

 

    1. 构建数据库

 

    1. 步骤 1/3:来自mysql:5.7

 

    1. —> 9cfcce23593a

 

    1. 步骤 2/3:拷贝my.cnf到/etc/mysql/conf.d

 

    1. —> 4af29808e20c

 

 

 

    1. 构建成功 b074e2d8831d

 

    1. 成功标记docker_web:latest

启动服务。
$ docker-compose up
创建网络 “docker_default” 并使用默认驱动程序
创建 docker_db_1 … 完成
创建 docker_app_1 … 完成
创建 docker_web_1 … 完成
正在连接至 docker_db_1,docker_app_1,docker_web_1
db_1 | 2020-06-22 23:04:49+09:00 [Note] [Entrypoint]: MySQL Server 5.7.30-1debian10 的入口点脚本已启动。


db_1 | 版本: ‘5.7.30’ socket: ‘/var/run/mysqld/mysqld.sock’ port: 3306 MySQL Community Server (GPL)


app_1 | [INFO] 正在扫描项目…
app_1 | 正在从中央下载: https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-starter-parent/2.2.8.RELEASE/spring-boot-starter-parent-2.2.8.RELEASE.pom
app_1 | 正在从中央下载: https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-dependencies/2.2.8.RELEASE/spring-boot-dependencies-2.2.8.RELEASE.pom


app_1 | [INFO] 附加代理: []
app_1 | 正在侦听传输 dt_socket,地址: 5005
app_1 |
app_1 | . __ __ _ __ _ (_) __ ___ __ __ ___ __ __ ___
app_1 | /\ | \/ | || | || | \ \ / / | \/ | \ \ / / \ \/ / |__ \
app_1 | / \ | |\/| | || | || | \ V / | |\/| | \ V / \ / ) |
app_1 |/ /\ \| | | | || | || | | | | | | | | | / \ / /
app_1 |\_\ \_\_| |_|_||__|_||_| |_| |_| |_| |_| /_/\_\ |____|
app_1 |
app_1 | :: Spring Boot :: (v2.2.8.RELEASE)
app_1 |
app_1 | 2020-06-22 23:07:31.526 INFO 74 — [ restartedMain] com.example.demo.DemoApplication : 在 e5dd9a4954d8 上使用 PID 74 启动 DemoApplication (/app/target/classes 在 /app 中启动)


app_1 | 2020-06-22 23:07:37.683 INFO 74 — [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat 在端口(s)上启动: 8080 (http),上下文路径为 ”
app_1 | 2020-06-22 23:07:37.686 INFO 74 — [ restartedMain] com.example.demo.DemoApplication : DemoApplication 启动成功,用时 6.781 秒 (JVM 运行时间为 8.41)

通过浏览器访问。

请在hosts文件中使用回环IP地址设置devnokiyo.example.com,然后访问https://devnokiyo.example.com。可能会出现无效证书的错误,请允许异常情况。以下是Chrome的示例,但页面内容会显示。

ブラウザの警告.png
nginxへアクセス.png
undefined
スクリーンショット 2020-06-23 1.32.32.png

访问Tomcat

Tomcatにアクセス.png

确认从主机OS连接到MySQL

通过宿主操作系统的MySQL Workbench访问以下内容。

ホスト名127.0.0.1ポート3306ユーザーspringパスワードspring

DB_確認_1.png

确认Tomcat能够连接到MySQL数据库。

DB_確認_4.png

远程调试

我使用Docker将Spring Boot容器化,但无法使用断点功能很不方便。我会从STS(Eclipse)中附加Tomcat容器,以便进行调试。

准备

リモートデバッグの準備.png

设定断点

ブレークポイントで停止中.png

自动重新加载

因为每次修改源代码后都需要重新构建很麻烦,所以我们使用Spring Boot Devtools的自动重载功能。正如前面提到的,使用Java -jar启动时,在开发过程中代码更新后将失去自动重载功能,但由于我们使用了Maven Wrapper来启动Spring Boot,所以可以实现自动重载。

修改源代码

我們試著添加以下的動作方法。當我們保存控制器類別的檔案時,它會重新載入。

@GetMapping("/hoge")
public String hoge() {
	return "root/index";
}
ソースコード修正

自动重新加载中

查看控制台,您可以了解重新加载的状况。第一行显示了初始启动时的日期和时间,接下来的行显示了自动重新加载的行为。

app_1  | 2020-06-23 00:09:00.911  INFO 40 --- [  restartedMain] com.example.demo.DemoApplication         : Started DemoApplication in 6.459 seconds (JVM running for 8.092)
app_1  | 2020-06-23 00:21:51.379  INFO 40 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
app_1  | 2020-06-23 00:21:51.379  INFO 40 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
app_1  | 2020-06-23 00:21:51.389  INFO 40 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 9 ms
app_1  | 2020-06-23 00:36:13.585  INFO 40 --- [       Thread-5] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
app_1  | 2020-06-23 00:36:13.588  INFO 40 --- [       Thread-5] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
app_1  | 2020-06-23 00:36:13.651  INFO 40 --- [       Thread-5] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
app_1  | 2020-06-23 00:36:13.755  INFO 40 --- [       Thread-5] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
app_1  | 
app_1  |   .   ____          _            __ _ _
app_1  |  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
app_1  | ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
app_1  |  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
app_1  |   '  |____| .__|_| |_|_| |_\__, | / / / /
app_1  |  =========|_|==============|___/=/_/_/_/
app_1  |  :: Spring Boot ::        (v2.2.8.RELEASE)
app_1  | 
app_1  | 2020-06-23 00:36:14.036  INFO 40 --- [  restartedMain] com.example.demo.DemoApplication         : Starting DemoApplication on e5dd9a4954d8 with PID 40 (/app/target/classes started by root in /app)
app_1  | 2020-06-23 00:36:14.037  INFO 40 --- [  restartedMain] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
app_1  | 2020-06-23 00:36:14.500  INFO 40 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
        :
        :
app_1  | 2020-06-23 00:36:15.884  INFO 40 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
app_1  | 2020-06-23 00:36:15.907  INFO 40 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
app_1  | 2020-06-23 00:36:15.908  INFO 40 --- [  restartedMain] com.example.demo.DemoApplication         : Started DemoApplication in 1.965 seconds (JVM running for 1644.96)
app_1  | 2020-06-23 00:36:15.911  INFO 40 --- [  restartedMain] .ConditionEvaluationDeltaLoggingListener : Condition evaluation unchanged
app_1  | 2020-06-23 00:36:30.177  INFO 40 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
app_1  | 2020-06-23 00:36:30.178  INFO 40 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
app_1  | 2020-06-23 00:36:30.183  INFO 40 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 5 ms

确认修正后的结果

自動リロード済み

结束

这次和上次一样,我主要是写了一些关于基础命令的解释以及作者的实际操作经验。与Ruby和Go等JVM系语言相比,关于Docker的信息较少。(虽然有一些零散的信息,但相对来说,线索较少。)
由于已经掌握了基本步骤,我打算尝试运用它作为开发环境,并看看能达到什么样的效果。

广告
将在 10 秒后关闭
bannerAds