DevOps tutorials
Contact us

Getting Started with Container Service (Swarm)

Summary

  1. Introduction
  2. Prerequisite
  3. Step 1 - Spring Boot application
  4. Step 2 - Containerisation with Docker
  5. Step 3 - GitHub repository
  6. Step 4 - Container Registry
  7. Step 5 - Container Service Swarm
  8. Step 6 - Automatic build & deploy verification
  9. References
  10. Support

Introduction

The goal of this tutorial is to explain how to create a simple CI / CD pipeline in order to deploy an application in Alibaba Cloud Container Service (Swarm).

Prerequisite

Step 1 - Spring Boot application

Let’s start with an example Spring Boot application. Please create a folder for this project (e.g. ~/projects/container-service-sample) with the following sub-directory structure:

├── src
│   └── main
│       └── java
│           └── com
│               └── alibabacloud
│                   └── howto
│                       └── ContainerServiceApplication.java
└── pom.xml

Create a pom.xml file with the following content:

<?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>com.alibabacloud.howto</groupId>
    <artifactId>container-service-sample</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <name>${artifactId}</name>
    <description>Demo project for Spring Boot, Docker, and will be running on top of Alibaba Cloud.</description>

    <properties>
        <spring-boot.version>2.1.1.RELEASE</spring-boot.version>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <!-- Import dependency management from Spring Boot -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</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>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

Our application is made of a single Java class ContainerServiceApplication. Please create the file src/main/java/com/alibabacloud/howto/ContainerServiceApplication.java with the following content:

package com.alibabacloud.howto;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class ContainerServiceApplication {

    @GetMapping("/")
    public String welcome() {
        return "Hello, Container Service!";
    }

    public static void main(String[] args) {
        SpringApplication.run(ContainerServiceApplication.class, args);
    }

}

Let’s test the application. Open a terminal and execute the following commands:

# Navigate to the project directory
cd ~/projects/container-service-sample

# Build the application
mvn clean package

# Run it
mvn spring-boot:run

Then open a web browser and go to localhost:8080. If everything went well, you should see the “Hello, Container Service!” message.

Note: to stop the application, press CTRL+C.

Step 2 - Containerisation with Docker

Let’s create a Docker image of our application. Add the following Dockerfile to the root directory of our project (e.g. ~/projects/container-service-sample/Dockerfile):

## Docker multi-stage build
## First stage: complete build environment
FROM maven:3.5.0-jdk-8-alpine AS builder
# Add source code and pom.xml
ADD ./src src/
ADD ./pom.xml pom.xml
# Package executable jar
RUN mvn clean package

## Second stage: minimal runtime environment
FROM openjdk:8-jdk-alpine
VOLUME /tmp
# Copy jar from the first stage
COPY --from=builder target/container-service-sample-1.0.0.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","app.jar"]

We could directly use the docker build command to build our Docker image, however we will integrate this build step into our Maven configuration.

Open the pom.xml file with your favorite text editor, and apply the following changes:

<?xml version="1.0" encoding="UTF-8"?>
<project>
    ...

    <properties>
        ...
        <docker.image.prefix>alibabacloud-howto</docker.image.prefix>
        <dockerfile-maven-plugin.version>1.4.9</dockerfile-maven-plugin.version>
    </properties>

    ...

    <build>
        <plugins>
            ...
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <version>${dockerfile-maven-plugin.version}</version>
                <configuration>
                    <repository>${docker.image.prefix}/${project.artifactId}</repository>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Note: the existing XML code has been replaced by ... to improve readability.

Let’s build our Docker image. Enter the following commands in your terminal:

# Build the Docker image
mvn clean dockerfile:build

Note: before executing this command, make sure you have your Docker daemon running.

The build step should take few minutes. Once this is finished, you can check if it worked with the following command:

# List all Docker images saved locally
docker images

You should be able to see the following Docker image:

docker images result

Let’s create a container from our image. Run the following command in your terminal:

# Run the our application with Docker
$ docker run -p 8080:8080 -t alibabacloud-howto/container-service-sample

The outputs should look like this:

container-service-sample docker image run result

You can also use your web browser and navigate to localhost:8080. You should see the “Hello, Container Service!” message.

In order to stop the Docker container, we need to run the following commands in a terminal:

# Get the container ID
docker container ls

# Stop the container
docker stop 54789f1c4b67 # Replace 54789f1c4b67 by your ID

Step 3 - GitHub repository

Alibaba Cloud Container Service can simplify our life by automatically deploying our application. In order to use this service, we first need to bind our Alibaba Cloud account with a source code hosting platform, such as GitHub, Bitbucket or GitLab.

Let’s host our project on GitHub:

On the top of the repository page, GitHub should display the repository address (e.g. git@github.com:username/container-service-sample.git).

Let’s push our code to Github. In our terminal we execute the following commands:

# Navigate to the project directory
cd ~/projects/container-service-sample

# Initialize the project as a git repository
git init

# Add and commit the files we want to push
git add Dockerfile pom.xml src
git commit -m "first commit"

# Add a remote origin
git remote add origin git@github.com:username/container-service-sample.git # Replace the username

# Push the commit to GitHub
git push -u origin master

We should now be able to see our files in GitHub after refreshing our page in the web browser.

Step 4 - Container Registry

Let’s bind our GitHub account with Alibaba Cloud Container Service:

At the end of this process we are redirected back to the Container Registry console with a message: “You have successfully bound the GitHub account.”

Let’s now create a namespace:

Let’s create a Docker repository:

After few minutes the build should succeed with the “Successful” status.

Click on the “Tags” left menu item to see the Docker image that we have just built.

Step 5 - Container Service Swarm

Let’s deploy our application into a Docker Swarm cluster:

It’s time to deploy our application into our new cluster:

Step 6 - Automatic build & deploy verification

Let’s configure the Container Service to automatically re-deploy our application when we push changes to GitHub. For that we need to link our cluster with our container repository:

Now that our container repository is linked to our cluster via a trigger, we can test the complete process.

Let’s modify our Java class (file src/main/java/com/alibabacloud/howto/ContainerServiceApplication.java). Open it in a text editor and replace its content with the following one:

package com.alibabacloud.howto;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.net.InetAddress;
import java.net.UnknownHostException;

@RestController
@SpringBootApplication
public class ContainerServiceApplication {

    private static final Logger LOGGER = LoggerFactory.getLogger(ContainerServiceApplication.class);

    @GetMapping("/")
    public String welcome() {
        return getServerIP() + " says: Hello, Container Service!";
    }

    public static void main(String[] args) {
        SpringApplication.run(ContainerServiceApplication.class, args);
    }

    private String getServerIP() {
        InetAddress inetAddress = null;
        try {
            inetAddress = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            LOGGER.warn("Unable to obtain the IP address of this server.", e);
        }

        if (inetAddress == null) {
            return "Docker server";
        }

        return inetAddress.getHostAddress();
    }

}

Note: as you can see this modification adds the machine IP address in the message returned when the user visits the home page.

Let’s commit and push this change to GitHub:

# Check the changes
git status

# Add the modified file
git add src/main/java/com/alibabacloud/howto/ContainerServiceApplication.java

# Commit and push
git commit -m "Show the IP address in the home message."
git push origin master

The commands above should trigger an automatic build:

Once the image is built, it only takes few seconds for the application to be deployed again. With your web browser, navigate to the application URL (e.g. “http://hi-docker.someid.ap-southeast-1.alicontainer.com”).

If everything went well, you should be able to see an updated message with the server IP address:

container service end

Note: as you can see the total rebuild process is composed of the following steps: GitHub push » Container Registry re-build » Container Service re-deploy.

Congratulations, you have completed this tutorial!

References

Support

If you need help, please don’t hesitate to contact us.