MavenProjectでAmazon EC2 Container Registry (ECR)にプッシュしてみた。

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

好物はインフラとフロントエンドのかじわらゆたかです。
ちょうど1ヶ月前、佐々木が以下のブログを上げていました。
【新機能】Amazon EC2 Container Registry (ECR)が東京リージョンにやってきました! | Developers.IO

実際に構築しているJavaのアプリケーションを組み込んだDocker ImageをAmazon ECRにPushするにはどうするんじゃい!
と思い調べてみました。

下準備編(Java Application)

Mavenプロジェクトで簡単なSpring Frameworkを用いたアプリを書きました。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>jp.classmethod</groupId>
    <artifactId>ecr_sample</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>ecr_sample</name>
    <description>ECR Sample project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

sampleController.java

package jp.classmethod;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by kajiwarayutaka on 2016/09/16.
 */
@RestController
public class sampleController {
    @RequestMapping(value = "/" ,method = RequestMethod.GET)
    public Response getMessage(){
        Response response = new Response();
        response.setMessage("Hello world.");
        return response;
    }
}
class Response {
    private String message;
    public String getMessage(){
        return message;
    }
    public void setMessage(String message){
        this.message = message;
    }
}

上記のような感じでアプリケーションを実装し、レスポンスが返ってくるのを確認します。

$ curl localhost:8080                                     
{"message":"Hello world."}

下準備編(Docker・ECR)

はじめにに記載した佐々木の記事をもとに、
レポジトリの作成とECRへのログインまで完了させてください。

docker-maven-plugin導入

Docker Image作成まで

pom.xml(pluginsの中に追記)

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.4.12</version>
    <executions>
        <execution>
            <id>tag-install</id>
            <phase>package</phase>
            <goals>
                <goal>build</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <baseImage>openjdk:8-jre-alpine</baseImage>
        <imageName>classmethod/ecr_sample</imageName>
        <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
        <dockerHost>unix:///var/run/docker.sock</dockerHost>
        <resources>
            <resource>
                <targetPath>/</targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.jar</include>
            </resource>
        </resources>
    </configuration>
</plugin>

解説

<dockerHost>unix:///var/run/docker.sock</dockerHost>

まず、18行目ですが、これを記載することでUNIXドメインソケットを用いてDockerとやり取りをすることになります。
これを記載しないとTCPでのDockerとやり取りを行うことになります。

<baseImage>openjdk:8-jre-alpine</baseImage>
<imageName>classmethod/ecr_sample</imageName>
<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>

次に15行目~17行目ですが、作成するDocker Imageの設定になります。
baseImageはその名の通り、ベースとなるDockerのイメージになります。
今回はJavaのアプリケーションということもあり、軽量のDockerImageであるalpineベースのJavaのイメージを用いました。
imageNameは作成するDockerのImage名になります。
entryPointはDockerfileのENTRYPOINTそのものです。

<resources>
    <resource>
        <targetPath>/</targetPath>
        <directory>${project.build.directory}</directory>
        <include>${project.build.finalName}.jar</include>
    </resource>
</resources>

20行目からのresourcesはDocker Imageに何を含ませるかを指定しています。
Spring Bootのアプリケーションなので、jarを含ませるのみになっています。

<execution>
    <id>tag-install</id>
    <phase>package</phase>
    <goals>
        <goal>build</goal>
    </goals>
</execution>

6行目以降のexecutionで、mavenのpackage phaseで、このプラグインのbuildを行うといった記載をしています。
mavenのpackage phaseでDockerのImageが作られる事になります。

実行結果

$ mvn clean package
(中略)
[INFO] --- docker-maven-plugin:0.4.12:build (tag-install) @ ecr_sample ---
[INFO] Copying /Users/kajiwarayutaka/ProjectSand/ecr_sample/target/ecr_sample-0.0.1-SNAPSHOT.jar -> /Users/kajiwarayutaka/ProjectSand/ecr_sample/target/docker/ecr_sample-0.0.1-SNAPSHOT.jar
[INFO] Building image classmethod/ecr_sample
Step 1 : FROM openjdk:8-jre-alpine
 ---> 87ec762b5790
Step 2 : ADD /ecr_sample-0.0.1-SNAPSHOT.jar //
 ---> 8eca3bbd6c92
Removing intermediate container 4ded54ac8a49
Step 3 : ENTRYPOINT java -jar /ecr_sample-0.0.1-SNAPSHOT.jar
 ---> Running in ad67d9bbb3d5
 ---> f1fc360bb0dd
Removing intermediate container ad67d9bbb3d5
Successfully built f1fc360bb0dd
[INFO] Built classmethod/ecr_sample
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10.978 s
[INFO] Finished at: 2016-09-16T20:30:27+09:00
[INFO] Final Memory: 41M/323M
[INFO] ------------------------------------------------------------------------
$ docker images
REPOSITORY                                                                  TAG                 IMAGE ID            CREATED              SIZE
classmethod/ecr_sample                                                      latest              f1fc360bb0dd        About a minute ago   121.9 MB

Docker Imageが作られたことがわかるかと思います。
一応Docker ImageにJavaのアプリケーションが組み込まれたことも確認しておきます。

$ docker run --name blog_ecr_sample -d -p 8080:8080 classmethod:ecr_sample
$ curl localhost:8080                                     
{"message":"Hello world."}

こちらも問題がないことが確認できました。

Amazon EC2 Container Registry (ECR)にプッシュ

pom.xml(pluginsの中に追記)

<executions>
    中略
    <execution>
        <id>tag-image</id>
        <phase>package</phase>
        <goals>
            <goal>tag</goal>
        </goals>
        <configuration>
            <image>classmethod/ecr_sample</image>
            <newName>123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/ecr_sample</newName>
        </configuration>
    </execution>
    <execution>
        <id>push-image</id>
        <phase>install</phase>
        <goals>
            <goal>push</goal>
        </goals>
        <configuration>
            <imageName>123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/ecr_sample</imageName>
        </configuration>
    </execution>
<executions>
<configuration>
    中略
    <useConfigFile>true</useConfigFile>
</configuration>

解説

executionのところで、タグの付与とイメージのプッシュが増えています。
idがtag-imageがタグの付与、push-imageがイメージのプッシュになります。
タグの付与はdocker上のコマンド以下のように行うコマンドになります。

$ docker tag classmethod/ecr_sample:latest 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/ecr_sample:latest

イメージのプッシュはdocker上のコマンドでは以下のようになります。

$ docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/ecr_sample:latest
<useConfigFile>true</useConfigFile>

最後のconfigurationの中に追加した上記の行ですが、このように書くことで、 このプラグインはAmazon ECRへログイン情報を用いてAmazon ECRへのプッシュを行うといったことが可能になっています。

実行結果

$ $(aws ecr get-login --region ap-northeast-1)
Flag --email has been deprecated, will be removed in 1.13.
Login Succeeded
$ ls ~/.docker
config.json machine
$ mvn clean install

ECR_01fix

まとめ

なかなか長旅ではありましたが、これでビルドタスクと同時にDockerのImageをAmazon ECRにプッシュすると言ったことが可能なりました。