{"id":40385,"date":"2023-09-18T18:20:26","date_gmt":"2024-03-08T03:31:44","guid":{"rendered":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82\/"},"modified":"2024-05-04T00:23:07","modified_gmt":"2024-05-03T16:23:07","slug":"%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82","status":"publish","type":"post","link":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82\/","title":{"rendered":"\u4f7f\u7528Docker+Spring Boot+MySQL+Flyway+Spock\u642d\u5efa\u5168\u5bb9\u5668\u57fa\u7840\u7684\u672c\u5730\u5f00\u53d1\u73af\u5883"},"content":{"rendered":"<p>KINTO Technologies\u8475\u30bf\u306e2021\u5e74\u306e\u30a2\u30c9\u30d9\u30f3\u30c8\u30ab\u30ec\u30f3\u30c0\u30fc- Qiita\u306e14\u65e5\u76ee\u306e\u8a18\u4e8b\u3067\u3059\u3002<\/p>\n<h1>\u5199\u8fd9\u7bc7\u6587\u7ae0\u7684\u539f\u56e0<\/h1>\n<p>\u6700\u521d\u7684\u76ee\u6807\u662f\u8ba9\u540e\u7aef\u5f00\u53d1\u4eba\u5458\u4e86\u89e3\u5e76\u4f53\u9a8cSpock\u6570\u636e\u9a71\u52a8\u6d4b\u8bd5\u7684\u4f18\u52bf\u3002<\/p>\n<p>\u7136\u800c\uff0c\u5728\u5efa\u7acb\u64b0\u5199\u8be5\u6587\u7ae0\u6240\u9700\u7684\u73af\u5883\u65f6\uff0c\u6211\u5f00\u59cb\u8ba4\u4e3a\u524d\u9762\u7684\u5e94\u7528\u7a0b\u5e8f\u5f00\u53d1\u73af\u5883\u5efa\u7acb\u8fc7\u7a0b\u4e5f\u662f\u6709\u9700\u6c42\u7684\uff0c\u751a\u81f3\u66f4\u591a\u4eba\u9700\u8981\u4f5c\u4e3a\u77e5\u8bc6\u6765\u5b66\u4e60\u3002<\/p>\n<p>\u7531\u4e8e\u6211\u4eec\u516c\u53f8\u7684\u7cfb\u7edf\u5e73\u53f0\u57fa\u672c\u4e0a\u90fd\u662f\u57fa\u4e8e\u4e91\u7aef\u5bb9\u5668\u670d\u52a1\u7684\uff0c\u56e0\u6b64\u5373\u4f7f\u662f\u5728\u672c\u5730\u5f00\u53d1\uff0c\u4e5f\u4e0d\u9700\u8981\u5728Mac\u4e0a\u5b89\u88c5MySQL\uff0c\u800c\u662f\u6700\u597d\u4ece\u4e00\u5f00\u59cb\u5c31\u91c7\u7528\u5bb9\u5668\u5316\u6784\u5efa\u7684\u65b9\u5f0f\uff0c\u8fd9\u6837\u4e0d\u4ec5\u5728DevOps\u65b9\u9762\u66f4\u5bb9\u6613\u8fdb\u884c\u8fc1\u79fb\u3002<\/p>\n<p>\u57fa\u4e8e\u4ee5\u4e0a\u7684\u539f\u56e0\uff0c\u6211\u4eec\u51b3\u5b9a\u6700\u7ec8\u5c06\u6587\u7ae0\u7684\u4e3b\u9898\u8bbe\u5b9a\u4e3a\u6240\u8ff0\u6807\u9898\u3002<\/p>\n<h1>\u5e0c\u671b\u6709\u4eba\u613f\u610f\u9605\u8bfb<\/h1>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u3046\u3063\u304b\u308a\u30af\u30e9\u30a6\u30c9\u30d9\u30fc\u30b9\u306e\u4f1a\u793e\u306b\u8ee2\u8077\u3057\u3061\u3083\u3063\u305f\u30aa\u30f3\u30d7\u30ec\u7cfb\u30a8\u30f3\u30b8\u30cb\u30a2<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u958b\u767a\u306f\u30b3\u30f3\u30c6\u30ca\u30d9\u30fc\u30b9\u3067\u3067\u304d\u3066\u308b\u3051\u3069\u30c6\u30b9\u30c8\u307e\u3067\u30b3\u30f3\u30c6\u30ca\u30d9\u30fc\u30b9\u3067\u52d5\u304b\u3057\u305f\u3044<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u3092\u66f8\u3051\u3068\u8a00\u308f\u308c\u308b\u3051\u3069JUnit\u66f8\u304d\u3065\u3089\u3044\u3057\u8aad\u307f\u3065\u3089\u3044\u3057\u306a\u3093\u304b\u30a4\u30e4<\/ul>\n<h1>\u73af\u5883<\/h1>\n<p>MacBook Pro<br \/>\nDocker Desktop for Mac 4.9.1 (\u5df2\u7ecf\u4ed8\u8d39\u5566&#8230;)<br \/>\nJava 17<br \/>\nGradle 7.3.1<br \/>\nSpring Boot 2.6.1<br \/>\nGroovy 3.0<br \/>\nSpock 2.0<br \/>\nTestcontainers 1.16.2<\/p>\n<h1>\u793a\u4f8b\u6e90\u4ee3\u7801<\/h1>\n<p>&nbsp;<\/p>\n<h2>\u884c\u52a8\u6982\u8ff0<\/h2>\n<h3>REST API -&gt; REST \u5e94\u7528\u7a0b\u5e8f\u63a5\u53e3<\/h3>\n<pre class=\"post-pre\"><code>http:\/\/localhost:8080\/v1\/cars\/{price}\r\n<\/code><\/pre>\n<p>\u60a8\u53ef\u4ee5\u83b7\u53d6\u5230KINTO\u6700\u53d7\u6b22\u8fce\u8f66\u578b\uff08\u622a\u81f32021\u5e7412\u6708\uff09\u4e2d\uff0c\u6307\u5b9a\u4ef7\u683c\u6216\u66f4\u4f4e\u6708\u79df\u8d39\u7684\u8f66\u8f86\u6570\u636e\u3002<\/p>\n<p>\u3010KINTO\u3011\u662f\u4ece\u4e30\u7530\u63a8\u51fa\u7684\u4e00\u79cd\u6c7d\u8f66\u8ba2\u9605\u670d\u52a1\u3002<\/p>\n<p>\u5728MySQL\u5bb9\u5668\u7684\u8868\u4e2d\uff0c\u5b58\u653e\u7740\u4ee5\u4e0b\u7684\u6c7d\u8f66\u6570\u636e\u3002<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d405337434c4406c91882\/18-0.png\" alt=\"\u540d\u79f0\u672a\u8a2d\u5b9a2.png\" \/><\/div>\n<h3>\u8003\u8bd5\u5185\u5bb9<\/h3>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">HTTP\u30b9\u30c6\u30fc\u30bf\u30b9200\u3067\u30ec\u30b9\u30dd\u30f3\u30b9\u304c\u8fd4\u308b\u304b<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\u4fa1\u683c\u30d1\u30bf\u30fc\u30f3\u306b\u3088\u308b\u30c7\u30fc\u30bf\u99c6\u52d5\u30c6\u30b9\u30c8<\/ul>\n<h1>\u5efa\u9020\u8fc7\u7a0b<\/h1>\n<h2>\u5f00\u53d1REST API<\/h2>\n<p>Spring Boot\u7684\u7c7b\u7ed3\u6784\u770b\u8d77\u6765\u662f\u8fd9\u6837\u7684\u3002<\/p>\n<pre class=\"post-pre\"><code>.\r\n\u251c\u2500\u2500 java\r\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 com\r\n\u2502\u00a0\u00a0     \u2514\u2500\u2500 example\r\n\u2502\u00a0\u00a0         \u2514\u2500\u2500 restapitestbyspock\r\n\u2502\u00a0\u00a0             \u251c\u2500\u2500 RestApiTestBySpockApplication.java\r\n\u2502\u00a0\u00a0             \u251c\u2500\u2500 application\r\n\u2502\u00a0\u00a0             \u2502\u00a0\u00a0 \u2514\u2500\u2500 CarController.java\r\n\u2502\u00a0\u00a0             \u251c\u2500\u2500 domain\r\n\u2502\u00a0\u00a0             \u2502\u00a0\u00a0 \u251c\u2500\u2500 model\r\n\u2502\u00a0\u00a0             \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 Car.java\r\n\u2502\u00a0\u00a0             \u2502\u00a0\u00a0 \u251c\u2500\u2500 repository\r\n\u2502\u00a0\u00a0             \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 CarRepository.java\r\n\u2502\u00a0\u00a0             \u2502\u00a0\u00a0 \u2514\u2500\u2500 service\r\n\u2502\u00a0\u00a0             \u2502\u00a0\u00a0     \u2514\u2500\u2500 CarService.java\r\n\u2502\u00a0\u00a0             \u2514\u2500\u2500 infrastructure\r\n\u2502\u00a0\u00a0                 \u251c\u2500\u2500 entity\r\n\u2502\u00a0\u00a0                 \u2502\u00a0\u00a0 \u2514\u2500\u2500 CarEntity.java\r\n\u2502\u00a0\u00a0                 \u2514\u2500\u2500 repository\r\n\u2502\u00a0\u00a0                     \u251c\u2500\u2500 CarJpaRepository.java\r\n\u2502\u00a0\u00a0                     \u2514\u2500\u2500 CarRepositoryImpl.java\r\n\u2514\u2500\u2500 resources\r\n    \u251c\u2500\u2500 application.yml\r\n    \u251c\u2500\u2500 static\r\n    \u2514\u2500\u2500 templates\r\n<\/code><\/pre>\n<p>\u4f7f\u7528Spring Data JPA\u7684\u67e5\u8be2\u751f\u6210\u529f\u80fd\uff0c\u83b7\u53d6\u201c\u6309\u7167\u4ef7\u683c\u5347\u5e8f\u6392\u5217\u7684\u6708\u79df\u8f66\u8f86\u6570\u636e\u201d\uff0c\u8fd9\u4e9b\u8f66\u8f86\u7684\u4ef7\u683c\u5c0f\u4e8e\u7b49\u4e8e\u6307\u5b9a\u7684\u4ef7\u683c\u6216\u66f4\u4f4e\u3002<\/p>\n<p>\u7531\u4e8e\u6ca1\u6709\u5176\u4ed6\u7279\u522b\u68d8\u624b\u7684\u4e8b\u60c5\uff0c\u6240\u4ee5\u6211\u53ea\u4f1a\u7b80\u5355\u5730\u8d34\u4e0a\u4ee3\u7801\u3002<\/p>\n<h3>\u57df\u540d\u5c42<\/h3>\n<pre class=\"post-pre\"><code><span class=\"nd\">@Data<\/span>\r\n<span class=\"nd\">@Builder<\/span>\r\n<span class=\"kd\">public<\/span> <span class=\"kd\">class<\/span> <span class=\"nc\">Car<\/span> <span class=\"o\">{<\/span>\r\n    <span class=\"nd\">@Id<\/span>\r\n    <span class=\"kd\">private<\/span> <span class=\"nc\">Integer<\/span> <span class=\"n\">id<\/span><span class=\"o\">;<\/span>\r\n    <span class=\"kd\">private<\/span> <span class=\"nc\">String<\/span> <span class=\"n\">name<\/span><span class=\"o\">;<\/span>\r\n    <span class=\"kd\">private<\/span> <span class=\"nc\">Integer<\/span> <span class=\"n\">price<\/span><span class=\"o\">;<\/span>\r\n<span class=\"o\">}<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"kd\">public<\/span> <span class=\"kd\">interface<\/span> <span class=\"nc\">CarRepository<\/span> <span class=\"o\">{<\/span>\r\n\r\n    <span class=\"nc\">List<\/span><span class=\"o\">&lt;<\/span><span class=\"nc\">Car<\/span><span class=\"o\">&gt;<\/span> <span class=\"nf\">findByPriceLessThanEqualOrderByPriceAsc<\/span><span class=\"o\">(<\/span><span class=\"nc\">Integer<\/span> <span class=\"n\">price<\/span><span class=\"o\">);<\/span>\r\n\r\n<span class=\"o\">}<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"nd\">@Service<\/span>\r\n<span class=\"nd\">@RequiredArgsConstructor<\/span>\r\n<span class=\"kd\">public<\/span> <span class=\"kd\">class<\/span> <span class=\"nc\">CarService<\/span> <span class=\"o\">{<\/span>\r\n\r\n    <span class=\"nd\">@NonNull<\/span>\r\n    <span class=\"kd\">private<\/span> <span class=\"kd\">final<\/span> <span class=\"nc\">CarRepository<\/span> <span class=\"n\">carRepository<\/span><span class=\"o\">;<\/span>\r\n\r\n    <span class=\"kd\">public<\/span> <span class=\"nc\">List<\/span><span class=\"o\">&lt;<\/span><span class=\"nc\">Car<\/span><span class=\"o\">&gt;<\/span> <span class=\"nf\">findByPriceLessThanEqualOrderByPriceAsc<\/span><span class=\"o\">(<\/span><span class=\"nc\">Integer<\/span> <span class=\"n\">price<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">return<\/span> <span class=\"k\">this<\/span><span class=\"o\">.<\/span><span class=\"na\">carRepository<\/span><span class=\"o\">.<\/span><span class=\"na\">findByPriceLessThanEqualOrderByPriceAsc<\/span><span class=\"o\">(<\/span><span class=\"n\">price<\/span><span class=\"o\">);<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n<span class=\"o\">}<\/span>\r\n\r\n<\/code><\/pre>\n<h3>\u57fa\u790e\u8a2d\u65bd\u5c64<\/h3>\n<pre class=\"post-pre\"><code><span class=\"nd\">@Data<\/span>\r\n<span class=\"nd\">@Builder<\/span>\r\n<span class=\"nd\">@NoArgsConstructor<\/span>\r\n<span class=\"nd\">@AllArgsConstructor<\/span>\r\n<span class=\"nd\">@Entity<\/span>\r\n<span class=\"nd\">@Table<\/span><span class=\"o\">(<\/span><span class=\"n\">name<\/span> <span class=\"o\">=<\/span> <span class=\"s\">\"cars\"<\/span><span class=\"o\">)<\/span>\r\n<span class=\"kd\">public<\/span> <span class=\"kd\">class<\/span> <span class=\"nc\">CarEntity<\/span> <span class=\"o\">{<\/span>\r\n    <span class=\"nd\">@Id<\/span>\r\n    <span class=\"kd\">private<\/span> <span class=\"nc\">Integer<\/span> <span class=\"n\">id<\/span><span class=\"o\">;<\/span>\r\n    <span class=\"kd\">private<\/span> <span class=\"nc\">String<\/span> <span class=\"n\">name<\/span><span class=\"o\">;<\/span>\r\n    <span class=\"kd\">private<\/span> <span class=\"nc\">Integer<\/span> <span class=\"n\">price<\/span><span class=\"o\">;<\/span>\r\n\r\n    <span class=\"kd\">public<\/span> <span class=\"nc\">Car<\/span> <span class=\"nf\">toDomainCar<\/span><span class=\"o\">()<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">return<\/span> <span class=\"nc\">Car<\/span><span class=\"o\">.<\/span><span class=\"na\">builder<\/span><span class=\"o\">()<\/span>\r\n                <span class=\"o\">.<\/span><span class=\"na\">id<\/span><span class=\"o\">(<\/span><span class=\"k\">this<\/span><span class=\"o\">.<\/span><span class=\"na\">id<\/span><span class=\"o\">)<\/span>\r\n                <span class=\"o\">.<\/span><span class=\"na\">name<\/span><span class=\"o\">(<\/span><span class=\"k\">this<\/span><span class=\"o\">.<\/span><span class=\"na\">name<\/span><span class=\"o\">)<\/span>\r\n                <span class=\"o\">.<\/span><span class=\"na\">price<\/span><span class=\"o\">(<\/span><span class=\"k\">this<\/span><span class=\"o\">.<\/span><span class=\"na\">price<\/span><span class=\"o\">)<\/span>\r\n                <span class=\"o\">.<\/span><span class=\"na\">build<\/span><span class=\"o\">();<\/span>\r\n    <span class=\"o\">}<\/span>\r\n<span class=\"o\">}<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"kd\">public<\/span> <span class=\"kd\">interface<\/span> <span class=\"nc\">CarJpaRepository<\/span> <span class=\"kd\">extends<\/span> <span class=\"nc\">JpaRepository<\/span><span class=\"o\">&lt;<\/span><span class=\"nc\">CarEntity<\/span><span class=\"o\">,<\/span> <span class=\"nc\">Integer<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">{<\/span>\r\n    <span class=\"nc\">List<\/span><span class=\"o\">&lt;<\/span><span class=\"nc\">CarEntity<\/span><span class=\"o\">&gt;<\/span> <span class=\"nf\">findByPriceLessThanEqualOrderByPriceAsc<\/span><span class=\"o\">(<\/span><span class=\"nc\">Integer<\/span> <span class=\"n\">price<\/span><span class=\"o\">);<\/span>\r\n<span class=\"o\">}<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"nd\">@Repository<\/span>\r\n<span class=\"nd\">@RequiredArgsConstructor<\/span>\r\n<span class=\"kd\">public<\/span> <span class=\"kd\">class<\/span> <span class=\"nc\">CarRepositoryImpl<\/span> <span class=\"kd\">implements<\/span> <span class=\"nc\">CarRepository<\/span> <span class=\"o\">{<\/span>\r\n\r\n    <span class=\"nd\">@NonNull<\/span>\r\n    <span class=\"kd\">private<\/span> <span class=\"kd\">final<\/span> <span class=\"nc\">CarJpaRepository<\/span> <span class=\"n\">carJpaRepository<\/span><span class=\"o\">;<\/span>\r\n\r\n    <span class=\"nd\">@Override<\/span>\r\n    <span class=\"kd\">public<\/span> <span class=\"nc\">List<\/span><span class=\"o\">&lt;<\/span><span class=\"nc\">Car<\/span><span class=\"o\">&gt;<\/span> <span class=\"nf\">findByPriceLessThanEqualOrderByPriceAsc<\/span><span class=\"o\">(<\/span><span class=\"nc\">Integer<\/span> <span class=\"n\">price<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">return<\/span> <span class=\"k\">this<\/span><span class=\"o\">.<\/span><span class=\"na\">carJpaRepository<\/span><span class=\"o\">.<\/span><span class=\"na\">findByPriceLessThanEqualOrderByPriceAsc<\/span><span class=\"o\">(<\/span><span class=\"n\">price<\/span><span class=\"o\">)<\/span>\r\n                <span class=\"o\">.<\/span><span class=\"na\">stream<\/span><span class=\"o\">().<\/span><span class=\"na\">map<\/span><span class=\"o\">(<\/span><span class=\"nl\">CarEntity:<\/span><span class=\"o\">:<\/span><span class=\"n\">toDomainCar<\/span><span class=\"o\">)<\/span>\r\n                <span class=\"o\">.<\/span><span class=\"na\">collect<\/span><span class=\"o\">(<\/span><span class=\"nc\">Collectors<\/span><span class=\"o\">.<\/span><span class=\"na\">toList<\/span><span class=\"o\">());<\/span>\r\n    <span class=\"o\">}<\/span>\r\n<span class=\"o\">}<\/span>\r\n<\/code><\/pre>\n<h3>\u5e94\u7528\u5c42<\/h3>\n<pre class=\"post-pre\"><code><span class=\"nd\">@RestController<\/span>\r\n<span class=\"nd\">@RequiredArgsConstructor<\/span>\r\n<span class=\"nd\">@RequestMapping<\/span><span class=\"o\">(<\/span><span class=\"n\">path<\/span> <span class=\"o\">=<\/span> <span class=\"s\">\"\/v1\/cars\"<\/span><span class=\"o\">)<\/span>\r\n<span class=\"kd\">public<\/span> <span class=\"kd\">class<\/span> <span class=\"nc\">CarController<\/span> <span class=\"o\">{<\/span>\r\n\r\n    <span class=\"nd\">@NonNull<\/span>\r\n    <span class=\"kd\">private<\/span> <span class=\"kd\">final<\/span> <span class=\"nc\">CarService<\/span> <span class=\"n\">carService<\/span><span class=\"o\">;<\/span>\r\n\r\n    <span class=\"nd\">@GetMapping<\/span><span class=\"o\">(<\/span><span class=\"s\">\"\/{price}\"<\/span><span class=\"o\">)<\/span>\r\n    <span class=\"nd\">@ResponseStatus<\/span><span class=\"o\">(<\/span><span class=\"nc\">HttpStatus<\/span><span class=\"o\">.<\/span><span class=\"na\">OK<\/span><span class=\"o\">)<\/span>\r\n    <span class=\"kd\">public<\/span> <span class=\"nc\">List<\/span><span class=\"o\">&lt;<\/span><span class=\"nc\">Car<\/span><span class=\"o\">&gt;<\/span> <span class=\"nf\">findByPriceLessThanEqualOrderByPriceAsc<\/span><span class=\"o\">(<\/span><span class=\"nd\">@PathVariable<\/span><span class=\"o\">(<\/span><span class=\"s\">\"price\"<\/span><span class=\"o\">)<\/span> <span class=\"nc\">Integer<\/span> <span class=\"n\">price<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">return<\/span> <span class=\"k\">this<\/span><span class=\"o\">.<\/span><span class=\"na\">carService<\/span><span class=\"o\">.<\/span><span class=\"na\">findByPriceLessThanEqualOrderByPriceAsc<\/span><span class=\"o\">(<\/span><span class=\"n\">price<\/span><span class=\"o\">);<\/span>\r\n    <span class=\"o\">}<\/span>\r\n<span class=\"o\">}<\/span>\r\n<\/code><\/pre>\n<h2>\u5b89\u88c5Docker Desktop<\/h2>\n<p>\u73b0\u5728\u8ba9\u6211\u4eec\u5f00\u59cb\u51c6\u5907\u5bb9\u5668\u5316\u7684\u5de5\u4f5c\u5427\u3002<\/p>\n<p>Docker\u684c\u9762\u7248\u9002\u7528\u4e8eMac\u548cWindows\u7cfb\u7edf<\/p>\n<p>\u8bf7\u6839\u636e\u4e0a\u8ff0\u5185\u5bb9\u9009\u62e9\u5e76\u4e0b\u8f7d\u3001\u5b89\u88c5\u5230\u60a8\u7684\u8bbe\u5907\u4e2d\u3002<\/p>\n<h2>Docker\u5bb9\u5668\u7684\u914d\u7f6e\u3002<\/h2>\n<p>\u914d\u7f6e\u6587\u4ef6\u7684\u7ed3\u6784\u5982\u4e0b\u6240\u793a\u3002<\/p>\n<pre class=\"post-pre\"><code>.\r\n\u251c\u2500\u2500 docker\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 flyway\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 conf\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 flyway.conf\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 sql\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0     \u251c\u2500\u2500 V1.0.0__schema.sql\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0     \u2514\u2500\u2500 V1.1.0__data.sql\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 log\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 mysql\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0     \u2514\u2500\u2500 mysqld.log\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 mysql\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 Dockerfile\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 conf.d\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0     \u2514\u2500\u2500 my.cnf\r\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 spring\r\n\u2502\u00a0\u00a0     \u2514\u2500\u2500 Dockerfile\r\n\u251c\u2500\u2500 docker-compose.yml\r\n<\/code><\/pre>\n<p>\u6211\u5011\u5c07\u4ee5Docker Compose\u70ba\u57fa\u790e\u9032\u884c\u914d\u7f6e\u6587\u4ef6\u7684\u5be6\u73fe\u3002\u6211\u5011\u60f3\u8981\u5efa\u7acb\u4e00\u500b\u7d50\u69cb\uff0c\u5f9eSpring Boot\u9023\u63a5\u5230MySQL\u4e26\u4f7f\u7528Flyway\u9032\u884c\u9077\u79fb\u7ba1\u7406\uff0c\u56e0\u6b64\u6211\u5011\u9700\u8981\u4ee5\u4e0b3\u500b\u5bb9\u5668\u6620\u50cf\u3002<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">MySQL<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">Flyway<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">Spring Boot<\/ul>\n<pre class=\"post-pre\"><code><span class=\"na\">version<\/span><span class=\"pi\">:<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">3.7\"<\/span>\r\n<span class=\"na\">services<\/span><span class=\"pi\">:<\/span>\r\n  <span class=\"na\">dbserver<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">container_name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">mysql-db<\/span>\r\n    <span class=\"na\">build<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">context<\/span><span class=\"pi\">:<\/span> <span class=\"s\">.\/docker\/mysql<\/span>\r\n      <span class=\"na\">dockerfile<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Dockerfile<\/span>\r\n    <span class=\"na\">image<\/span><span class=\"pi\">:<\/span> <span class=\"s\">chig1215\/mysql:latest<\/span>\r\n    <span class=\"na\">environment<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">MYSQL_ROOT_PASSWORD<\/span><span class=\"pi\">:<\/span> <span class=\"s\">root<\/span>\r\n      <span class=\"na\">MYSQL_USER<\/span><span class=\"pi\">:<\/span> <span class=\"s\">chig1215<\/span>\r\n      <span class=\"na\">MYSQL_PASSWORD<\/span><span class=\"pi\">:<\/span> <span class=\"s\">chig1215<\/span>\r\n      <span class=\"na\">MYSQL_DATABASE<\/span><span class=\"pi\">:<\/span> <span class=\"s\">kinto<\/span>\r\n    <span class=\"na\">restart<\/span><span class=\"pi\">:<\/span> <span class=\"s\">always<\/span>\r\n    <span class=\"na\">command<\/span><span class=\"pi\">:<\/span> <span class=\"s\">--default-authentication-plugin=mysql_native_password<\/span>\r\n    <span class=\"na\">ports<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">3306:3306\"<\/span>\r\n    <span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">.\/docker\/mysql\/conf.d:\/etc\/mysql\/conf.d<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">.\/docker\/log\/mysql:\/var\/log\/mysql<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">mysql_db:\/var\/lib\/mysql<\/span>\r\n  <span class=\"na\">flyway-repair<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">container_name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">flyway-repair<\/span>\r\n    <span class=\"na\">image<\/span><span class=\"pi\">:<\/span> <span class=\"s\">flyway\/flyway<\/span>\r\n    <span class=\"na\">command<\/span><span class=\"pi\">:<\/span> <span class=\"s\">repair<\/span>\r\n    <span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">.\/docker\/flyway\/conf:\/flyway\/conf<\/span>\r\n    <span class=\"na\">depends_on<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">dbserver<\/span>\r\n  <span class=\"na\">flyway-migration<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">container_name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">flyway-migration<\/span>\r\n    <span class=\"na\">image<\/span><span class=\"pi\">:<\/span> <span class=\"s\">flyway\/flyway<\/span>\r\n    <span class=\"na\">command<\/span><span class=\"pi\">:<\/span> <span class=\"s\">-url=jdbc:mysql:\/\/dbserver -schemas=kinto -user=chig1215 -password=chig1215 -connectRetries=60 migrate<\/span>\r\n    <span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">.\/docker\/flyway\/conf:\/flyway\/conf<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">.\/docker\/flyway\/sql:\/flyway\/sql<\/span>\r\n    <span class=\"na\">depends_on<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">flyway-repair<\/span>\r\n  <span class=\"na\">spring<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">container_name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">spring-app<\/span>\r\n    <span class=\"na\">build<\/span><span class=\"pi\">:<\/span> <span class=\"s\">.\/docker\/spring<\/span>\r\n    <span class=\"na\">depends_on<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">flyway-migration<\/span>\r\n    <span class=\"na\">ports<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">8080:8080\"<\/span>\r\n    <span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">.:\/app<\/span>\r\n    <span class=\"na\">environment<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">spring.datasource.driverClassName<\/span><span class=\"pi\">:<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">com.mysql.cj.jdbc.Driver\"<\/span>\r\n      <span class=\"na\">spring.datasource.url<\/span><span class=\"pi\">:<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">jdbc:mysql:\/\/dbserver\/kinto\"<\/span>\r\n      <span class=\"na\">spring.datasource.username<\/span><span class=\"pi\">:<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">chig1215\"<\/span>\r\n      <span class=\"na\">spring.datasource.password<\/span><span class=\"pi\">:<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">chig1215\"<\/span>\r\n    <span class=\"na\">working_dir<\/span><span class=\"pi\">:<\/span> <span class=\"s\">\/app<\/span>\r\n    <span class=\"na\">command<\/span><span class=\"pi\">:<\/span> <span class=\"s\">sh -c \"java -jar .\/build\/libs\/rest-api-test-by-spock-0.0.1-SNAPSHOT.jar\"<\/span>\r\n<span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\r\n  <span class=\"na\">mysql_db<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">driver<\/span><span class=\"pi\">:<\/span> <span class=\"s\">local<\/span>\r\n<\/code><\/pre>\n<p>\u6211\u5011\u5c07\u901a\u904e\u8a3b\u89e3\u4f86\u89e3\u91cb\u6bcf\u500b\u5bb9\u5668\u7684\u8a2d\u7f6e\u3002<\/p>\n<h3>MySQL\uff1aMySQL is a relational database management system. MySQL\u662f\u4e00\u79cd\u5173\u7cfb\u578b\u6570\u636e\u5e93\u7ba1\u7406\u7cfb\u7edf\u3002<\/h3>\n<pre class=\"post-pre\"><code>  <span class=\"na\">dbserver<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">container_name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">mysql-db<\/span>  <span class=\"c1\"># \u30b3\u30f3\u30c6\u30ca\u540d\uff08Docker Desktop\u4e0a\u306f\u3053\u306e\u540d\u524d\u3067\u8868\u793a\u3055\u308c\u308b\uff09<\/span>\r\n    <span class=\"na\">build<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">context<\/span><span class=\"pi\">:<\/span> <span class=\"s\">.\/docker\/mysql<\/span> <span class=\"c1\"># Dockerfile\u3092\u542b\u3080\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3078\u306e\u30d1\u30b9<\/span>\r\n      <span class=\"na\">dockerfile<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Dockerfile<\/span>  <span class=\"c1\"># Dockerfile\u540d<\/span>\r\n    <span class=\"na\">image<\/span><span class=\"pi\">:<\/span> <span class=\"s\">chig1215\/mysql:latest<\/span> <span class=\"c1\"># \u30a4\u30e1\u30fc\u30b8\u540d<\/span>\r\n    <span class=\"na\">environment<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">MYSQL_ROOT_PASSWORD<\/span><span class=\"pi\">:<\/span> <span class=\"s\">root<\/span> <span class=\"c1\"># \u74b0\u5883\u5909\u6570\uff08root\u30e6\u30fc\u30b6\u306e\u30d1\u30b9\u30ef\u30fc\u30c9\uff09<\/span>\r\n      <span class=\"na\">MYSQL_USER<\/span><span class=\"pi\">:<\/span> <span class=\"s\">chig1215<\/span>      <span class=\"c1\"># \u74b0\u5883\u5909\u6570\uff08\u30e6\u30fc\u30b6\uff09<\/span>\r\n      <span class=\"na\">MYSQL_PASSWORD<\/span><span class=\"pi\">:<\/span> <span class=\"s\">chig1215<\/span>  <span class=\"c1\"># \u74b0\u5883\u5909\u6570\uff08\u30d1\u30b9\u30ef\u30fc\u30c9\uff09<\/span>\r\n      <span class=\"na\">MYSQL_DATABASE<\/span><span class=\"pi\">:<\/span> <span class=\"s\">kinto<\/span>     <span class=\"c1\"># \u74b0\u5883\u5909\u6570\uff08\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u540d\uff09<\/span>\r\n    <span class=\"na\">restart<\/span><span class=\"pi\">:<\/span> <span class=\"s\">always<\/span> <span class=\"c1\"># \u518d\u8d77\u52d5\u30dd\u30ea\u30b7\u30fc<\/span>\r\n    <span class=\"na\">command<\/span><span class=\"pi\">:<\/span> <span class=\"s\">--default-authentication-plugin=mysql_native_password<\/span>  <span class=\"c1\"># mysql_native_password \u3092\u4f7f\u7528\u3057\u305f\u30cd\u30a4\u30c6\u30a3\u30d6\u8a8d\u8a3c<\/span>\r\n    <span class=\"na\">ports<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">3306:3306\"<\/span> <span class=\"c1\"># \u30dd\u30fc\u30c8\u30de\u30c3\u30d4\u30f3\u30b0<\/span>\r\n    <span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">.\/docker\/mysql\/conf.d:\/etc\/mysql\/conf.d<\/span> <span class=\"c1\"># mysql.conf\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u30de\u30c3\u30d4\u30f3\u30b0<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">.\/docker\/log\/mysql:\/var\/log\/mysql<\/span>       <span class=\"c1\"># mysqld.log\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u30de\u30c3\u30d4\u30f3\u30b0<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">mysql_db:\/var\/lib\/mysql<\/span>                 <span class=\"c1\"># \u30c7\u30fc\u30bf\u6c38\u7d9a\u5316\u30dc\u30ea\u30e5\u30fc\u30e0\u306e\u30de\u30c3\u30d4\u30f3\u30b0<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"c1\"># DB\u306e\u6c38\u7d9a\u5316\u5148<\/span>\r\n<span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\r\n  <span class=\"na\">mysql_db<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">driver<\/span><span class=\"pi\">:<\/span> <span class=\"s\">local<\/span>\r\n<\/code><\/pre>\n<h3>\u98de\u8d8a<\/h3>\n<pre class=\"post-pre\"><code>  <span class=\"na\">flyway-repair<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">container_name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">flyway-repair<\/span> <span class=\"c1\"># \u30b3\u30f3\u30c6\u30ca\u540d\uff08Docker Desktop\u4e0a\u306f\u3053\u306e\u540d\u524d\u3067\u8868\u793a\u3055\u308c\u308b\uff09<\/span>\r\n    <span class=\"na\">image<\/span><span class=\"pi\">:<\/span> <span class=\"s\">flyway\/flyway<\/span>          <span class=\"c1\"># \u30a4\u30e1\u30fc\u30b8\u540d<\/span>\r\n    <span class=\"na\">command<\/span><span class=\"pi\">:<\/span> <span class=\"s\">repair<\/span>               <span class=\"c1\"># \u524d\u56de\u306eSQL\u30a8\u30e9\u30fc\u89e3\u6d88\uff08\u30b5\u30f3\u30d7\u30eb\u30b3\u30f3\u30c6\u30f3\u30c4\u306e\u305f\u3081\u3002\u672c\u756a\u7a3c\u50cd\u30a2\u30d7\u30ea\u3067\u306f\u4e0d\u8981\uff09<\/span>\r\n    <span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">.\/docker\/flyway\/conf:\/flyway\/conf<\/span> <span class=\"c1\"># flyway.conf\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u30de\u30c3\u30d4\u30f3\u30b0<\/span>\r\n    <span class=\"na\">depends_on<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">dbserver<\/span>  <span class=\"c1\"># MySQL\u30b3\u30f3\u30c6\u30ca\u304c\u8d77\u52d5\u3057\u305f\u5f8c\u306b\u8d77\u52d5\u3055\u305b\u308b<\/span>\r\n  <span class=\"na\">flyway-migration<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">container_name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">flyway-migration<\/span>  <span class=\"c1\"># \u30b3\u30f3\u30c6\u30ca\u540d\uff08Docker Desktop\u4e0a\u306f\u3053\u306e\u540d\u524d\u3067\u8868\u793a\u3055\u308c\u308b\uff09<\/span>\r\n    <span class=\"na\">image<\/span><span class=\"pi\">:<\/span> <span class=\"s\">flyway\/flyway<\/span>              <span class=\"c1\"># \u30a4\u30e1\u30fc\u30b8\u540d<\/span>\r\n    <span class=\"c1\"># MySQL\u306e\u63a5\u7d9a\u5148\u3092\u6307\u5b9a\u3057\u3066\u30de\u30a4\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u3092\u5b9f\u884c\u3059\u308b\uff08host:port\u90e8\u5206\u306f\u30b3\u30f3\u30c6\u30ca\u540d\u3092\u6307\u5b9a\u3059\u308b\uff09<\/span>\r\n    <span class=\"na\">command<\/span><span class=\"pi\">:<\/span> <span class=\"s\">-url=jdbc:mysql:\/\/dbserver -schemas=kinto -user=chig1215 -password=chig1215 -connectRetries=60 migrate<\/span>\r\n    <span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">.\/docker\/flyway\/conf:\/flyway\/conf<\/span> <span class=\"c1\"># flyway.conf\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u30de\u30c3\u30d4\u30f3\u30b0<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">.\/docker\/flyway\/sql:\/flyway\/sql<\/span>   <span class=\"c1\"># \u30de\u30a4\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3SQL\u30d5\u30a1\u30a4\u30eb\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u30de\u30c3\u30d4\u30f3\u30b0<\/span>\r\n    <span class=\"na\">depends_on<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">flyway-repair<\/span> <span class=\"c1\"># repair\u304c\u5b8c\u4e86\u3057\u305f\u5f8c\u306b\u8d77\u52d5\u3055\u305b\u308b<\/span>\r\n<\/code><\/pre>\n<h3>\u6625\u5b63\u542f\u52a8<\/h3>\n<pre class=\"post-pre\"><code>  <span class=\"na\">spring<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">container_name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">spring-app<\/span>  <span class=\"c1\"># \u30b3\u30f3\u30c6\u30ca\u540d\uff08Docker Desktop\u4e0a\u306f\u3053\u306e\u540d\u524d\u3067\u8868\u793a\u3055\u308c\u308b\uff09<\/span>\r\n    <span class=\"na\">build<\/span><span class=\"pi\">:<\/span> <span class=\"s\">.\/docker\/spring<\/span>      <span class=\"c1\"># Dockerfile\u3092\u542b\u3080\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3078\u306e\u30d1\u30b9<\/span>\r\n    <span class=\"na\">depends_on<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">flyway-migration<\/span>        <span class=\"c1\"># \u30de\u30a4\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u304c\u5b8c\u4e86\u3057\u305f\u5f8c\u306b\u8d77\u52d5\u3055\u305b\u308b<\/span>\r\n    <span class=\"na\">ports<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">8080:8080\"<\/span>             <span class=\"c1\"># \u30dd\u30fc\u30c8\u30de\u30c3\u30d4\u30f3\u30b0<\/span>\r\n    <span class=\"na\">volumes<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s\">.:\/app<\/span>                  <span class=\"c1\"># \u30dc\u30ea\u30e5\u30fc\u30e0\u30de\u30c3\u30d4\u30f3\u30b0<\/span>\r\n    <span class=\"na\">environment<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"c1\"># MySQL\u306e\u63a5\u7d9a\u8a2d\u5b9a<\/span>\r\n      <span class=\"na\">spring.datasource.driverClassName<\/span><span class=\"pi\">:<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">com.mysql.cj.jdbc.Driver\"<\/span>\r\n      <span class=\"na\">spring.datasource.url<\/span><span class=\"pi\">:<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">jdbc:mysql:\/\/dbserver\/kinto\"<\/span>  <span class=\"c1\"># host:port\u90e8\u5206\u306f\u30b3\u30f3\u30c6\u30ca\u540d\u3092\u6307\u5b9a\u3059\u308b<\/span>\r\n      <span class=\"na\">spring.datasource.username<\/span><span class=\"pi\">:<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">chig1215\"<\/span>\r\n      <span class=\"na\">spring.datasource.password<\/span><span class=\"pi\">:<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">chig1215\"<\/span>\r\n    <span class=\"na\">working_dir<\/span><span class=\"pi\">:<\/span> <span class=\"s\">\/app<\/span> <span class=\"c1\"># \u4f5c\u696d\u30c7\u30a3\u30ec\u30af\u30c8\u30ea<\/span>\r\n    <span class=\"c1\"># jar\u304b\u3089\u8d77\u52d5<\/span>\r\n    <span class=\"na\">command<\/span><span class=\"pi\">:<\/span> <span class=\"s\">sh -c \"java -jar .\/build\/libs\/rest-api-test-by-spock-0.0.1-SNAPSHOT.jar\"<\/span>\r\n<\/code><\/pre>\n<p>\u8bf7\u53c2\u8003\u6bcf\u4e2a\u5bb9\u5668\u7684Dockerfile\u548cconf\u6587\u4ef6\u4e2d\u7684\u793a\u4f8b\u6e90\u4ee3\u7801\u3002<\/p>\n<h2>\u786e\u8ba4\u884c\u52a8<\/h2>\n<h3>\u5e94\u7528\u7a0b\u5e8f\u7684\u6784\u5efa<\/h3>\n<pre class=\"post-pre\"><code> $ .\/gradlew clean build\r\n<\/code><\/pre>\n<p>\u8ba9\u6211\u4eec\u786e\u8ba4\u5728build\u6587\u4ef6\u5939\u4e2d\u521b\u5efa\u4e86\u4e00\u4e2ajar\u6587\u4ef6\u3002<\/p>\n<pre class=\"post-pre\"><code>.\r\n\u251c\u2500\u2500 build\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 libs\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 rest-api-test-by-spock-0.0.1-SNAPSHOT-plain.jar\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 rest-api-test-by-spock-0.0.1-SNAPSHOT.jar\r\n<\/code><\/pre>\n<h3>\u542f\u52a8\u5bb9\u5668<\/h3>\n<pre class=\"post-pre\"><code>$ docker-compose up --build\r\n<\/code><\/pre>\n<p>\u5982\u679c\u542f\u52a8\u6210\u529f\uff0cDocker Desktop\u7684Containers\/Apps\u5e94\u8be5\u4ee5\u4ee5\u4e0b\u65b9\u5f0f\u663e\u793a\u3002<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d405337434c4406c91882\/64-0.png\" alt=\"\u540d\u79f0\u672a\u8a2d\u5b9a.png\" \/><\/div>\n<p>\u5982\u679c\u6210\u529f\u542f\u52a8\uff0c\u901a\u8fc7GET\u8bf7\u6c42REST API\u5e76\u8fd4\u56de\u5982\u4e0b\u7ed3\u679c\u3002<\/p>\n<pre class=\"post-pre\"><code>http:\/\/localhost:8080\/v1\/cars\/20000\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>[{\r\n\t\"id\": 3,\r\n\t\"name\": \"\u30eb\u30fc\u30df\u30fc\",\r\n\t\"price\": 14630\r\n}, {\r\n\t\"id\": 7,\r\n\t\"name\": \"\u30e4\u30ea\u30b92WD\",\r\n\t\"price\": 14960\r\n}, {\r\n\t\"id\": 2,\r\n\t\"name\": \"RAIZE\",\r\n\t\"price\": 16170\r\n}, {\r\n\t\"id\": 10,\r\n\t\"name\": \"\u30d7\u30ea\u30a6\u30b9\",\r\n\t\"price\": 18700\r\n}, {\r\n\t\"id\": 4,\r\n\t\"name\": \"\u30a2\u30af\u30a2\",\r\n\t\"price\": 19580\r\n}]\r\n<\/code><\/pre>\n<h3>\u505c\u6b62\u5bb9\u5668<\/h3>\n<pre class=\"post-pre\"><code>$ docker-compose down\r\n<\/code><\/pre>\n<h2>\u5c0f\u4f11\u4e00\u4e0b<\/h2>\n<p>\u5496\u5561\u4f11\u606f<\/p>\n<h2>\u8003\u8bd5\u5f00\u53d1<\/h2>\n<p>\u597d\uff0c\u7d42\u65bc\u5230\u4e86\u6700\u521d\u7684\u4e3b\u984c\uff0cSpock\u7684\u767b\u5834\u3002<\/p>\n<p>\u7531\u4e8e\u672c\u6b21\u6211\u4eec\u60f3\u8981\u4ee5\u5bb9\u5668\u4e3a\u57fa\u7840\u8fdb\u884c\u6d4b\u8bd5\uff0c\u56e0\u6b64\u6211\u4eec\u5c06\u540c\u65f6\u4f7f\u7528Testcontainers\u3002<\/p>\n<p>\u73ed\u7ea7\u6784\u6210\u662f\u8fd9\u6837\u7684\u3002<\/p>\n<pre class=\"post-pre\"><code>.\r\n\u2514\u2500\u2500 src\r\n    \u2514\u2500\u2500 test\r\n        \u251c\u2500\u2500 groovy\r\n        \u2502\u00a0\u00a0 \u2514\u2500\u2500 com\r\n        \u2502\u00a0\u00a0     \u2514\u2500\u2500 example\r\n        \u2502\u00a0\u00a0         \u2514\u2500\u2500 restapitestbyspock\r\n        \u2502\u00a0\u00a0             \u2514\u2500\u2500 application\r\n        \u2502\u00a0\u00a0                 \u2514\u2500\u2500 CarControllerTest.groovy\r\n        \u251c\u2500\u2500 java\r\n        \u2502\u00a0\u00a0 \u2514\u2500\u2500 com\r\n        \u2502\u00a0\u00a0     \u2514\u2500\u2500 example\r\n        \u2502\u00a0\u00a0         \u2514\u2500\u2500 restapitestbyspock\r\n        \u2502\u00a0\u00a0             \u2514\u2500\u2500 helper\r\n        \u2502\u00a0\u00a0                 \u2514\u2500\u2500 test\r\n        \u2502\u00a0\u00a0                     \u2514\u2500\u2500 MySQLContainerContextInitializer.java\r\n        \u2514\u2500\u2500 resources\r\n<\/code><\/pre>\n<h3>\u6dfb\u52a0\u5fc5\u8981\u7684\u5e93\u6765\u6784\u5efa\u6d4b\u8bd5\u7248\u672c<\/h3>\n<p>\u6211\u4f1a\u5728build.gradle\u6587\u4ef6\u4e2d\u6309\u7167\u4ee5\u4e0b\u65b9\u5f0f\u8fdb\u884c\u8ffd\u52a0\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"n\">plugins<\/span> <span class=\"o\">{<\/span>\r\n    <span class=\"n\">id<\/span> <span class=\"s1\">'org.springframework.boot'<\/span> <span class=\"n\">version<\/span> <span class=\"s1\">'2.6.1'<\/span>\r\n    <span class=\"n\">id<\/span> <span class=\"s1\">'io.spring.dependency-management'<\/span> <span class=\"n\">version<\/span> <span class=\"s1\">'1.0.11.RELEASE'<\/span>\r\n    <span class=\"n\">id<\/span> <span class=\"s1\">'java'<\/span>\r\n    <span class=\"n\">id<\/span> <span class=\"s1\">'groovy'<\/span> <span class=\"c1\">\/\/ \u8ffd\u8a18\uff08Spock\u306fGroovy\u3067\u8a18\u8ff0\u3059\u308b\u305f\u3081\uff09<\/span>\r\n<span class=\"o\">}<\/span>\r\n\r\n<span class=\"n\">group<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">'com.example'<\/span>\r\n<span class=\"n\">version<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">'0.0.1-SNAPSHOT'<\/span>\r\n<span class=\"n\">sourceCompatibility<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">'17'<\/span>\r\n\r\n<span class=\"n\">configurations<\/span> <span class=\"o\">{<\/span>\r\n    <span class=\"n\">compileOnly<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"n\">extendsFrom<\/span> <span class=\"n\">annotationProcessor<\/span>\r\n    <span class=\"o\">}<\/span>\r\n<span class=\"o\">}<\/span>\r\n\r\n<span class=\"k\">repositories<\/span> <span class=\"o\">{<\/span>\r\n    <span class=\"n\">maven<\/span> <span class=\"o\">{<\/span> <span class=\"n\">url<\/span> <span class=\"s1\">'https:\/\/repo.spring.io\/release'<\/span> <span class=\"o\">}<\/span>\r\n    <span class=\"n\">mavenCentral<\/span><span class=\"o\">()<\/span>\r\n<span class=\"o\">}<\/span>\r\n\r\n<span class=\"k\">dependencies<\/span> <span class=\"o\">{<\/span>\r\n    <span class=\"n\">implementation<\/span> <span class=\"s1\">'org.springframework.boot:spring-boot-starter-data-rest'<\/span>\r\n    <span class=\"n\">implementation<\/span> <span class=\"s1\">'org.springframework.boot:spring-boot-starter-web'<\/span>\r\n    <span class=\"n\">implementation<\/span> <span class=\"s1\">'org.springframework.boot:spring-boot-starter-jdbc'<\/span>\r\n    <span class=\"n\">implementation<\/span> <span class=\"s1\">'org.springframework.boot:spring-boot-starter-data-jpa'<\/span>\r\n    <span class=\"n\">implementation<\/span> <span class=\"s1\">'javax.persistence:javax.persistence-api'<\/span>\r\n    <span class=\"n\">compileOnly<\/span> <span class=\"s1\">'org.projectlombok:lombok'<\/span>\r\n    <span class=\"n\">runtimeOnly<\/span> <span class=\"s1\">'mysql:mysql-connector-java'<\/span>\r\n    <span class=\"n\">annotationProcessor<\/span> <span class=\"s1\">'org.springframework.boot:spring-boot-configuration-processor'<\/span>\r\n    <span class=\"n\">annotationProcessor<\/span> <span class=\"s1\">'org.projectlombok:lombok'<\/span>\r\n    <span class=\"c1\">\/\/ \u3053\u3053\u304b\u3089\u8ffd\u8a18<\/span>\r\n    <span class=\"n\">testImplementation<\/span> <span class=\"s1\">'org.springframework.boot:spring-boot-test:2.6.2'<\/span>\r\n    <span class=\"n\">testImplementation<\/span> <span class=\"s1\">'org.springframework.boot:spring-boot-starter-test:2.6.2'<\/span>\r\n    <span class=\"n\">testImplementation<\/span> <span class=\"s1\">'org.spockframework:spock-core:2.0-groovy-3.0'<\/span>\r\n    <span class=\"n\">testImplementation<\/span> <span class=\"s1\">'org.spockframework:spock-spring:2.0-groovy-3.0'<\/span>\r\n    <span class=\"n\">testImplementation<\/span> <span class=\"s1\">'org.testcontainers:testcontainers:1.16.2'<\/span>\r\n    <span class=\"n\">testImplementation<\/span> <span class=\"s1\">'org.testcontainers:mysql:1.16.2'<\/span>\r\n    <span class=\"n\">testImplementation<\/span> <span class=\"s1\">'com.jayway.jsonpath:json-path:2.6.0'<\/span>\r\n<span class=\"o\">}<\/span>\r\n\r\n<span class=\"n\">test<\/span> <span class=\"o\">{<\/span>\r\n    <span class=\"n\">useJUnitPlatform<\/span><span class=\"o\">()<\/span>\r\n<span class=\"o\">}<\/span>\r\n\r\n<span class=\"n\">bootBuildImage<\/span> <span class=\"o\">{<\/span>\r\n    <span class=\"n\">builder<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">'paketobuildpacks\/builder:tiny'<\/span>\r\n    <span class=\"n\">environment<\/span> <span class=\"o\">=<\/span> <span class=\"o\">[<\/span><span class=\"s1\">'BP_NATIVE_IMAGE'<\/span><span class=\"o\">:<\/span> <span class=\"s1\">'true'<\/span><span class=\"o\">]<\/span>\r\n<span class=\"o\">}<\/span>\r\n\r\n<span class=\"c1\">\/\/ \u8ffd\u8a18\uff08Flyway\u306e\u30de\u30a4\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3SQL\u3092\u30c6\u30b9\u30c8\u30ea\u30bd\u30fc\u30b9\u3068\u3057\u3066\u4f7f\u3044\u305f\u3044\u305f\u3081\uff09<\/span>\r\n<span class=\"k\">sourceSets<\/span><span class=\"o\">.<\/span><span class=\"na\">test<\/span> <span class=\"o\">{<\/span>\r\n    <span class=\"n\">resources<\/span><span class=\"o\">.<\/span><span class=\"na\">srcDirs<\/span> <span class=\"o\">=<\/span> <span class=\"o\">[<\/span><span class=\"s2\">\"src\/test\/resources\"<\/span><span class=\"o\">,<\/span> <span class=\"s2\">\"docker\"<\/span><span class=\"o\">]<\/span>\r\n<span class=\"o\">}<\/span>\r\n<\/code><\/pre>\n<h3>\u7528\u4e8e\u6d4b\u8bd5\u6570\u636e\u5e93\u5bb9\u5668\u914d\u7f6e\u7684\u8f85\u52a9\u7c7b<\/h3>\n<pre class=\"post-pre\"><code><span class=\"nd\">@SuppressWarnings<\/span><span class=\"o\">({<\/span><span class=\"s\">\"rawtypes\"<\/span><span class=\"o\">,<\/span> <span class=\"s\">\"unchecked\"<\/span><span class=\"o\">})<\/span>\r\n<span class=\"kd\">public<\/span> <span class=\"kd\">class<\/span> <span class=\"nc\">MySQLContainerContextInitializer<\/span>\r\n        <span class=\"kd\">implements<\/span> <span class=\"nc\">ApplicationContextInitializer<\/span><span class=\"o\">&lt;<\/span><span class=\"nc\">ConfigurableApplicationContext<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">{<\/span>\r\n\r\n    <span class=\"kd\">private<\/span> <span class=\"kd\">static<\/span> <span class=\"kd\">final<\/span> <span class=\"nc\">Logger<\/span> <span class=\"no\">LOGGER<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">LoggerFactory<\/span><span class=\"o\">.<\/span><span class=\"na\">getLogger<\/span><span class=\"o\">(<\/span><span class=\"nc\">MySQLContainerContextInitializer<\/span><span class=\"o\">.<\/span><span class=\"na\">class<\/span><span class=\"o\">);<\/span>\r\n\r\n    <span class=\"kd\">private<\/span> <span class=\"kd\">static<\/span> <span class=\"kd\">final<\/span> <span class=\"nc\">MySQLContainer<\/span> <span class=\"no\">MYSQL<\/span> <span class=\"o\">=<\/span>\r\n            <span class=\"k\">new<\/span> <span class=\"nf\">MySQLContainer<\/span><span class=\"o\">(<\/span><span class=\"s\">\"mysql:latest\"<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\r\n                <span class=\"o\">{<\/span>\r\n                    <span class=\"n\">withDatabaseName<\/span><span class=\"o\">(<\/span><span class=\"s\">\"kinto\"<\/span><span class=\"o\">);<\/span>\r\n                    <span class=\"n\">withUsername<\/span><span class=\"o\">(<\/span><span class=\"s\">\"chig1215\"<\/span><span class=\"o\">);<\/span>\r\n                    <span class=\"n\">withPassword<\/span><span class=\"o\">(<\/span><span class=\"s\">\"chig1215\"<\/span><span class=\"o\">);<\/span>\r\n                    <span class=\"n\">withExposedPorts<\/span><span class=\"o\">(<\/span><span class=\"mi\">3306<\/span><span class=\"o\">);<\/span>\r\n                    <span class=\"n\">withLogConsumer<\/span><span class=\"o\">(<\/span><span class=\"k\">new<\/span> <span class=\"nc\">Slf4jLogConsumer<\/span><span class=\"o\">(<\/span><span class=\"no\">LOGGER<\/span><span class=\"o\">));<\/span>\r\n                    <span class=\"n\">withClasspathResourceMapping<\/span><span class=\"o\">(<\/span>\r\n                            <span class=\"s\">\"mysql\/conf.d\"<\/span><span class=\"o\">,<\/span>\r\n                            <span class=\"s\">\"\/etc\/mysql\/conf.d\"<\/span><span class=\"o\">,<\/span> <span class=\"nc\">BindMode<\/span><span class=\"o\">.<\/span><span class=\"na\">READ_ONLY<\/span><span class=\"o\">);<\/span>\r\n                    <span class=\"n\">withClasspathResourceMapping<\/span><span class=\"o\">(<\/span>\r\n                            <span class=\"s\">\"flyway\/sql\"<\/span><span class=\"o\">,<\/span>\r\n                            <span class=\"s\">\"\/docker-entrypoint-initdb.d\"<\/span><span class=\"o\">,<\/span> <span class=\"nc\">BindMode<\/span><span class=\"o\">.<\/span><span class=\"na\">READ_ONLY<\/span><span class=\"o\">);<\/span>\r\n                <span class=\"o\">}<\/span>\r\n            <span class=\"o\">};<\/span>\r\n\r\n    <span class=\"kd\">static<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"no\">MYSQL<\/span><span class=\"o\">.<\/span><span class=\"na\">start<\/span><span class=\"o\">();<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n    <span class=\"nd\">@Override<\/span>\r\n    <span class=\"kd\">public<\/span> <span class=\"kt\">void<\/span> <span class=\"nf\">initialize<\/span><span class=\"o\">(<\/span><span class=\"nc\">ConfigurableApplicationContext<\/span> <span class=\"n\">applicationContext<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"nc\">TestPropertyValues<\/span><span class=\"o\">.<\/span><span class=\"na\">of<\/span><span class=\"o\">(<\/span><span class=\"s\">\"spring.datasource.url=\"<\/span> <span class=\"o\">+<\/span> <span class=\"no\">MYSQL<\/span><span class=\"o\">.<\/span><span class=\"na\">getJdbcUrl<\/span><span class=\"o\">())<\/span>\r\n                <span class=\"o\">.<\/span><span class=\"na\">applyTo<\/span><span class=\"o\">(<\/span><span class=\"n\">applicationContext<\/span><span class=\"o\">.<\/span><span class=\"na\">getEnvironment<\/span><span class=\"o\">());<\/span>\r\n    <span class=\"o\">}<\/span>\r\n<span class=\"o\">}<\/span>\r\n<\/code><\/pre>\n<p>\u4e3a\u4e86\u5728Spring\u542f\u52a8\u65f6\u6267\u884c\u64cd\u4f5c\uff0c\u6211\u4eec\u5c06\u521b\u5efa\u4e00\u4e2a\u5b9e\u73b0ApplicationContextInitializer\u63a5\u53e3\u7684\u7c7b\u3002<\/p>\n<p>\u63a5\u7d9a\u4fe1\u606f\u4e0edocker-compose.yml\u6587\u4ef6\u4e2d\u7684\u8bbe\u7f6e\u76f8\u540c\u3002<br \/>\nmysql.conf\u76ee\u5f55\u548c\u8fc1\u79fbSQL\u76ee\u5f55\u5728\u5c42\u6b21\u4e0a\u662f\u4e00\u6837\u7684\u3002<\/p>\n<pre class=\"post-pre\"><code>.\r\n\u251c\u2500\u2500 docker\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 flyway\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 conf\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 flyway.conf\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 sql\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0     \u251c\u2500\u2500 V1.0.0__schema.sql\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0     \u2514\u2500\u2500 V1.1.0__data.sql\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 mysql\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 Dockerfile\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 conf.d\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0     \u2514\u2500\u2500 my.cnf\r\n<\/code><\/pre>\n<p>\u6211\u5728\u8fd9\u91cc\u7684\u8bdd\uff0c\u53ea\u80fd\u5c06\u5b83\u590d\u5236\u5230src\/test\/resources\u5417\uff1f\u6211\u4e00\u76f4\u5728\u8003\u8651\u8fd9\u4e2a\u95ee\u9898\uff0c\u4f46\u8fc7\u4e86\u4e00\u4f1a\u513f\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"c1\">\/\/ \u8ffd\u8a18\uff08Flyway\u306e\u30de\u30a4\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3SQL\u3092\u30c6\u30b9\u30c8\u30ea\u30bd\u30fc\u30b9\u3068\u3057\u3066\u4f7f\u3044\u305f\u3044\u305f\u3081\uff09<\/span>\r\n<span class=\"k\">sourceSets<\/span><span class=\"o\">.<\/span><span class=\"na\">test<\/span> <span class=\"o\">{<\/span>\r\n    <span class=\"n\">resources<\/span><span class=\"o\">.<\/span><span class=\"na\">srcDirs<\/span> <span class=\"o\">=<\/span> <span class=\"o\">[<\/span><span class=\"s2\">\"src\/test\/resources\"<\/span><span class=\"o\">,<\/span> <span class=\"s2\">\"docker\"<\/span><span class=\"o\">]<\/span>\r\n<span class=\"o\">}<\/span>\r\n<\/code><\/pre>\n<p>\u8fd9\u4e2a\u610f\u8bc6\u5230\u4e86\u4e00\u4e2a\u597d\u5904\uff0c\u987a\u5229\u5730\u5c06\u6587\u4ef6\u901a\u8fc7\u5e94\u7528\u548c\u6d4b\u8bd5\u96c6\u4e2d\u7ba1\u7406\u4e86\u8d77\u6765\u3002<\/p>\n<h3>\u5199\u8bd5\u5377<\/h3>\n<pre class=\"post-pre\"><code><span class=\"nd\">@SpringBootTest<\/span>\r\n<span class=\"nd\">@AutoConfigureMockMvc<\/span>\r\n<span class=\"nd\">@ContextConfiguration<\/span><span class=\"o\">(<\/span><span class=\"n\">initializers<\/span> <span class=\"o\">=<\/span> <span class=\"o\">[<\/span><span class=\"n\">MySQLContainerContextInitializer<\/span><span class=\"o\">.<\/span><span class=\"na\">class<\/span><span class=\"o\">])<\/span>\r\n<span class=\"kd\">class<\/span> <span class=\"nc\">CarControllerTest<\/span> <span class=\"kd\">extends<\/span> <span class=\"n\">Specification<\/span> <span class=\"o\">{<\/span>\r\n    <span class=\"nd\">@Autowired<\/span>\r\n    <span class=\"n\">MockMvc<\/span> <span class=\"n\">mockMvc<\/span>\r\n\r\n    <span class=\"nd\">@Unroll<\/span>\r\n    <span class=\"kt\">def<\/span> <span class=\"s2\">\"FindByPriceLessThanEqualOrderByPriceAsc HttpStatus\"<\/span><span class=\"o\">()<\/span> <span class=\"o\">{<\/span>\r\n\r\n        <span class=\"nl\">when:<\/span>\r\n        <span class=\"kt\">def<\/span> <span class=\"n\">result<\/span> <span class=\"o\">=<\/span>\r\n                <span class=\"n\">mockMvc<\/span><span class=\"o\">.<\/span><span class=\"na\">perform<\/span><span class=\"o\">(<\/span><span class=\"n\">MockMvcRequestBuilders<\/span><span class=\"o\">.<\/span><span class=\"na\">get<\/span><span class=\"o\">(<\/span><span class=\"s2\">\"\/v1\/cars\/30000\"<\/span><span class=\"o\">))<\/span>\r\n                        <span class=\"o\">.<\/span><span class=\"na\">andReturn<\/span><span class=\"o\">().<\/span><span class=\"na\">getResponse<\/span><span class=\"o\">()<\/span>\r\n\r\n        <span class=\"nl\">then:<\/span>\r\n        <span class=\"n\">result<\/span><span class=\"o\">.<\/span><span class=\"na\">getStatus<\/span><span class=\"o\">()<\/span> <span class=\"o\">==<\/span> <span class=\"n\">HttpStatus<\/span><span class=\"o\">.<\/span><span class=\"na\">OK<\/span><span class=\"o\">.<\/span><span class=\"na\">value<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n    <span class=\"nd\">@Unroll<\/span>\r\n    <span class=\"kt\">def<\/span> <span class=\"s2\">\"FindByPriceLessThanEqualOrderByPriceAsc Data Pattern\"<\/span><span class=\"o\">()<\/span> <span class=\"o\">{<\/span>\r\n\r\n        <span class=\"nl\">expect:<\/span>\r\n        <span class=\"n\">mockMvc<\/span><span class=\"o\">.<\/span><span class=\"na\">perform<\/span><span class=\"o\">(<\/span><span class=\"n\">MockMvcRequestBuilders<\/span><span class=\"o\">.<\/span><span class=\"na\">get<\/span><span class=\"o\">(<\/span><span class=\"s2\">\"\/v1\/cars\/\"<\/span> <span class=\"o\">+<\/span> <span class=\"n\">price<\/span><span class=\"o\">))<\/span>\r\n                <span class=\"o\">.<\/span><span class=\"na\">andExpect<\/span><span class=\"o\">(<\/span><span class=\"n\">MockMvcResultMatchers<\/span><span class=\"o\">.<\/span><span class=\"na\">jsonPath<\/span><span class=\"o\">(<\/span><span class=\"s2\">\"\\$.*\"<\/span><span class=\"o\">,<\/span> <span class=\"n\">Matchers<\/span><span class=\"o\">.<\/span><span class=\"na\">hasSize<\/span><span class=\"o\">(<\/span><span class=\"n\">size<\/span><span class=\"o\">)))<\/span>\r\n\r\n        <span class=\"nl\">where:<\/span>\r\n        <span class=\"n\">price<\/span>   <span class=\"o\">||<\/span> <span class=\"n\">size<\/span>\r\n        <span class=\"s2\">\"50000\"<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">10<\/span>\r\n        <span class=\"s2\">\"40000\"<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">10<\/span>\r\n        <span class=\"s2\">\"30000\"<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">9<\/span>\r\n        <span class=\"s2\">\"20000\"<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">5<\/span>\r\n        <span class=\"s2\">\"15000\"<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">2<\/span>\r\n        <span class=\"s2\">\"10000\"<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span>\r\n\r\n    <span class=\"o\">}<\/span>\r\n\r\n<span class=\"o\">}<\/span>\r\n<\/code><\/pre>\n<p>@ContextConfiguration(initializers = [MySQLContainerContextInitializer.class]) &#8211; \u91c7\u7528 @ContextConfiguration \u6ce8\u89e3\uff0c\u5e76\u6307\u5b9a\u521d\u59cb\u5316\u5668\u4e3a MySQLContainerContextInitializer.class\u3002<\/p>\n<p>\u901a\u8fc7\u6307\u5b9a\u5148\u524d\u521b\u5efa\u7684Helper\u7c7b\uff0c\u542f\u52a8\u5e76\u8bbe\u7f6e\u5bb9\u5668\u7684\u8fde\u63a5\u4fe1\u606f\u3002<br \/>\n\u8fd9\u6837\uff0c\u5c31\u53ef\u4ee5\u4ece\u6d4b\u8bd5\u4ee3\u7801\u4e2d\u8bbf\u95ee\u7528\u4e8e\u6d4b\u8bd5\u7684MySQL\u5bb9\u5668\u4e86\u3002<\/p>\n<p>\u8003\u8bd5\u7684\u5185\u5bb9\u5305\u62ec\u4ee5\u4e0b\u4e24\u9879\u3002<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">HTTP\u30b9\u30c6\u30fc\u30bf\u30b9200\u3067\u30ec\u30b9\u30dd\u30f3\u30b9\u304c\u8fd4\u308b\u304b\uff08FindByPriceLessThanEqualOrderByPriceAsc HttpStatus\uff09<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\u4fa1\u683c\u30d1\u30bf\u30fc\u30f3\u306b\u3088\u308b\u30c7\u30fc\u30bf\u99c6\u52d5\u30c6\u30b9\u30c8\uff08FindByPriceLessThanEqualOrderByPriceAsc Data Pattern\uff09<\/ul>\n<p>\u6211\u652f\u6301Spock\u7684\u6700\u5927\u7406\u7531\u65e0\u7591\u662f\u5176\u201c\u6613\u8bfb\u6027\u201d\u3002<\/p>\n<pre class=\"post-pre\"><code>        <span class=\"nl\">expect:<\/span>\r\n        <span class=\"n\">mockMvc<\/span><span class=\"o\">.<\/span><span class=\"na\">perform<\/span><span class=\"o\">(<\/span><span class=\"n\">MockMvcRequestBuilders<\/span><span class=\"o\">.<\/span><span class=\"na\">get<\/span><span class=\"o\">(<\/span><span class=\"s2\">\"\/v1\/cars\/\"<\/span> <span class=\"o\">+<\/span> <span class=\"n\">price<\/span><span class=\"o\">))<\/span>\r\n                <span class=\"o\">.<\/span><span class=\"na\">andExpect<\/span><span class=\"o\">(<\/span><span class=\"n\">MockMvcResultMatchers<\/span><span class=\"o\">.<\/span><span class=\"na\">jsonPath<\/span><span class=\"o\">(<\/span><span class=\"s2\">\"\\$.*\"<\/span><span class=\"o\">,<\/span> <span class=\"n\">Matchers<\/span><span class=\"o\">.<\/span><span class=\"na\">hasSize<\/span><span class=\"o\">(<\/span><span class=\"n\">size<\/span><span class=\"o\">)))<\/span>\r\n\r\n        <span class=\"nl\">where:<\/span>\r\n        <span class=\"n\">price<\/span>   <span class=\"o\">||<\/span> <span class=\"n\">size<\/span>\r\n        <span class=\"s2\">\"50000\"<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">10<\/span>\r\n        <span class=\"s2\">\"40000\"<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">10<\/span>\r\n        <span class=\"s2\">\"30000\"<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">9<\/span>\r\n        <span class=\"s2\">\"20000\"<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">5<\/span>\r\n        <span class=\"s2\">\"15000\"<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">2<\/span>\r\n        <span class=\"s2\">\"10000\"<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span>\r\n<\/code><\/pre>\n<p>\u5c31\u7b97\u6ca1\u6709\u8bc4\u8bba\uff0c\u4f60\u4e5f\u77e5\u9053\u5728\u6d4b\u8bd5\u4ec0\u4e48\u5427\u3002\u6211\u4eec\u5c06\u4f20\u9012\u7ed9REST API\u7684\u4ef7\u683c\u6570\u636e\u6a21\u5f0f\u5b9a\u4e49\u4e3aprice\uff0c\u5e76\u5c06\u5e94\u8fd4\u56de\u7684\u6c7d\u8f66\u5bf9\u8c61\u6570\u5b9a\u4e49\u4e3a\u6bcf\u4e2a\u6570\u636e\u6a21\u5f0f\u7684size\u3002<\/p>\n<h2>\u901a\u8fc7\u8003\u8bd5<\/h2>\n<pre class=\"post-pre\"><code> $ .\/gradlew clean test\r\n<\/code><\/pre>\n<p>\u6d4b\u8bd5\u7ed3\u679c\u5c06\u663e\u793a\u5728\u63a7\u5236\u53f0\u4e0a\uff0c\u5e76\u4e14\u8fd8\u4f1a\u751f\u6210\u62a5\u544a\uff0c\u6240\u4ee5\u8ba9\u6211\u4eec\u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u4e00\u4e0b\u3002<\/p>\n<pre class=\"post-pre\"><code>.\r\n\u251c\u2500\u2500 build\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 reports\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 tests\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0     \u2514\u2500\u2500 test\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0         \u251c\u2500\u2500 classes\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0         \u2502\u00a0\u00a0 \u2514\u2500\u2500 com.example.restapitestbyspock.application.CarControllerTest.html\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0         \u251c\u2500\u2500 css\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0         \u2502\u00a0\u00a0 \u251c\u2500\u2500 base-style.css\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0         \u2502\u00a0\u00a0 \u2514\u2500\u2500 style.css\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0         \u251c\u2500\u2500 index.html\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0         \u251c\u2500\u2500 js\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0         \u2502\u00a0\u00a0 \u2514\u2500\u2500 report.js\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0         \u2514\u2500\u2500 packages\r\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0             \u2514\u2500\u2500 com.example.restapitestbyspock.application.html\r\n\r\n<\/code><\/pre>\n<h3>\u6240\u6709\u7684\u6d4b\u8bd5\u90fd\u53d6\u5f97\u4e86\u6210\u529f\u3002<\/h3>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d405337434c4406c91882\/102-0.png\" alt=\"\u540d\u79f03\u8a2d\u5b9a\uff13.png\" \/><\/div>\n<h3>\u6d4b\u8bd5\u5931\u8d25\u6709<\/h3>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d405337434c4406c91882\/104-0.png\" alt=\"\u540d\u79f0\u672a\u8a2d\u5b9a4.png\" \/><\/div>\n<h1>\u8bf7\u67e5\u9605\u76f8\u5173\u8d44\u6599<\/h1>\n<p>https:\/\/matsuand.github.io\/docs.docker.jp.onthefly\/reference\/ \u7684\u4e2d\u6587\u5185\u5bb9\u5982\u4e0b\uff1a<br \/>\nhttps:\/\/www.testcontainers.org\/ \u7684\u4e2d\u6587\u5185\u5bb9\u5982\u4e0b\uff1a<\/p>\n<h1>\u6700\u540e<\/h1>\n<p>\u60a8\u5bf9\u6b64\u6709\u4f55\u770b\u6cd5\uff1f<br \/>\n\u5982\u679c\u80fd\u5bf9\u5927\u5bb6\u7a0d\u6709\u5e2e\u52a9\u5c31\u975e\u5e38\u8363\u5e78\u4e86\u3002<\/p>\n<p>\u6211\u4eec\u516c\u53f8\u76ee\u524d\u6b63\u5728\u8fdb\u884c\u4e30\u7530\u6c7d\u8f66\u7684\u8ba2\u9605\u670d\u52a1\u201cKINTO\u201d\u7b49\u9879\u76ee\u7684\u4f01\u5212\u548c\u5f00\u53d1\uff0c\u5e76\u6b63\u5728\u62db\u8058\u5de5\u7a0b\u5e08\u3002<br \/>\nKINTO Technologies \u516c\u53f8\u7f51\u7ad9<\/p>\n","protected":false},"excerpt":{"rendered":"<p>KINTO Technologies\u8475\u30bf\u306e2021\u5e74\u306e\u30a2\u30c9\u30d9\u30f3\u30c8\u30ab\u30ec\u30f3\u30c0\u30fc- Qiita\u306e14\u65e5\u76ee\u306e\u8a18\u4e8b\u3067\u3059\u3002 [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-40385","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v21.5 (Yoast SEO v21.5) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>\u4f7f\u7528Docker+Spring Boot+MySQL+Flyway+Spock\u642d\u5efa\u5168\u5bb9\u5668\u57fa\u7840\u7684\u672c\u5730\u5f00\u53d1\u73af\u5883 - Blog - Silicon Cloud<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528dockerspring-bootmysqlflywayspock\u642d\u5efa\u5168\u5bb9\u5668\u57fa\u7840\u7684\u672c\u5730\u5f00\u53d1\u73af\u5883\u3002\/\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\u4f7f\u7528Docker+Spring Boot+MySQL+Flyway+Spock\u642d\u5efa\u5168\u5bb9\u5668\u57fa\u7840\u7684\u672c\u5730\u5f00\u53d1\u73af\u5883\" \/>\n<meta property=\"og:description\" content=\"KINTO Technologies\u8475\u30bf\u306e2021\u5e74\u306e\u30a2\u30c9\u30d9\u30f3\u30c8\u30ab\u30ec\u30f3\u30c0\u30fc- Qiita\u306e14\u65e5\u76ee\u306e\u8a18\u4e8b\u3067\u3059\u3002 [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528dockerspring-bootmysqlflywayspock\u642d\u5efa\u5168\u5bb9\u5668\u57fa\u7840\u7684\u672c\u5730\u5f00\u53d1\u73af\u5883\u3002\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog - Silicon Cloud\" \/>\n<meta property=\"article:published_time\" content=\"2024-03-08T03:31:44+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-05-03T16:23:07+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d405337434c4406c91882\/18-0.png\" \/>\n<meta name=\"author\" content=\"\u79d1, \u9896\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"\u79d1, \u9896\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82\/\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82\/\",\"name\":\"\u4f7f\u7528Docker+Spring Boot+MySQL+Flyway+Spock\u642d\u5efa\u5168\u5bb9\u5668\u57fa\u7840\u7684\u672c\u5730\u5f00\u53d1\u73af\u5883 - Blog - Silicon Cloud\",\"isPartOf\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\"},\"datePublished\":\"2024-03-08T03:31:44+00:00\",\"dateModified\":\"2024-05-03T16:23:07+00:00\",\"author\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/8ca01ba7f7362ad4edb7da206a12f29e\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82\/#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.silicloud.com\/zh\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u4f7f\u7528Docker+Spring Boot+MySQL+Flyway+Spock\u642d\u5efa\u5168\u5bb9\u5668\u57fa\u7840\u7684\u672c\u5730\u5f00\u53d1\u73af\u5883\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/\",\"name\":\"Blog - Silicon Cloud\",\"description\":\"\",\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/8ca01ba7f7362ad4edb7da206a12f29e\",\"name\":\"\u79d1, \u9896\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8a6fb3cc7ba2f69d2189ba532aec4633ea7ed75ac0af162ec367cb3abc0fb2af?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8a6fb3cc7ba2f69d2189ba532aec4633ea7ed75ac0af162ec367cb3abc0fb2af?s=96&d=mm&r=g\",\"caption\":\"\u79d1, \u9896\"},\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/author\/keying\/\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82\/#local-main-organization-logo\",\"url\":\"\",\"contentUrl\":\"\",\"caption\":\"Blog - Silicon Cloud\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"\u4f7f\u7528Docker+Spring Boot+MySQL+Flyway+Spock\u642d\u5efa\u5168\u5bb9\u5668\u57fa\u7840\u7684\u672c\u5730\u5f00\u53d1\u73af\u5883 - Blog - Silicon Cloud","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528dockerspring-bootmysqlflywayspock\u642d\u5efa\u5168\u5bb9\u5668\u57fa\u7840\u7684\u672c\u5730\u5f00\u53d1\u73af\u5883\u3002\/","og_locale":"zh_CN","og_type":"article","og_title":"\u4f7f\u7528Docker+Spring Boot+MySQL+Flyway+Spock\u642d\u5efa\u5168\u5bb9\u5668\u57fa\u7840\u7684\u672c\u5730\u5f00\u53d1\u73af\u5883","og_description":"KINTO Technologies\u8475\u30bf\u306e2021\u5e74\u306e\u30a2\u30c9\u30d9\u30f3\u30c8\u30ab\u30ec\u30f3\u30c0\u30fc- Qiita\u306e14\u65e5\u76ee\u306e\u8a18\u4e8b\u3067\u3059\u3002 [&hellip;]","og_url":"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528dockerspring-bootmysqlflywayspock\u642d\u5efa\u5168\u5bb9\u5668\u57fa\u7840\u7684\u672c\u5730\u5f00\u53d1\u73af\u5883\u3002\/","og_site_name":"Blog - Silicon Cloud","article_published_time":"2024-03-08T03:31:44+00:00","article_modified_time":"2024-05-03T16:23:07+00:00","og_image":[{"url":"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d405337434c4406c91882\/18-0.png"}],"author":"\u79d1, \u9896","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"\u79d1, \u9896","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"6 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82\/","url":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82\/","name":"\u4f7f\u7528Docker+Spring Boot+MySQL+Flyway+Spock\u642d\u5efa\u5168\u5bb9\u5668\u57fa\u7840\u7684\u672c\u5730\u5f00\u53d1\u73af\u5883 - Blog - Silicon Cloud","isPartOf":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website"},"datePublished":"2024-03-08T03:31:44+00:00","dateModified":"2024-05-03T16:23:07+00:00","author":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/8ca01ba7f7362ad4edb7da206a12f29e"},"breadcrumb":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82\/#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.silicloud.com\/zh\/blog\/"},{"@type":"ListItem","position":2,"name":"\u4f7f\u7528Docker+Spring Boot+MySQL+Flyway+Spock\u642d\u5efa\u5168\u5bb9\u5668\u57fa\u7840\u7684\u672c\u5730\u5f00\u53d1\u73af\u5883"}]},{"@type":"WebSite","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website","url":"https:\/\/www.silicloud.com\/zh\/blog\/","name":"Blog - Silicon Cloud","description":"","inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/8ca01ba7f7362ad4edb7da206a12f29e","name":"\u79d1, \u9896","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8a6fb3cc7ba2f69d2189ba532aec4633ea7ed75ac0af162ec367cb3abc0fb2af?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8a6fb3cc7ba2f69d2189ba532aec4633ea7ed75ac0af162ec367cb3abc0fb2af?s=96&d=mm&r=g","caption":"\u79d1, \u9896"},"url":"https:\/\/www.silicloud.com\/zh\/blog\/author\/keying\/"},{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8dockerspring-bootmysqlflywayspock%e6%90%ad%e5%bb%ba%e5%85%a8%e5%ae%b9%e5%99%a8%e5%9f%ba%e7%a1%80%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e3%80%82\/#local-main-organization-logo","url":"","contentUrl":"","caption":"Blog - Silicon Cloud"}]}},"_links":{"self":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/40385","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/comments?post=40385"}],"version-history":[{"count":2,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/40385\/revisions"}],"predecessor-version":[{"id":94992,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/40385\/revisions\/94992"}],"wp:attachment":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/media?parent=40385"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/categories?post=40385"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/tags?post=40385"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}