IntelliJ IDEAをDocker for Macと連携させる方法

IntelliJでDockerコンテナを起動停止できるようにする方法自体は、既に「[IntelliJのDockerインテグレーションを使う](http://qiita.com/imaifactory/items/feca75fa158d10391bf3)」等で紹介されています。Docker for Macを使った方法がなかなか見つからなかったので、本記事で紹介します。

記事中の例は、`maven-archetype-webapp`アーキタイプを使って作成したMavenプロジェクトを、[GlassFishの公式コンテナイメージ](https://hub.docker.com/r/glassfish/server/)(glassfish/server)を元に作成されたコンテナで実行する想定となっています。適宜ご自身の環境に読み替えてください。

**2017.1リリースに伴い、手順を更新しました。2016.3以前から2017.1にアップデートしたら、Docker Integrationプラグインを更新してIntelliJを再起動しましょう。 (2017.03.23)**

# socatの導入(2016.3以前の場合のみ)

boot2dockerの頃と異なり、Docker for Macは、[Unixソケットを使ってDocker Remote APIと連携する方式となっています](https://docs.docker.com/docker-for-mac/faqs/#/how-do-i-connect-to-the-remote-docker-engine-api)。しかし、2016.3以前のDocker IntegrationではUnixソケットを使えません。後述のAPI URLにソケットのURIを入れても、エラーとなります([IDEA-159223](https://youtrack.jetbrains.com/issue/IDEA-159223))。

この問題を回避するために、[socat](http://www.dest-unreach.org/socat/)を使い、TCPで要求を受け付ける窓口を作っておきます。

* インストール

```
$ brew install socat
```

* 起動(ポート8099で待ち受ける場合)

```
$ socat TCP-LISTEN:8099,reuseaddr,fork,bind=localhost UNIX-CONNECT:/var/run/docker.sock
```

> 必要に応じて`&`や`nohup`をつけてください。

# IntelliJとDocker for Macの連携設定

Dockerと連携するプラグインを入れて、IntelliJをDocker for Macと連携させます。

### Dockerと連携するプラグイン(Docker Integration)の導入

`Preferences`を開きます。`Plugins`画面で、`Install JetBrains plugin...`ボタンをクリックし、**Docker integration**プラグインをインストールし、IntelliJを再起動します。

### 環境設定

もう一度`Preferences`を開きます。`Build, Execution, Deployment`->`Clouds`画面で、`+`ボタンをクリックして、プルダウンメニューから`Docker`を選択します。

![環境設定1](https://qiita-image-store.s3.amazonaws.com/0/10290/72cab357-60b2-d836-e2b5-e5a8475827cc.png)

boot2docker前提での初期値が色々表示されますが、Docker for Macでの設定に直します。

* `API URL:`には、`unix:///var/run/docker.sock`を設定
  - 2016.3以前の場合は`tcp://localhost:8099`を設定
* `Certificates folder:`は、空欄
* `VirtualBox shared folders`欄のエントリを削除

![環境設定2](https://qiita-image-store.s3.amazonaws.com/0/10290/0f86f69a-fb1e-cb44-12b4-3adf43510f81.png)

> `API URL:`入力後、Docker for Macとの通信テストが行われます。成功すると、`Connection Successful`と表示されます。

# コンテナの設定(第一段階)

まずは、アプリケーションをデプロイしていないコンテナを立ててみます。

### コンテナ起動設定の作成

`Run`->`Edit Configurations...`より、`Run/Debug Configurations`画面を開きます。`+`をクリックし、`Docker Deployment`を選択します。

![コンテナ起動設定1](https://qiita-image-store.s3.amazonaws.com/0/10290/6e93c818-c435-e5d4-0942-4596e5a1ad1e.png)

設定を編集します。

* `Image ID:`に、作成しているアプリを動かすコンテナのベースイメージを指定
* `Container name:`に、コンテナの名前を指定

以下の例では、[GlassFishの公式コンテナイメージ](https://hub.docker.com/r/glassfish/server/)(glassfish/server)をベースイメージに指定しています。

![コンテナ起動設定2](https://qiita-image-store.s3.amazonaws.com/0/10290/6eb08f89-dcb3-3648-f180-fc07a82dd162.png)

> アプリケーションサーバー系なら、この例のように、`Open browser`で管理コンソールを開く設定を入れておくと良いでしょう。

`Container`タブで、ポートフォワーディング設定を行います。今回の例では、GlassFishの管理コンソールのポート(4848)だけを使えるようにしています。

![コンテナ起動設定3](https://qiita-image-store.s3.amazonaws.com/0/10290/6b0f24d4-af28-9553-2af3-5760cca80003.png)

### ベースイメージの取り込み

現在のDocker Integrationは、ベースイメージがローカルにない場合、自動でpullせずにエラーとなります([IDEA-158324](https://youtrack.jetbrains.com/issue/IDEA-158324))ので、あらかじめpullしておきます。

`Docker`ツールタブを開き、一番上の要素を選択した状態で、図のアイコンをクリックします。

![pull](https://qiita-image-store.s3.amazonaws.com/0/10290/a3da329a-a119-54a3-4600-30dbcea0f1d0.png)

`Repository`に、ベースイメージの名前を入れて、`OK`をクリックします。

![スクリーンショット 2016-12-04 14.32.32.png](https://qiita-image-store.s3.amazonaws.com/0/10290/ac241e9f-dbd3-d29f-8f9c-659885af0b7c.png)

ダウンロードが完了すると、`Images`の中に、ベースイメージが表示されます。

![スクリーンショット 2016-12-04 14.34.27.png](https://qiita-image-store.s3.amazonaws.com/0/10290/1affb792-899a-b87c-7922-97351f545d91.png)


### 実行

`Docker`ツールタブを開いて、先ほど作成したコンテナ起動設定を実行します。`Containers`の中に青く塗りつぶされた四角のアイコンで、先ほど指定した名前のコンテナが現れていれば、成功です。

![Dockerツールタブ](https://qiita-image-store.s3.amazonaws.com/0/10290/c4c0d81a-70d3-3cf7-877a-112a48045c95.png)

`Open browser`を設定した場合は、コンテナ起動後、ブラウザが開きます。ただし、アプリケーションサーバープロセスの起動が完了する前にブラウザが開かれ、404エラーが表示されてしまうことが結構あります。その場合は、しばらく待ってリロードしてみましょう。

![ブラウザ表示](https://qiita-image-store.s3.amazonaws.com/0/10290/49fe1844-1206-a55b-5e78-958f07599694.png)

# コンテナの設定(第二段階)

ここまでは、ある意味、練習です。これから、実際に作成したアプリをデプロイする設定を行います。

### Dockerfileの作成

プロジェクトルート直下にDockerfileを作成します。少なくとも、以下の設定は必要です。

* ベースイメージを継承する記述
* 生成物を然るべき場所に配置する記述

GlassFishの場合、`domain1`というドメインが作成されます。ドメインディレクトリ内の`autodeploy`ディレクトリにwarファイルを格納すれば、アプリが実行されるようになります。

```Dockerfile:Dockerfile
# ベースイメージを継承
FROM glassfish/server:latest

# GlassFishのオートデプロイディレクトリに、warファイルを配置
ADD ["target/DockerTest.war", "/glassfish4/glassfish/domains/domain1/autodeploy"]
```

> `ADD`コマンドでは、Dockerfileが置いてある位置からの相対位置でソースファイルの格納位置を指定します。

### コンテナ起動設定の修正

先ほど作成した起動設定を開き(もしくは複写して)、以下のように修正していきます。

* `Deployment:`を`Dockerfile`に変更
* `Image tag:`に、このDockerfileで作成されるコンテナイメージの名前を指定
* `Container name:`に、コンテナの名前を指定
* `Open browser:`に、アプリのトップページとなるURLを指定(アプリケーションサーバの場合)
* コンテナ起動前のビルド設定を追加

![コンテナ起動設定修正1](https://qiita-image-store.s3.amazonaws.com/0/10290/c908d372-a706-d463-dd97-7c06b198a2fb.png)

> この例では、Mavenのpacakgeフェーズの起動設定を作成しておいてから、この画面で`Run Another Configuration`を選択して追加しています。

`Container`タブで、ポートフォワーディング設定を必要に応じて追加します。この例では、GlassFishのドメインポート8080を追加しています。

![コンテナ起動設定修正2](https://qiita-image-store.s3.amazonaws.com/0/10290/ddad78b6-d75b-62be-bcfd-133157492b8f.png)

### 実行

以前に作成したコンテナを削除してから、再実行します。プロジェクトのビルドが行われ、warファイルが作成された後で、Dockerコンテナが起動します。

![Dockerツールタブ](https://qiita-image-store.s3.amazonaws.com/0/10290/a1093230-a1db-17e6-da82-b6e9c38af4a9.png)

`Open browser:`を指定している場合は、起動するとブラウザが開きますが、ほとんどの確率で404となっています。アプリケーションサーバーの起動とWebアプリのデプロイが完了するまでに時間がかかるためです。しばらくしてリロードすると、表示されるようになるはずです。

![ブラウザ表示](https://qiita-image-store.s3.amazonaws.com/0/10290/f693bb6a-7054-10c1-725c-cf97aee083a5.png)