[DOCKER] [Java] Von der Erstellung neuer Projekte bis zur automatischen Realisierung von Tests / Builds / Bereitstellungen

TL;DR Automatisch, wenn Änderungen am Git-Zweig vorgenommen werden

Erstellen Sie ein Java-Projekt, das von Grund auf neu erstellt wird.

Was erscheint

OSS

Bedienung

Implementierung eines Beispielprojekts

Schließlich sieht die Verzeichnisstruktur so aus. Ich werde es Schritt für Schritt machen. Sie können auch von [GitHub] klonen (https://github.com/aaaanwz/java-autodeploy-example).

testproject/
    ├ src/
    │   ├ main/
    │   │   └ java/
    │   │        └testpackage/
    │   │            └Main.java
    │   └ test/
    │       └ java/
    │           └testpackage/  
    │              └MainTest.java   
    ├ .cifcleci/
    │   └ config.yml
    ├ schema.sql
    ├ pom.xml
    ├ deploy.yaml
    └ Dockerfile

1. Schemadefinition

Beschreiben Sie das Tabellenschema. Sie können es in den Ressourcenordner legen, aber dieses Mal werde ich es in das oberste Verzeichnis legen. Es ist kein Datenbankname angegeben.

schema.sql


CREATE TABLE user (id int, name varchar(10));

2. Erstellen Sie ein Maven-Projekt

Implementieren Sie ein minimales Java-Projekt, das die entsprechenden Datensätze in die obige Tabelle einfügt.

Verwenden Sie JDBC, JUnit, Maven-Assembly-Plugin.

pom.xml


<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>aaaanwz</groupId>
	<artifactId>test</artifactId>
	<version>0.0.1</version>
	<name>testproject</name>
	<properties>
		<maven.compiler.source>11</maven.compiler.source>
		<maven.compiler.target>11</maven.compiler.target>
	</properties>
	<dependencies>
		<!-- JDBC driver -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.17</version>
		</dependency>
		<!-- JUnit -->
		<dependency>
			<groupId>org.junit.jupiter</groupId>
			<artifactId>junit-jupiter-engine</artifactId>
			<version>5.3.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<!-- JUnit test -->
			<plugin>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>3.0.0-M3</version>
			</plugin>
			<!-- Build runnable jar -->
			<plugin>
				<artifactId>maven-assembly-plugin</artifactId>
				<executions>
					<execution>
						<phase>package</phase>
						<goals>
							<goal>single</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<archive>
						<manifest>
							<mainClass>testpackage.Main</mainClass>
						</manifest>
					</archive>
					<descriptorRefs>
						<descriptorRef>jar-with-dependencies</descriptorRef>
					</descriptorRefs>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Implementieren Sie die Hauptklasse, die nur einen Datensatz einfügt. Die Verbindungsinformationen zur Datenbank werden aus der Umgebungsvariablen abgerufen.

src/main/java/testpackage/Main.java


package testpackage;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Main {

  public static void main(String[] args) throws ClassNotFoundException, SQLException {
    final String host = System.getenv("DB_HOST");
    final String dbname = System.getenv("DB_NAME");
    execute(host, dbname);
  }

  static void execute(String host, String dbname) throws ClassNotFoundException, SQLException {
    Class.forName("com.mysql.cj.jdbc.Driver");
    Connection conn = DriverManager.getConnection(
        "jdbc:mySql://" + host + "/" + dbname + "?useSSL=false", "root", "");
    PreparedStatement stmt = conn.prepareStatement("INSERT INTO user(id,name) VALUES(?, ?)");
    stmt.setInt(1, 1);
    stmt.setString(2, "Yamada");
    stmt.executeUpdate();
  }

}

Schreiben Sie einen Test, der nur bestätigt, dass der Datensatz eingefügt wurde.

src/test/java/testpackage/MainTest.java


package testpackage;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import testpackage.Main;

class MainTest {
  Statement stmt;

  @BeforeEach
  void before() throws ClassNotFoundException, SQLException {
    Class.forName("com.mysql.cj.jdbc.Driver");
    Connection conn =
        DriverManager.getConnection("jdbc:mySql://localhost/test?useSSL=false", "root", "");
    stmt = conn.createStatement();
  }

  @AfterEach
  void after() throws SQLException {
    stmt.executeUpdate("TRUNCATE TABLE user");
  }

  @Test
  void test() throws Exception {
    Main.execute("localhost", "test");
    try (ResultSet rs = stmt.executeQuery("SELECT * FROM user WHERE id = 1;")) {
      if (rs.next()) {
        assertEquals("Yamada", rs.getString("name"));
      } else {
        fail();
      }
    }
  }
}

3. Erstellen Sie eine Docker-Datei

Schreiben Sie eine Docker-Datei. Da die Tests in einem vom Docker-Build getrennten Schritt durchgeführt werden, fügen Sie -DskipTests hinzu, um die Build-Time-Tests zu überspringen.

Um die Bildgröße zu reduzieren, erstellen Sie mit maven: 3.6 und führen Sie eine mehrstufige Erstellung mit openjdk11: apline-slim durch. Es ist ungefähr 800 MB für Maven: 3,6 und ungefähr 300 MB für openjdk11: alpine-slim. Derzeit beträgt die kostenlose ECR-Stufe 500 MB, was einen großen Unterschied für die persönliche Entwicklung darstellt.

Dockerfile


FROM maven:3.6 AS build

ADD . /var/tmp/testproject/
WORKDIR /var/tmp/testproject/
RUN mvn -DskipTests package

FROM adoptopenjdk/openjdk11:alpine-slim

COPY --from=build /var/tmp/testproject/target/test-0.0.1-jar-with-dependencies.jar /usr/local/
CMD java -jar /usr/local/test-0.0.1-jar-with-dependencies.jar.jar

4. Erstellen Sie eine k8s-Yaml-Datei

Schreiben Sie yaml, um den in 3. bis k8s integrierten Container bereitzustellen. Versuchen Sie, kind: Job zu verwenden, da dieses Programm SQL in einem einzigen Schuss ausführt und endet. Ersetzen Sie die URL in der Docker-Registrierung entsprechend. Definieren Sie die Verbindungsinformationen zur DB mit env. Der Wert von "DB_HOST" ist "mysql", da die Verbindung über den Kubernetes-Dienst hergestellt wird.

k8s-job.yaml


apiVersion: batch/v1
kind: Job
metadata:
  name: test
spec:
  template:
    spec:
      containers:
      - name: test
        image: your-docker-registry-url/testimage:latest
        imagePullPolicy: Always
        env:
        - name: DB_HOST
          value: "mysql"
        - name: DB_NAME
          value: "ekstest"
      restartPolicy: Never
  backoffLimit: 0

5. Erstellen Sie eine circleci-Konfigurationsdatei

Dies ist der Schlüssel zu diesem Artikel. Schreiben Sie Konfigurationseinstellungen für das automatisierte Testen / Erstellen mit CircleCI.

yml:.circleci/config.yml


version: 2.1
orbs:
  aws-ecr: circleci/[email protected]
  aws-eks: circleci/[email protected]
  kubernetes: circleci/[email protected]
jobs:
  test: #① Führen Sie den JUnit-Test aus
    docker:
      - image: circleci/openjdk:11
      - image: circleci/mysql:5.7
        environment:
          MYSQL_ALLOW_EMPTY_PASSWORD: yes
          MYSQL_DATABASE: test
        command: [--character-set-server=utf8, --collation-server=utf8_general_ci, --default-storage-engine=innodb]
    steps:
      - checkout
      - run:
          name: Waiting for MySQL to be ready
          command: dockerize -wait tcp://localhost:3306 -timeout 1m
      - run:
          name: Install MySQL CLI; Create table;
          command: sudo apt-get install default-mysql-client && mysql -h 127.0.0.1 -uroot test < schema.sql
      - restore_cache:
          key: circleci-test-{{ checksum "pom.xml" }}
      - run: mvn dependency:go-offline
      - save_cache:
          paths:
            - ~/.m2
          key: circleci-test-{{ checksum "pom.xml" }}
      - run: mvn test
      - store_test_results:
          path: target/surefire-reports
  deploy: #③ kubectl gelten für EKS
    executor: aws-eks/python3
    steps:
      - checkout
      - kubernetes/install
      - aws-eks/update-kubeconfig-with-authenticator:
          cluster-name: test-cluster
          aws-region: "${AWS_REGION}"
      - run:
          command: |
            kubectl apply -f k8s-job.yaml
          name: apply
workflows:
  test-and-deploy:
    jobs: 
      - test: #① Führen Sie den JUnit-Test aus
          filters:
            branches:
              only: develop
      - aws-ecr/build-and-push-image: #② Bauen Sie den Container und drücken Sie auf ECR
          filters:
            branches:
              only: master
          create-repo: true
          repo: "testimage"
          tag: "latest"
      - deploy: #③ kubectl gelten für EKS
          requires:
            - aws-ecr/build-and-push-image

① Durchführung des JUnit-Tests

Ich habe versucht, den "MVN-Test" auszuführen, wenn eine Änderung am "Entwicklungs" -Zweig durch Filter vorgenommen wird. Zu diesem Zeitpunkt wird eine Test-MySQL-Instanz gestartet und die Test-Datenbank vorbereitet.

Dies wird im offiziellen Dokument ausführlich erläutert.

② Bauen Sie den Container und drücken Sie auf ECR

Wenn Änderungen am Master-Zweig vorgenommen werden, erstellen Sie gemäß der Docker-Datei und drücken Sie auf ECR. Dies wird ausführlich in der Orb Quick Start Guide erläutert.

③ kubectl gelten für EKS

Nachdem ② ausgeführt wurde, wird der in 4. definierte Job ausgeführt. Es gibt eine Erklärung in circleci / aws-eks, aber der Beispielcode wurde geändert, um einfacher zu sein. Gemäß der Dokumentation zu @ 0.2.1 ist der Parameter "aws-region" nicht erforderlich, scheint jedoch in der Praxis erforderlich zu sein. Die Umgebungsvariable "AWS_REGION" wird durch Drücken von ECR angefordert, also habe ich sie so verwendet, wie sie ist.

Infrastruktureinstellungen

Meist eine Sammlung von Links zu offiziellen Dokumenten.

1. ECR, EKS Umweltvorbereitung

1-1. Grundeinstellungen

Starten Sie test-cluster.

1-2. Stellen Sie MySQL auf EKS bereit

Kubernetes hat offiziell ein Dokument namens Deploy MySQL. Bereiten Sie die Datenbank "ekstest" und die Tabelle "user" mit dem Befehl "kubectl exec -it mysql-0 mysql" vor.

2. CircleCI-Projekteinstellungen

2-1. Projekteinrichtung

2-2. Umgebungsvariablen einstellen

Zusammenfassung

Was haben Sie gedacht. Ich hoffe, Sie werden verschiedene Dinge ausprobieren, z. B. den Test absichtlich fallen lassen.

Recommended Posts

[Java] Von der Erstellung neuer Projekte bis zur automatischen Realisierung von Tests / Builds / Bereitstellungen
Neue Funktionen von Java7 bis Java8
Automatische Erstellung eines Java-Unit-Testergebnisberichts
Änderungen von Java 8 zu Java 11
Summe von Java_1 bis 100
Eclipse ~ Java-Projekterstellung ~
Von Java zu Ruby !!
Informieren Sie sich sofort über neue Funktionen von Java 7 bis Java 9
Migration von Cobol nach JAVA
Stellen Sie eine Verbindung von Java zu PostgreSQL her
Von ineffektivem Java zu effektivem Java
So erstellen Sie ein neues Gradle + Java + Jar-Projekt in Intellij 2016.03
[Gradle] Erstellen Sie ein Java-Projekt mit einer Konfiguration, die von der Konvention abweicht
Erstellen eines Java-Projekts mit Gradle
Java soll ab heute dabei sein
Von Java zu VB.NET-Writing Kontrastmemo-
Java, Schnittstelle für Anfänger
Süchtig nach dem Importieren von Projekten aus GitHub
Der Weg von JavaScript nach Java
[Java] Konvertierung von Array zu Liste
Wechseln Sie in einem neuen Ruby on Rails-Projekt von SQLite3 zu PostgreSQL