vendredi 7 novembre 2014

How to deploy wisdom application to AWS Beanstalk using Docker


Today I'd like to demonstrate how to deploy a wisdom application on AWS BeanStalk using Docker. The goal is to be able to update your current deployed app in one maven command. Maybe you want first to check some points 

Create your Wisdom app

In order to create a new app just do :
mvn org.wisdom-framework:wisdom-maven-plugin:0.6.5:create \
-DgroupId=YOUR_GROUPID \
 -DartifactId=YOUR_ARTIFACTID \
 -Dversion=1.0-SNAPSHOT
congratulation you have now a cool app ! You can try it :
mvn wisdom:run
To package your application run :
mvn clean package
It packages your app inside a zip into target/yourApp-version.zip, this is the zip to deploy in the server.

Add a Dockerfile

If you want to use Docker, there is no magic trick, create a Dockerfile at the root directory of your app (next to your pom.xml).
FROM dockerfile/java:oracle-java8

# Add the wisdom distribution
ADD . /root/wisdom

# Expose the port 9000
EXPOSE 9000

# Volumes
VOLUME /root/wisdom/logs
VOLUME /root/wisdom/application

# Change workdir.
WORKDIR /root/wisdom

RUN touch /root/wisdom.log

# For easier handling, we dump the log, so `docker logs containerId` displays
# the log.
CMD chmod +x chameleon.sh; ./chameleon.sh stop;./chameleon.sh start; tail -F logs/wisdom.log
To include the Dockerfile inside the .zip of your packaged app you have to add the following resources tag inside your pom.xml between the build tag :
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>${project.basedir}</directory>
            <includes>
                <include>Dockerfile</include>
            </includes>
            <targetPath>${project.build.directory}/wisdom</targetPath>
        </resource>
    </resources>
    ...
</build>
run again
mvn clean package
If you open the zip file the Dockerfile is now present.

Create a cool Beanstalk application

From here I suppose you already have a AWS access and you are able to create a BeanStalk app.
  • From AWS console go to Elastic Beanstalk
  • Create a new application and fill the name and click next
  • Environment type
    • Environment tier > Web server
    • Predefined configuration > Docker
    • Environment type > single instance
  • Application version > Upload your own > select the zip file of your packaged app
  • Environment information > put what you want
  • Additional resources > just click next (or configure following your requierments)
  • Configuration details > just click next (or configure following your requierments)
  • Environment tags > just click next (or configure following your requierments)
  • And LAUNCH
That it ! Wait a moment while beanstalk creates your application. Once it's done just check your app and you should see the wisdom sample page ! If not... Sorry you probably missed something

BUT WAIT !! I DON'T WANT TO UPLOAD MY ZIP BY HAND EACH TIME !!!

I know ! As I promised, it's time to reduce the heavy uploading step by a single maven command. Take a look at Beanstalker maven plugin it does all the boring part for you.
First, follow the Setting Up Credential part to configue your access and secret key.
next add the following profile to your pom.xml
<profiles>
    <profile>
        <id>deploy</id>
        <properties>
            <beanstalker-serverId>aws.amazon.com</beanstalker-serverId>
            <beanstalker.region>eu-west-1</beanstalker.region>
            <maven.install.skip>true</maven.install.skip>
            <maven.deploy.skip>true</maven.deploy.skip>
            <beanstalk.applicationName>test</beanstalk.applicationName>
            <beanstalk.cnamePrefix>test-env</beanstalk.cnamePrefix>    //This is the first part of your env url  test-env.elasticbeanstalk.com
            <beanstalk.environmentName>Test-env</beanstalk.environmentName>
            <maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>
            <beanstalk.s3Bucket>application-version</beanstalk.s3Bucket>  // The name of your S3 bucket which will contain every version uploaded
            <beanstalk.s3Key>${project.build.finalName}.zip</beanstalk.s3Key>  //The name of the zip to upload
            <beanstalk.multipartUpload>false</beanstalk.multipartUpload>
            <beanstalk.useLatestVersion>false</beanstalk.useLatestVersion>
        </properties>
        <build>
            <defaultGoal>deploy</defaultGoal>
            <finalName>${project.name}-${project.version}</finalName>
            <plugins>
                <plugin>
                    <groupId>br.com.ingenieux</groupId>
                    <artifactId>beanstalk-maven-plugin</artifactId>
                    <version>1.3.5</version>
                    <executions>
                        <execution>
                            <id>default-deploy</id>
                            <phase>deploy</phase>
                            <goals>
                                <goal>upload-source-bundle</goal>
                                <goal>delete-application-version</goal>  //delete the application version on beanstalk if it already exist (useful for snapshot)
                                <goal>create-application-version</goal>
                                <goal>update-environment</goal>
                            </goals>
                            <configuration>
                                <artifactFile>${project.build.directory}/${project.name}-${project.version}.zip
                                </artifactFile>
                                <skipExisting>false</skipExisting>
                                <environmentRef>cloudtest-env.elasticbeanstalk.com</environmentRef>
                                <optionSettings>                           //This part does nothing but I get NulPointer if I don't put anything here
                                    <setting>
                                        <namespace>aws:elasticbeanstalk:application</namespace>
                                        <optionName>Application Healthcheck URL</optionName>
                                        <value>/ping</value>
                                    </setting>
                                </optionSettings>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>
Now you just have to run :
mvn -Pdeploy
Wait and... Voila !