Spring BootをHerokuにデプロイするのが劇的に簡単になっている件

# はじめに
以前[herokuでspring-bootをgradleを使ってデプロイするときのコツ](http://qiita.com/gosshys/items/fa02b390b60ee3001dae)の記事で紹介したspring-bootをherokuにデプロイするやり方を書いたが、最近はコツがなくてもデプロイできるようになっていたので改めて試してみた。

# 手順
手順はHeroku公式の[Deploying Spring Boot Applications to Heroku](https://devcenter.heroku.com/articles/deploying-spring-boot-apps-to-heroku)に書いてあるとおり実施。Spring BootのプロジェクトをIntelliJから作るところだけ俺流です。

- herokuにアカウントを作る(ない人だけ)
- Heroku CLIをインストール(インストールしていない人だけ)
- Herokuにログイン
- IntelliJのSpringInitializrからSpringBootのプロジェクトを作成
- gitにコミット
- herokuにアプリケーション作成
- herokuにpush

# 環境

- Mac 10.10
- IntelliJ IDEA 2016.2

# 詳細な手順

`herokuのアカウント作成`(アプリケーションではなくHerokuのアカウントのこと)と`Heroku CLI`のインストールは割愛します。（公式ページを参考にしてください）

## Heroku CLIをつかってHerokuにログインする

```
❯❯❯ heroku login
Enter your Heroku credentials.
Email: gosshys@gmail.com
Password (typing will be hidden): 
Logged in as gosshys@gmail.com
```

## IntelliJからSpring Bootのプロジェクトを作成

- メニュー「File」->「New」->「Project」を選択
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/b775e4c3-8002-f86a-4b99-36f6682f7125.png)

- 左ペインの　「Spring Initializr」を選択して、「Next」ボタンで次へ
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/c0e5f2d6-c9c4-0001-ab79-310926bb3090.png)

- 「Type」を『Gradle Project』に変更して、「Next」ボタンで次へ(Mavenでもいい、Mavenのほうがいいかも)
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/d2973947-d39a-e28a-7b74-188c2e46df7c.png)

- 「Web」の`Web`と「Ops」の`Actuator`くらいを選択して、「Next」ボタンで次へ(`Actuator`は任意、あると便利)
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/651d6faa-54e8-015b-dd9b-11ea0f8a7b8e.png)

- デフォルトの設定でいいので、「Finish」ボタンで終了
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/404ca679-788e-f8c7-fe8f-dca754cd0bfb.png)

- Gradleの設定を聞かれるのでお好みの設定で「OK」ボタンで進む(ここでGradle入れてない人は詰まる) 
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/d3d098e7-f3dc-0a0f-a8c6-edc8768aa741.png)

- できた
![image](https://qiita-image-store.s3.amazonaws.com/0/38174/d2a91526-7bd3-1344-d523-b053f3c1d1d2.png)

## gitにコミット

これも公式ページの[Preparing a Spring Boot app for Heroku](https://devcenter.heroku.com/articles/deploying-spring-boot-apps-to-heroku#preparing-a-spring-boot-app-for-heroku)のとおりにgitにコミットする

```
~/D/g/demo ❯❯❯ git init
Initialized empty Git repository in /Users/tgoto/Develop/git/demo/.git/
~/D/g/demo ❯❯❯ git add .                                                                                                                                                                [master]
warning: CRLF will be replaced by LF in gradlew.bat.
The file will have its original line endings in your working directory.
~/D/g/demo ❯❯❯ git commit -m "first commit"                                                                                                                                             [master]
[master (root-commit) b580cc2] first commit
warning: CRLF will be replaced by LF in gradlew.bat.
The file will have its original line endings in your working directory.
 9 files changed, 345 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 build.gradle
 create mode 100644 gradle/wrapper/gradle-wrapper.jar
 create mode 100644 gradle/wrapper/gradle-wrapper.properties
 create mode 100755 gradlew
 create mode 100644 gradlew.bat
 create mode 100644 src/main/java/com/example/DemoApplication.java
 create mode 100644 src/main/resources/application.properties
 create mode 100644 src/test/java/com/example/DemoApplicationTests.java
~/D/g/demo ❯❯❯  
```

## herokuにアプリケーション作成

```
~/D/g/demo ❯❯❯ heroku create                                                                                                                                                            [master]
Creating app... done, ⬢ salty-badlands-47970
https://salty-badlands-47970.herokuapp.com/ | https://git.heroku.com/salty-badlands-47970.git
```

## herokuにpush

```
~/D/g/demo ❯❯❯ git push heroku master                                                                                                                                                   [master]
Counting objects: 23, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (23/23), 51.72 KiB | 0 bytes/s, done.
Total 23 (delta 0), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Gradle app detected
remote: -----> Spring Boot detected
remote: -----> Installing OpenJDK 1.8... done
remote: -----> Building Gradle app...
remote:        WARNING: The Gradle buildpack is currently in Beta.
remote: -----> executing ./gradlew build -x test
remote:        Downloading https://services.gradle.org/distributions/gradle-2.13-bin.zip
remote:        Unzipping /app/tmp/cache/.gradle/wrapper/dists/gradle-2.13-bin/4xsgxlfjcxvrea7akf941nvc7/gradle-2.13-bin.zip to /app/tmp/cache/.gradle/wrapper/dists/gradle-2.13-bin/4xsgxlfjcxvrea7akf941nvc7
remote:        Set executable permissions for: /app/tmp/cache/.gradle/wrapper/dists/gradle-2.13-bin/4xsgxlfjcxvrea7akf941nvc7/gradle-2.13/bin/gradle
remote:        Download https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-gradle-plugin/1.4.2.RELEASE/spring-boot-gradle-plugin-1.4.2.RELEASE.pom
・・・中略・・・
core/1.1.7/logback-core-1.1.7.jar
remote:        Download https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.21/slf4j-api-1.7.21.jar
remote:        :processResources
remote:        :classes
remote:        :findMainClass
remote:        :jar
remote:        :bootRepackage
remote:        :assemble
remote:        :check
remote:        :build
remote:        
remote:        BUILD SUCCESSFUL
remote:        
remote:        Total time: 14.244 secs
remote: -----> Discovering process types
remote:        Procfile declares types     -> (none)
remote:        Default types for buildpack -> web
remote: 
remote: -----> Compressing...
remote:        Done: 60.5M
remote: -----> Launching...
remote:        Released v3
remote:        https://salty-badlands-47970.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/salty-badlands-47970.git
 * [new branch]      master -> master
~/D/g/demo ❯❯❯  
```

### herokuのログを確認

```
~/D/g/demo ❯❯❯ heroku logs --tail                                                                                                                                                       [master]
2016-11-19T13:56:01.568716+00:00 app[api]: Release v2 created by gosshys@gmail.com
2016-11-19T13:56:01.566787+00:00 app[api]: Enable Logplex by gosshys@gmail.com
2016-11-19T13:58:44.799732+00:00 heroku[slug-compiler]: Slug compilation started
2016-11-19T13:58:44.799737+00:00 heroku[slug-compiler]: Slug compilation finished
2016-11-19T13:58:44.467345+00:00 app[api]: Scaled to web@1:Free by gosshys@gmail.com
2016-11-19T13:58:44.470909+00:00 app[api]: Deploy b580cc2 by gosshys@gmail.com
2016-11-19T13:58:44.472389+00:00 app[api]: Release v3 created by gosshys@gmail.com
2016-11-19T13:58:48.591821+00:00 heroku[web.1]: Starting process with command `java -Dserver.port=52225 $JAVA_OPTS -jar build/libs/*.jar`
2016-11-19T13:58:50.260077+00:00 app[web.1]: Create a Procfile to customize the command used to run this process: https://devcenter.heroku.com/articles/procfile
2016-11-19T13:58:50.264741+00:00 app[web.1]: Setting JAVA_TOOL_OPTIONS defaults based on dyno size. Custom settings will override them.
2016-11-19T13:58:50.268163+00:00 app[web.1]: Picked up JAVA_TOOL_OPTIONS: -Xmx350m -Xss512k -Dfile.encoding=UTF-8
2016-11-19T13:58:52.076863+00:00 app[web.1]: 
2016-11-19T13:58:52.076916+00:00 app[web.1]:   .   ____          _            __ _ _
2016-11-19T13:58:52.076979+00:00 app[web.1]:  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
2016-11-19T13:58:52.077036+00:00 app[web.1]: ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
2016-11-19T13:58:52.077087+00:00 app[web.1]:  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
2016-11-19T13:58:52.077144+00:00 app[web.1]:   '  |____| .__|_| |_|_| |_\__, | / / / /
2016-11-19T13:58:52.077198+00:00 app[web.1]:  =========|_|==============|___/=/_/_/_/
2016-11-19T13:58:52.079909+00:00 app[web.1]:  :: Spring Boot ::        (v1.4.2.RELEASE)
2016-11-19T13:58:52.079980+00:00 app[web.1]: 
2016-11-19T13:58:52.269726+00:00 app[web.1]: 2016-11-19 13:58:52.264  INFO 4 --- [           main] com.example.DemoApplication              : Starting DemoApplication on 25aad326-8a96-43bf-8b22-edd3d5d66816 with PID 4 (/app/build/libs/demo-0.0.1-SNAPSHOT.jar started by u13413 in /app)
2016-11-19T13:58:52.270165+00:00 app[web.1]: 2016-11-19 13:58:52.269  INFO 4 --- [           main] com.example.DemoApplication              : No active profile set, falling back to default profiles: default
2016-11-19T13:58:52.419052+00:00 app[web.1]: 2016-11-19 13:58:52.418  INFO 4 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@5a2e4553: startup date [Sat Nov 19 13:58:52 UTC 2016]; root of context hierarchy
2016-11-19T13:58:54.647292+00:00 app[web.1]: 2016-11-19 13:58:54.647  INFO 4 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 52225 (http)
2016-11-19T13:58:54.663369+00:00 app[web.1]: 2016-11-19 13:58:54.663  INFO 4 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2016-11-19T13:58:54.664271+00:00 app[web.1]: 2016-11-19 13:58:54.664  INFO 4 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.6
2016-11-19T13:58:54.813979+00:00 app[web.1]: 2016-11-19 13:58:54.813  INFO 4 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2016-11-19T13:58:54.814136+00:00 app[web.1]: 2016-11-19 13:58:54.814  INFO 4 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2399 ms
2016-11-19T13:58:55.078824+00:00 app[web.1]: 2016-11-19 13:58:55.078  INFO 4 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2016-11-19T13:58:55.083817+00:00 app[web.1]: 2016-11-19 13:58:55.083  INFO 4 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'metricsFilter' to: [/*]
2016-11-19T13:58:55.084166+00:00 app[web.1]: 2016-11-19 13:58:55.084  INFO 4 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2016-11-19T13:58:55.084272+00:00 app[web.1]: 2016-11-19 13:58:55.084  INFO 4 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2016-11-19T13:58:55.084376+00:00 app[web.1]: 2016-11-19 13:58:55.084  INFO 4 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2016-11-19T13:58:55.084478+00:00 app[web.1]: 2016-11-19 13:58:55.084  INFO 4 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2016-11-19T13:58:55.084580+00:00 app[web.1]: 2016-11-19 13:58:55.084  INFO 4 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'webRequestLoggingFilter' to: [/*]
2016-11-19T13:58:55.084686+00:00 app[web.1]: 2016-11-19 13:58:55.084  INFO 4 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'applicationContextIdFilter' to: [/*]
2016-11-19T13:58:55.597506+00:00 app[web.1]: 2016-11-19 13:58:55.597  INFO 4 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@5a2e4553: startup date [Sat Nov 19 13:58:52 UTC 2016]; root of context hierarchy
2016-11-19T13:58:55.673440+00:00 app[web.1]: 2016-11-19 13:58:55.673  INFO 4 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2016-11-19T13:58:55.674627+00:00 app[web.1]: 2016-11-19 13:58:55.674  INFO 4 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2016-11-19T13:58:55.723994+00:00 app[web.1]: 2016-11-19 13:58:55.723  INFO 4 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-11-19T13:58:55.782426+00:00 app[web.1]: 2016-11-19 13:58:55.782  INFO 4 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-11-19T13:58:55.724075+00:00 app[web.1]: 2016-11-19 13:58:55.723  INFO 4 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-11-19T13:58:56.224259+00:00 app[web.1]: 2016-11-19 13:58:56.224  INFO 4 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-11-19T13:58:56.226739+00:00 app[web.1]: 2016-11-19 13:58:56.226  INFO 4 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-11-19T13:58:56.225195+00:00 app[web.1]: 2016-11-19 13:58:56.225  INFO 4 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException
2016-11-19T13:58:56.228147+00:00 app[web.1]: 2016-11-19 13:58:56.228  INFO 4 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-11-19T13:58:56.230478+00:00 app[web.1]: 2016-11-19 13:58:56.230  INFO 4 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/env || /env.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-11-19T13:58:56.230280+00:00 app[web.1]: 2016-11-19 13:58:56.230  INFO 4 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String)
2016-11-19T13:58:56.232092+00:00 app[web.1]: 2016-11-19 13:58:56.231  INFO 4 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-11-19T13:58:56.233083+00:00 app[web.1]: 2016-11-19 13:58:56.232  INFO 4 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/info || /info.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-11-19T13:58:56.237902+00:00 app[web.1]: 2016-11-19 13:58:56.237  INFO 4 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String)
2016-11-19T13:58:56.238064+00:00 app[web.1]: 2016-11-19 13:58:56.237  INFO 4 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-11-19T13:58:56.239229+00:00 app[web.1]: 2016-11-19 13:58:56.239  INFO 4 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-11-19T13:58:56.241230+00:00 app[web.1]: 2016-11-19 13:58:56.241  INFO 4 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/health || /health.json],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(java.security.Principal)
2016-11-19T13:58:56.240394+00:00 app[web.1]: 2016-11-19 13:58:56.240  INFO 4 --- [           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2016-11-19T13:58:56.377719+00:00 app[web.1]: 2016-11-19 13:58:56.377  INFO 4 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2016-11-19T13:58:56.389556+00:00 app[web.1]: 2016-11-19 13:58:56.389  INFO 4 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 0
2016-11-19T13:58:56.565557+00:00 app[web.1]: 2016-11-19 13:58:56.565  INFO 4 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 52225 (http)
2016-11-19T13:58:56.572245+00:00 app[web.1]: 2016-11-19 13:58:56.572  INFO 4 --- [           main] com.example.DemoApplication              : Started DemoApplication in 5.187 seconds (JVM running for 6.304)
2016-11-19T13:58:57.102150+00:00 heroku[web.1]: State changed from starting to up
```

メモリは結構シビア

```
2016-11-19T13:58:50.268163+00:00 app[web.1]: Picked up JAVA_TOOL_OPTIONS: -Xmx350m -Xss512k -Dfile.encoding=UTF-8
```

### actuatorを叩いてみる

```
~/D/g/demo ❯❯❯ curl https://salty-badlands-47970.herokuapp.com/health                                                                                                                   [master]
{"status":"UP","diskSpace":{"status":"UP","total":402672611328,"free":349425127424,"threshold":10485760}}%    
```

うごきました。