前の2つの記事では、Dockerデプロイメントに基づくSpringBootコンテナーについて説明しましたが、この記事を読む前に関連する基礎がない場合は、前のチュートリアルを確認できます。
入門から落とし穴へのDocker(2):Dockerに基づいてSpringBootマイクロサービスを構築する
初めてdockerを使用したときにこのシナリオに遭遇したかどうかはわかりません。マイクロサービスをデプロイするたびに、コンテナーを操作するためにdocker run xxx、docker kill xxxなどのコマンドを実行する必要があります。システムが複数のDockerコンテナーに依存していると仮定すると、各Dockerコンテナーの展開は、開始およびシャットダウンするコマンドを手動で書き込む必要がありますか?これを行うと、運用および保守担当者の開発作業負荷が増加し、エラーが発生しやすくなります。
Docker Composeオーケストレーションテクノロジー
前回の記事では、我々はドッカーのコンテナ化技術の開発を説明したが、私たちが持っているとして、より多くのドッカーをして、コンテナの管理は、また、特に厄介であるドッカーのCompose技術が生まれました。
Docker Composeテクノロジーは、ファイルを介して一連の複雑なアプリケーションを定義および実行し、Docker-composeファイルを介して複数のコンテナーを開始するDockerツールです。インターネット上での実際のDocker-composeの事例は多数ありますが、一部の詳細は省略されています。 、そのため、以下では、Docker-composeを簡単なケースを通してより浅いものからより深いものへと順を追って説明します。
SpringBootマイクロサービスアプリケーションをパッケージ化して統合するDocker Composeに基づく
いつものように基本的なSpringBootマイクロサービスプロジェクトを構築しましょうまず、基本バージョンのプロジェクト構造を見てみましょう。
1つ目は、pomファイルの構成内容です。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sise.idea</groupId>
<artifactId>springboot-docker</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-boot-docker</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
</dependencies>
<build>
<finalName>springboot-docker</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
次に、Javaプログラムのコンテンツコードがあります。従来のコントローラクラスとアプリケーションクラスがあります。コードは次のとおりです。
クラスアプリケーションの開始
package com.sise.docker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author idea
* @data 2019/11/20
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
コントローラーDockerController
package com.sise.docker.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author idea
* @data 2019/11/20
*/
@RestController
@RequestMapping(value = "/docker")
public class DockerController {
@GetMapping(value = "/test")
public String test(){
System.out.println("=========docker test=========");
return "this is docker test";
}
}
yml設定ファイル:
server:
port: 7089
次は、docker-composeがパッケージ化されているときに使用される構成ファイルです。ここで使用される方法は通常、必要なdockerコンテナー用のdockerfileを書き込み、それをDocker Composeでパッケージ化して管理することです。マイクロサービスがMySQLやMongoDBなどのアプリケーションを参照する必要があると仮定すると、全体的なアーキテクチャは次の図に示されています。
それでは、シンプルな単一のコンテナーから始めて、Docker ComposeでSpringBootを管理する方法を見てみましょう。以下は、SpringBootをDockerコンテナーにパッケージ化するDockerfileです。
#需要依赖的其他镜像
FROM openjdk:8-jdk-alpine
# Spring Boot应用程序为Tomcat创建的默认工作目录。作用是在你的主机”/var/lib/docker”目录下创建一个临时的文件,并且链接到容器中#的”/tmp”目录。
VOLUME /tmp
#是指将原先的src文件 添加到我们需要打包的镜像里面
ADD target/springboot-docker.jar app.jar
#设置镜像的时区,避免出现8小时的误差
ENV TZ=Asia/Shanghai
#容器暴露的端口号 和SpringBoot的yml文件暴露的端口号要一致
EXPOSE 7089
#输入的启动参数内容 下边这段内容相当于运行了java -Xms256m -Xmx512m -jar app.jar
ENTRYPOINT ["java","-Xms256m","-Xmx512m","-jar","app.jar"]
次にdocker-compose.ymlファイルを追加するためのリンクがあります以下はスクリプトの内容です:
#docker引擎对应所支持的docker-compose文本格式
version: '3'
services:
#服务的名称
springboot-docker:
build:
context: .
# 构建这个容器时所需要使用的dockerfile文件
dockerfile: springboot-dockerfile
ports:
# docker容器和宿主机之间的端口映射
- "7089:7089"
docker-compose.ym構成ファイルには特別なルールがあり、通常は最初にバージョン番号を定義してから、一連のコンテナー関連サービスをリストします。
次に、このDockerサービスをパッケージ化して、関連するLinuxサーバーにデプロイします。ここでは、Alibaba Cloudから購入したサーバーを使用してデモを行います。
現在、ファイルはパッケージ化されていないため、ターゲットディレクトリはありません。したがって、dockerfileファイルがビルドされると、成功しません。mvnを最初にパッケージ化する必要があります。
mvn package
次はDocker-Composeコマンドの入力です。
[root@izwz9ic9ggky8kub9x1ptuz springboot-docker]# docker-compose up -d
Starting springboot-docker_springboot-docker_1 ... done
[root@izwz9ic9ggky8kub9x1ptuz springboot-docker]#
今回入力したコマンドは、前のチュートリアルで説明したdockerコマンドとは多少異なることがわかります。これはdocker-composeコマンドになります。このコマンドは、Docker composeファイル専用に設計されており、コンテナーがバックグラウンドで実行されていることを示します。docker-composeファイルのナレッジはSpringBootコンテナーのパッケージングを書き込むため、起動時に1つのdockerコンテナーのみが表示されます。
docker-composeコマンドが有効かどうかを確認するには、docker--compose psコマンドを使用して確認できます。
ここでは、docker logs [container id] コマンドを使用して コンテナーにアクセスし、ログの印刷を表示します。
docker logs ad83c82b014d
最後に、リクエストの前に記述されたインターフェースを介して、関連する応答が表示されます。
SpringBoot + Docker構成ケースの基本バージョンが作成されました。最初に描いた絵を思い出してください。
通常、実際の開発では、私たちが直面しているDockerコンテナーはそれほど単純ではなく、複数のコンテナーに依存している可能性があります。
以下では、MySQLとMongoDBへの依存関係を元のSpringBootプロジェクトに追加します。次のシナリオのシミュレーションを容易にするために、2つのエンティティークラスを追加します。
ユーザークラス
package com.sise.docker.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author idea
* @data 2019/11/23
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
private Integer id;
private String username;
}
自動車カテゴリー:
package com.sise.docker.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
/**
* @author idea
* @data 2019/11/23
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Car {
@Id
private Integer id;
private String number;
}
mongodbとmysqlのpom依存関係のコンテンツを増やす
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
関連するdaoレイヤーを記述します。
package com.sise.docker.dao;
import com.sise.docker.domain.Car;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
/**
* @author idea
* @data 2019/11/23
*/
@Repository
public interface CarDao extends MongoRepository<Car, Integer> {
}
package com.sise.docker.dao;
import com.sise.docker.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @author idea
* @data 2019/11/23
*/
@Repository
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void insert() {
String time = String.valueOf(System.currentTimeMillis());
String sql = "insert into t_user (username) values ('idea-" + time + "')";
jdbcTemplate.update(sql);
System.out.println("==========执行插入语句==========");
}
class UserMapper implements RowMapper<User> {
@Override
public User mapRow(ResultSet resultSet, int i) throws SQLException {
User unitPO = new User();
unitPO.setId(resultSet.getInt("id"));
unitPO.setUsername(resultSet.getString("username"));
return unitPO;
}
}
}
コントローラに関連する関数エントリを追加します。
package com.sise.docker.controller;
import com.sise.docker.dao.CarDao;
import com.sise.docker.dao.UserDao;
import com.sise.docker.domain.Car;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Random;
/**
* @author idea
* @data 2019/11/20
*/
@RestController
@RequestMapping(value = "/docker")
public class DockerController {
@Autowired
private UserDao userDao;
@Autowired
private CarDao carDao;
@GetMapping(value = "/insert-mongodb")
public String insertMongoDB() {
Car car = new Car();
car.setId(new Random().nextInt(15000000));
String number = String.valueOf(System.currentTimeMillis());
car.setNumber(number);
carDao.save(car);
return "this is insert-mongodb";
}
@GetMapping(value = "/insert-mysql")
public String insertMySQL() {
userDao.insert();
return "this is insert-mysql";
}
@GetMapping(value = "/test2")
public String test() {
System.out.println("=========docker test222=========");
return "this is docker test";
}
}
対応するコンテンツを元のdocker-compose.ymlファイルに追加し、主にmongodbとmysqlの依存モジュールを増やします。
#docker引擎对应所支持的docker-compose文本格式
version: '3'
services:
#服务的名称
springboot-docker:
container_name: docker-springboot
build:
context: .
dockerfile: springboot-dockerfile
ports:
- "7089:7089"
depends_on:
- mongodb
mongodb:
#容器的名称
container_name: docker-mongodb
image: daocloud.io/library/mongo:latest
ports:
- "27017:27017"
mysql:
#镜像的版本
image: mysql:5.7
container_name: docker-mysql
ports:
- 3309:3306
environment:
MYSQL_DATABASE: test
MYSQL_ROOT_PASSWORD: root
MYSQL_ROOT_USER: root
MYSQL_ROOT_HOST: '%'
ここでは、さまざまなプロファイルでapplication.ymlファイルを区別しようとしています。
前の記事での読者の質問への回答として、異なる環境での異なる構成の指定について考える方法があります。Springbootは、元のプロファイルを維持して、異なる環境の構成を識別します。特定のパッケージング後に読み取られた構成は、springboot-このdockerfileファイルのENTRYPOINTパラメータは、たとえば次の形式で指定されます。
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD target/springboot-docker.jar springboot-docker.jar
#设置镜像的时区,避免出现8小时的误差
ENV TZ=Asia/Shanghai
EXPOSE 7089
#这里可以通过-D参数在对jar打包运行的时候指定需要读取的配置问题
ENTRYPOINT ["java","-Xms256m","-Xmx512m","-Dspring.profiles.active=prod","-jar","springboot-docker.jar"]
最後は、yml構成ファイルの内容です。構成クラスDockerコンテナーの依存関係により、ymlの書き込みメソッドは、ipを介して対応するデータベースにアクセスするのではなく、サービス名マッピングを介して目的を達成します。
application-prod.yml
server:
port: 7089
spring:
data:
mongodb:
uri: mongodb://mongodb:27017
database: test
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://mysql:3306/test?useUnicode=true&characterEncoding=UTF-8
username: root
password: root
関連するコードとファイルが分類されると、コードはパッケージ化のためにサーバーに送信されます。
mvn package
次に、docker-composeを開始します。
这里有个小坑需要注意一下,由于之前我们已经对单独的springboot容器进行过打包了,所以在执行docker-compose up指令的时候会优先使用已有的容器,而不是重新创建容器。
这个时候需要先将原先的image镜像进行手动删除,再打包操作:
[root@izwz9ic9ggky8kub9x1ptuz springboot-docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
springboot-docker latest 86f32bd9257f 4 hours ago 128MB
<none> <none> 411616c3d7f7 2 days ago 679MB
<none> <none> 77044e3ad9c2 2 days ago 679MB
<none> <none> 5d9328dd1aca 2 days ago 679MB
springbootmongodocker_springappserver latest 36237acf08e1 3 days ago 695MB
删除镜像的命令:
docker rmi 【镜像id】
此时再重新进行docker-compose指令的打包操作即可:
docker-compose up
启动之后,可以通过docker-compose自带的一些指令来进行操作,常用的一些指令我都归纳在了下边:
docker-compose [Command]
Commands:
build 构建或重建服务
bundle 从compose配置文件中产生一个docker绑定
config 验证并查看compose配置文件
create 创建服务
down 停止并移除容器、网络、镜像和数据卷
events 从容器中接收实时的事件
exec 在一个运行中的容器上执行一个命令
help 获取命令的帮助信息
images 列出所有镜像
kill 通过发送SIGKILL信号来停止指定服务的容器
logs 从容器中查看服务日志输出
pause 暂停服务
port 打印绑定的公共端口
ps 列出所有运行中的容器
pull 拉取并下载指定服务镜像
push Push service images
restart 重启YAML文件中定义的服务
rm 删除指定已经停止服务的容器
run 在一个服务上执行一条命令
scale 设置指定服务运行容器的个数
start 在容器中启动指定服务
stop 停止已运行的服务
top 显示各个服务容器内运行的进程
unpause 恢复容器服务
up 创建并启动容器
version 显示Docker-Compose版本信息
最后对相应的接口做检测:
相关的完整代码我已经上传到了gitee地址,如果有需要的朋友可以前往进行下载。
代码地址:https://gitee.com/IdeaHome_admin/wfw
实践完毕之后,你可能会觉得有了docker-compose之后,对于多个docker容器来进行管理显得就特别轻松了。
但是往往现实中并没有这么简单,docker-compose存在着一个弊端,那就是不能做跨机器之间的docker容器进行管理。
因此随者技术的发展,后边也慢慢出现了一种叫做Kubernetes的技术。Kubernetes(俗称k8s)是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。
Kubernetes这类技术对于小白来说入门的难度较高,后边可能会抽空专门来写一篇适合小白阅读的k8s入门文章。