Docker containers with Vagrant – частина друга.

Щоб запустити якись додаток у контейнері, цей додаток спочатку треба створити. Створимо простий додаток, котрий буде мати підключення до бази даних MongoDB та дасть змогу щось до неї писати та читати записане. А у наступному записі ми створемо 2 контейнери – один з базою даних, інший з додатком.

Створюємо простий додаток з використанням Spring Boot.

1. Створюємо об’єкт, котрий будемо зберігати у базі даних

package ua.net.maxx.demo.docker;

import org.springframework.data.annotation.Id;

public class Item {

	@Id
	private String id;
	private String value;

	private Item() {

	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

	public String getId() {
		return id;
	}

	@Override
	public String toString() {
		return "Item [id=" + id + ", value=" + value + "]";
	}

}

2. Створюємо інтерфейс для бази даних

package ua.net.maxx.demo.docker;

import org.springframework.data.mongodb.repository.MongoRepository;

public interface ItemRepository extends MongoRepository<Item, String> {

	public Item findById(String id);

}

3. Створюємо контролер

package ua.net.maxx.demo.docker;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/demo")
public class WebController {

	@Autowired
	private ItemRepository repository;

	@RequestMapping(method = RequestMethod.GET)
	public @ResponseBody Item getItem(@RequestParam(value = "id", required = true) String id) {
		return repository.findById(id);
	}

	@RequestMapping(method = RequestMethod.POST)
	public @ResponseBody Item getUpdateItem(@RequestBody Item item) {
		return repository.save(item);
	}

}

4. Створюємо клас щоб виконати додаток

package ua.net.maxx.demo.docker;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Starter {

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

5. Створюємо фай конфігурації

spring:
  profiles.active: default
---
spring:
  profiles: default
  
  data:
    mongodb:
      host: db-host
      database: demo-database

6. Створюємо конфігурація для maven

<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>ua.net.maxx.demo.docker</groupId>
	<artifactId>docker-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>Docker demo project</name>

	<properties>
		<java.version>1.8</java.version>
		<spring.boot.version>1.4.0.RELEASE</spring.boot.version>
	</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-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-mongodb</artifactId>
		</dependency>
	</dependencies>

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

</project>

Тепер це можна запустити додаток за допомогою команди

clean package spring-boot:run

Тепер можна відкрити браузер та перейти за посиланням http://localhost:8080/demo/ та побачити таку відповідь:

demo-page-1

Незважаючи на помилку, усе працює нормально. У цьому додатку немає функції, яка обробляє такий запит.

7. Наступним кроком додаємо до цього проекту документацію, яка буде сгенерована автоматично за допомогою бібліотеки Swagger

додаємо наступні рядки до файлу pom.xml

		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger2</artifactId>
			<version>${swagger.version}</version>
		</dependency>
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger-ui</artifactId>
			<version>${swagger.version}</version>
		</dependency>

Та додаємо файл конфігурації Swagger

package ua.net.maxx.demo.docker;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {
	@Bean
	public Docket api() {
		return new Docket(DocumentationType.SWAGGER_2).select()
				.apis(RequestHandlerSelectors.basePackage("ua.net.maxx.demo.docker")).paths(PathSelectors.any()).build()
				.apiInfo(apiInfo());
	}

	private ApiInfo apiInfo() {
		ApiInfo apiInfo = new ApiInfo("Demo service REST API", "API for demo", "1.0", "Terms of service",
				"myeaddress@company.com", "License of API", "API license URL");
		return apiInfo;
	}

}

8. Тепер можна запустити додаток за допомогою тієї самої команди

clean package spring-boot:run

та перейти за посиланням http://localhost:8080/swagger-ui.html та навіть за допомогою Swagger спробувати відправити запит до додатка. У відповідь через деякий час ми отримаємо помилку. Це нормально, бо бази даних в нас досі немає.

demo-page-29. Наступним кроком підготуємо наш додаток для запуску у контейнері. Для цього додаємо у конфігурацію pom.xml плагіни, котри зберуть усі бублиотеки у теку /lib та створять jar файл, котрий можна запускати.

<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<configuration>
					<archive>
						<manifest>
							<addClasspath>true</addClasspath>
							<classpathPrefix>lib/</classpathPrefix>
							<mainClass>ua.net.maxx.demo.docker.Starter</mainClass>
						</manifest>
					</archive>
				</configuration>
				<version>3.0.2</version>
			</plugin>
			<plugin>
				<artifactId>maven-dependency-plugin</artifactId>
				<executions>
					<execution>
						<phase>install</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<outputDirectory>${project.build.directory}/lib</outputDirectory>
						</configuration>
					</execution>
				</executions>
				<version>2.10</version>
			</plugin>

10. Виконуємо команду

clean package install

після цього у теці /target можна буде побачити файл docker-demo-0.0.1-SNAPSHOT.jar та теку /lib з усіма бібліотеками, які необхідні цьому додатку.

 У наступній частині ми створимо контейнер до docker та запустимо додаток у образі, котрий було зроблено у частині першій.