Spring Bootとは?初心者にもわかりやすく解説『Spring Boot完全ガイド2024:環境構築から本番デプロイまで15のステップで解説』Spring Bootとは?初心者にもわかりやすく解説

Spring Bootとは?初心者でもわかる基礎知識

Spring Bootは、本格的な Spring アプリケーションを素早く効率的に開発するためのフレームワークです。従来のSpring Frameworkの複雑な設定を大幅に簡略化し、「設定より規約」(Convention over Configuration)の原則に基づいて、開発者が本質的なビジネスロジックに集中できる環境を提供します。

従来のSpring Frameworkとの決定的な違い

Spring FrameworkとSpring Bootの主な違いは以下の通りです:

項目Spring FrameworkSpring Boot
設定方法XML設定やJava設定が必要自動設定が基本(設定不要)
アプリケーション起動外部のアプリケーションサーバーが必要組み込みサーバー(Tomcatなど)を内包
依存関係管理手動での設定が必要スターターPOMによる自動管理
デプロイWAR形式が基本実行可能なJARファイルとして配布可能
開発速度設定に時間がかかる最小限の設定で素早く開発可能

従来のSpring Frameworkでは、以下のような設定が必要でした:

// 従来のSpring Framework設定例
@Configuration
public class WebConfig {
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/db_name");
        dataSource.setUsername("username");
        dataSource.setPassword("password");
        return dataSource;
    }
}

一方、Spring Bootでは多くの設定が自動化されています:

// Spring Bootでの最小構成
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

なぜ今Spring Bootが選ばれているのか

  1. 開発生産性の大幅な向上
  • スターターPOMによる依存関係の自動管理
  • 自動設定による設定作業の削減
  • 組み込みサーバーによる即時実行環境の提供
  1. マイクロサービスアーキテクチャとの親和性
  • 軽量で独立したサービスの開発が容易
  • クラウドネイティブアプリケーションの開発に最適
  • コンテナ化が容易で、Kubernetesなどとの統合が簡単
  1. 充実したエコシステム
  • 豊富な組み込み機能(セキュリティ、モニタリング等)
  • アクチュエーター機能による運用管理の容易さ
  • 多様なクラウドプラットフォームとの連携

Spring Bootが解決する3つの開発課題

  1. 複雑な設定管理の課題
// 従来の複雑なデータベース設定の代わりに
spring.datasource.url=jdbc:mysql://localhost:3306/db_name
spring.datasource.username=username
spring.datasource.password=password
  1. アプリケーション展開の課題
# 実行可能JARファイルの作成と実行が簡単
./mvnw package
java -jar target/myapplication-0.0.1-SNAPSHOT.jar
  1. 開発環境の標準化の課題
<!-- 必要な依存関係を一括で管理 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.0</version>
</parent>

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

これらの特徴により、Spring Bootは現代のJava開発における事実上の標準フレームワークとして確立されています。次世代のクラウドネイティブアプリケーション開発において、Spring Bootは不可欠なツールとなっています。

【2024年版】Spring Boot開発環境の構築手順

Spring Bootの開発環境を効率的に構築し、スムーズな開発をスタートするための手順を詳しく解説します。2024年の最新バージョンに対応した環境構築方法を紹介します。

JDKとIDEのインストールとセットアップ

  1. JDK(Java Development Kit)のインストール
  • Spring Boot 3.x系は Java 17以上が必要
  • 推奨:Amazon Corretto 17 または Eclipse Temurin 17
# macOSの場合(Homebrewを使用)
brew install --cask temurin17

# Windowsの場合
# Eclipse Temurinの公式サイトからインストーラーをダウンロード
# https://adoptium.net/

環境変数の設定(Windows):

setx JAVA_HOME "C:\Program Files\Eclipse Adoptium\jdk-17.x.x"
setx PATH "%PATH%;%JAVA_HOME%\bin"
  1. IDEのインストールと設定
    推奨IDE:IntelliJ IDEA または Spring Tool Suite(STS)

IntelliJ IDEAの場合:

  • Ultimate版:Spring Boot開発に最適な機能が標準搭載
  • Community版:追加プラグインで対応可能

Spring Tool Suiteの場合:

# macOSの場合
brew install --cask springtoolsuite

# Windowsの場合は公式サイトからダウンロード
# https://spring.io/tools

Spring Initializrを使った最速プロジェクト作成

  1. Webインターフェースの利用
    https://start.spring.io/ にアクセスし、以下の項目を設定:
Project: Maven
Language: Java
Spring Boot: 3.2.x
Project Metadata:
  Group: com.example
  Artifact: demo
  Name: demo
  Description: Demo project for Spring Boot
  Package name: com.example.demo
Packaging: Jar
Java: 17
  1. IDEからの直接利用

IntelliJ IDEAの場合:

1. File → New → Project
2. Spring Initializr を選択
3. 必要な依存関係を追加:
   - Spring Web
   - Spring Data JPA
   - Spring Security(必要な場合)
   - Lombok
   - DevTools
  1. CLIからの利用
# Spring Boot CLIのインストール(macOS)
brew tap spring-io/tap
brew install spring-boot

# プロジェクト作成
spring init --dependencies=web,data-jpa,security my-project

依存関係の効率的な管理方法

  1. pom.xmlの基本構成
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>17</java.version>
        <!-- カスタムプロパティの定義 -->
        <mysql.version>8.0.33</mysql.version>
        <lombok.version>1.18.30</lombok.version>
    </properties>

    <dependencies>
        <!-- 必要な依存関係を追加 -->
    </dependencies>
</project>
  1. よく使用される依存関係の追加
<dependencies>
    <!-- Web アプリケーション用 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- データベース接続用 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- 開発ツール -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>

    <!-- テスト用 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
  1. バージョン管理のベストプラクティス
  • spring-boot-starter-parentを使用してバージョン管理を一元化
  • 依存関係の衝突を防ぐためのバージョン指定
  • BOMを使用した依存関係バージョンの管理
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

開発環境構築後のプロジェクト動作確認:

# プロジェクトのビルド
./mvnw clean install

# アプリケーションの起動
./mvnw spring-boot:run

これで基本的な開発環境の構築は完了です。次のステップでは、この環境を使って実際のアプリケーション開発に進むことができます。

Spring Bootによるサンプルアプリケーション開発

実践的なSpring Bootアプリケーション開発の手順を、具体的なコード例と共に解説します。ここでは書籍管理システムを例に、基本的なCRUD操作を実装していきます。

RESTful APIの実装手順と注意点

  1. エンティティクラスの作成
@Entity
@Table(name = "books")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank(message = "タイトルは必須です")
    private String title;

    @NotBlank(message = "著者は必須です")
    private String author;

    @Column(name = "published_date")
    private LocalDate publishedDate;

    @DecimalMin(value = "0.0", message = "価格は0円以上である必要があります")
    private BigDecimal price;
}
  1. リポジトリの実装
@Repository
public interface BookRepository extends JpaRepository<Book, Long> {
    List<Book> findByAuthor(String author);
    Optional<Book> findByTitleAndAuthor(String title, String author);

    // カスタムクエリの例
    @Query("SELECT b FROM Book b WHERE b.price <= :maxPrice")
    List<Book> findBooksWithinPriceRange(@Param("maxPrice") BigDecimal maxPrice);
}
  1. サービス層の実装
@Service
@Transactional
@Slf4j
public class BookService {
    private final BookRepository bookRepository;

    @Autowired
    public BookService(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    public Book createBook(Book book) {
        log.info("Creating new book: {}", book.getTitle());
        validateBook(book);
        return bookRepository.save(book);
    }

    public List<Book> getAllBooks() {
        return bookRepository.findAll();
    }

    public Book updateBook(Long id, Book bookDetails) {
        return bookRepository.findById(id)
            .map(existingBook -> {
                BeanUtils.copyProperties(bookDetails, existingBook, "id");
                return bookRepository.save(existingBook);
            })
            .orElseThrow(() -> new ResourceNotFoundException("Book not found with id: " + id));
    }

    private void validateBook(Book book) {
        if (bookRepository.findByTitleAndAuthor(book.getTitle(), book.getAuthor()).isPresent()) {
            throw new DuplicateResourceException("Book already exists");
        }
    }
}
  1. コントローラーの実装
@RestController
@RequestMapping("/api/books")
@Validated
public class BookController {
    private final BookService bookService;

    @Autowired
    public BookController(BookService bookService) {
        this.bookService = bookService;
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public ResponseEntity<Book> createBook(@Valid @RequestBody Book book) {
        Book createdBook = bookService.createBook(book);
        return ResponseEntity.created(URI.create("/api/books/" + createdBook.getId()))
                           .body(createdBook);
    }

    @GetMapping
    public List<Book> getAllBooks() {
        return bookService.getAllBooks();
    }

    @GetMapping("/{id}")
    public ResponseEntity<Book> getBookById(@PathVariable Long id) {
        return bookService.getBookById(id)
                         .map(ResponseEntity::ok)
                         .orElse(ResponseEntity.notFound().build());
    }

    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Map<String, String> handleValidationExceptions(ConstraintViolationException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getConstraintViolations().forEach(violation -> {
            errors.put(violation.getPropertyPath().toString(), violation.getMessage());
        });
        return errors;
    }
}

データベース連携のベストプラクティス

  1. アプリケーションプロパティの設定
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/bookdb?useSSL=false
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}
    hikari:
      maximum-pool-size: 10
      minimum-idle: 5
      idle-timeout: 300000

  jpa:
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQLDialect
        format_sql: true
    show-sql: true
  1. トランザクション管理の実装
@Service
@Transactional(readOnly = true)  // 読み取り専用をデフォルトに
public class BookTransactionService {

    @Transactional  // 書き込み操作用に個別指定
    public void transferBook(Long fromId, Long toId) {
        Book sourceBook = bookRepository.findById(fromId)
            .orElseThrow(() -> new ResourceNotFoundException("Source book not found"));
        Book targetBook = bookRepository.findById(toId)
            .orElseThrow(() -> new ResourceNotFoundException("Target book not found"));

        // トランザクション内での処理
        sourceBook.setAvailable(false);
        targetBook.setAvailable(true);

        bookRepository.save(sourceBook);
        bookRepository.save(targetBook);
    }
}

セキュリティ設定の実装方法

  1. Spring Securityの基本設定
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/books/**").authenticated()
                .anyRequest().authenticated()
            )
            .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )
            .oauth2ResourceServer(oauth2 -> oauth2
                .jwt(jwt -> jwt.decoder(jwtDecoder()))
            );

        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
  1. JWT認証の実装
@Service
@Slf4j
public class JwtTokenProvider {
    @Value("${jwt.secret}")
    private String jwtSecret;

    @Value("${jwt.expiration}")
    private int jwtExpiration;

    public String generateToken(Authentication authentication) {
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();

        return Jwts.builder()
                .setSubject(userDetails.getUsername())
                .setIssuedAt(new Date())
                .setExpiration(new Date((new Date()).getTime() + jwtExpiration))
                .signWith(SignatureAlgorithm.HS512, jwtSecret)
                .compact();
    }

    public boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token);
            return true;
        } catch (SignatureException ex) {
            log.error("Invalid JWT signature");
        } catch (MalformedJwtException ex) {
            log.error("Invalid JWT token");
        } catch (ExpiredJwtException ex) {
            log.error("Expired JWT token");
        }
        return false;
    }
}
  1. CORSの設定
@Configuration
public class CorsConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**")
                        .allowedOrigins("http://localhost:3000")
                        .allowedMethods("GET", "POST", "PUT", "DELETE")
                        .allowedHeaders("*")
                        .allowCredentials(true)
                        .maxAge(3600);
            }
        };
    }
}

このサンプルアプリケーションは、実践的なSpring Boot開発の基礎となる要素を含んでいます。実際の開発では、これらのコードを基盤として、要件に応じたカスタマイズや機能の追加を行っていくことになります。

実践的なSpring Boot開発テクニック

Spring Bootの高度な機能を活用し、より堅牢なアプリケーションを開発するための実践的なテクニックを解説します。

自動設定(Auto-configuration)の活用方法

  1. カスタム自動設定の作成
@Configuration
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class CustomDataSourceConfig {

    @Bean
    @ConditionalOnMissingBean
    public DataSourceHealthIndicator dataSourceHealthIndicator(DataSource dataSource) {
        return new DataSourceHealthIndicator(dataSource);
    }

    @Bean
    @ConditionalOnProperty(prefix = "app.datasource", name = "enable-metrics", havingValue = "true")
    public DataSourceMetricsCollector dataSourceMetricsCollector(DataSource dataSource) {
        return new DataSourceMetricsCollector(dataSource);
    }
}
  1. 条件付き設定の実装
@Configuration
@ConditionalOnClass(name = "org.springframework.data.redis.connection.RedisConnectionFactory")
public class RedisConfig {

    @Bean
    @ConditionalOnMissingBean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        return template;
    }
}
  1. 自動設定のデバッグ
# application.properties
debug=true
logging.level.org.springframework.boot.autoconfigure=DEBUG

プロファイル管理による環境分離の実現

  1. プロファイル別の設定ファイル
# application-development.yml
spring:
  datasource:
    url: jdbc:h2:mem:devdb
    username: sa
    password: 
  jpa:
    show-sql: true

# application-production.yml
spring:
  datasource:
    url: jdbc:mysql://prod-server:3306/proddb
    username: ${PROD_DB_USER}
    password: ${PROD_DB_PASS}
  jpa:
    show-sql: false
  1. プロファイル別のBean定義
@Configuration
public class ProfileSpecificConfig {

    @Bean
    @Profile("development")
    public EmailService mockEmailService() {
        return new MockEmailService();
    }

    @Bean
    @Profile("production")
    public EmailService smtpEmailService(
            @Value("${smtp.host}") String host,
            @Value("${smtp.port}") int port) {
        return new SmtpEmailService(host, port);
    }
}
  1. プロファイルの動的切り替え
@Component
@Slf4j
public class ProfileManager {
    private final Environment environment;

    @Autowired
    public ProfileManager(Environment environment) {
        this.environment = environment;
    }

    public void logActiveProfiles() {
        for (String profile : environment.getActiveProfiles()) {
            log.info("Currently active profile: {}", profile);
        }
    }
}

ログ設定とモニタリングの実装

  1. Logback設定の実装
<!-- logback-spring.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <springProperty scope="context" name="appName" source="spring.application.name"/>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
                %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
            </pattern>
        </encoder>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/${appName}.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/${appName}-%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>
                %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
            </pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </root>

    <logger name="com.example.myapp" level="DEBUG"/>
</configuration>
  1. Actuatorの設定とカスタマイズ
# application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,metrics,info,prometheus
  endpoint:
    health:
      show-details: always
  metrics:
    tags:
      application: ${spring.application.name}
@Component
public class CustomHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        try {
            // カスタムヘルスチェックロジック
            checkExternalService();
            return Health.up()
                    .withDetail("externalService", "OK")
                    .build();
        } catch (Exception e) {
            return Health.down()
                    .withDetail("error", e.getMessage())
                    .build();
        }
    }
}
  1. メトリクス収集の実装
@Component
@Slf4j
public class CustomMetricsCollector {
    private final MeterRegistry meterRegistry;

    public CustomMetricsCollector(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }

    @Scheduled(fixedRate = 60000)
    public void collectMetrics() {
        // カスタムメトリクスの収集
        Gauge.builder("app.business.metric", this, this::calculateBusinessMetric)
            .tag("type", "business")
            .description("A business metric")
            .register(meterRegistry);
    }

    @Timed(value = "app.processing.time", description = "Time taken to process")
    public void processBusinessLogic() {
        // ビジネスロジックの実行
    }
}
  1. 分散トレーシングの設定
# application.yml
spring:
  sleuth:
    sampler:
      probability: 1.0
  zipkin:
    base-url: http://zipkin:9411
@RestController
@Slf4j
public class TracedController {

    @Autowired
    private Tracer tracer;

    @GetMapping("/traced-endpoint")
    public ResponseEntity<?> tracedEndpoint() {
        Span span = tracer.currentSpan();
        span.tag("custom.tag", "value");

        log.info("Processing traced endpoint");

        return ResponseEntity.ok().build();
    }
}

これらの実践的なテクニックを適切に組み合わせることで、より保守性が高く、運用しやすいアプリケーションを開発することができます。特に本番環境での運用を見据えた場合、ログ管理とモニタリングの重要性は非常に高くなります。

Spring Bootアプリケーションの本番デプロイ

Spring Bootアプリケーションを本番環境にデプロイする際の手順と、運用管理のベストプラクティスを解説します。

コンテナ化とDockerfileの作成手順

  1. マルチステージビルドを活用したDockerfile
# ビルドステージ
FROM eclipse-temurin:17-jdk AS builder
WORKDIR /app
COPY . .
RUN ./mvnw clean package -DskipTests

# 実行ステージ
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar

# ヘルスチェック設定
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:8080/actuator/health || exit 1

# 環境変数の設定
ENV JAVA_OPTS="-Xms512m -Xmx1024m"

EXPOSE 8080
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
  1. Docker Composeによる環境構築
# docker-compose.yml
version: '3.8'

services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=production
      - SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/myapp
      - SPRING_DATASOURCE_USERNAME=${DB_USER}
      - SPRING_DATASOURCE_PASSWORD=${DB_PASS}
    depends_on:
      - db
    networks:
      - app-network

  db:
    image: mysql:8.0
    environment:
      - MYSQL_DATABASE=myapp
      - MYSQL_USER=${DB_USER}
      - MYSQL_PASSWORD=${DB_PASS}
      - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASS}
    volumes:
      - db-data:/var/lib/mysql
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

volumes:
  db-data:

クラウドプラットフォームへのデプロイ方法

  1. AWS Elastic Beanstalkへのデプロイ
# .elasticbeanstalk/config.yml
branch-defaults:
  main:
    environment: myapp-production
environment-defaults:
  myapp-production:
    branch: null
    repository: null
global:
  application_name: myapp
  default_ec2_keyname: null
  default_platform: Docker running on 64bit Amazon Linux 2
  default_region: ap-northeast-1
  sc: git

デプロイコマンド:

# Elastic Beanstalk CLIのインストール
pip install awsebcli

# 初期化とデプロイ
eb init
eb create myapp-production
eb deploy
  1. Google Cloud Runへのデプロイ
# プロジェクトの設定
gcloud config set project myapp-project

# Dockerイメージのビルドとプッシュ
gcloud builds submit --tag gcr.io/myapp-project/myapp

# Cloud Runへのデプロイ
gcloud run deploy myapp \
  --image gcr.io/myapp-project/myapp \
  --platform managed \
  --region asia-northeast1 \
  --allow-unauthenticated \
  --set-env-vars="SPRING_PROFILES_ACTIVE=production"
  1. Azure App Serviceへのデプロイ
# azure-pipeline.yml
trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: Docker@2
  inputs:
    containerRegistry: 'myAzureContainerRegistry'
    repository: 'myapp'
    command: 'buildAndPush'
    Dockerfile: '**/Dockerfile'
    tags: |
      $(Build.BuildId)
      latest

- task: AzureWebAppContainer@1
  inputs:
    azureSubscription: 'myAzureSubscription'
    appName: 'myapp'
    containers: 'myazurecontainerregistry.azurecr.io/myapp:$(Build.BuildId)'

本番環境での性能監視とトラブルシューティング

  1. Prometheusによるメトリクス監視
# prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'spring-boot-app'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['app:8080']
  1. Grafanaダッシュボードの設定
{
  "dashboard": {
    "id": null,
    "title": "Spring Boot Metrics",
    "panels": [
      {
        "title": "JVM Memory Usage",
        "type": "graph",
        "datasource": "Prometheus",
        "targets": [
          {
            "expr": "jvm_memory_used_bytes",
            "legendFormat": "{{area}}"
          }
        ]
      },
      {
        "title": "HTTP Request Duration",
        "type": "graph",
        "datasource": "Prometheus",
        "targets": [
          {
            "expr": "http_server_requests_seconds_count",
            "legendFormat": "{{status}}"
          }
        ]
      }
    ]
  }
}
  1. ログ集約とアラート設定
# fluentd.conf
<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

<match app.**>
  @type elasticsearch
  host elasticsearch
  port 9200
  logstash_format true
  logstash_prefix app-logs
  flush_interval 5s
</match>
  1. パフォーマンスチューニングの設定例
# application-production.yml
server:
  tomcat:
    max-threads: 200
    min-spare-threads: 20
    accept-count: 100

spring:
  datasource:
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
      idle-timeout: 300000

  jpa:
    properties:
      hibernate:
        jdbc:
          batch_size: 50
        order_inserts: true
        order_updates: true
        generate_statistics: true

logging:
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
  file:
    name: /var/log/myapp/application.log
  level:
    root: INFO
    org.springframework.web: WARN
    com.example.myapp: INFO

これらの設定と手順を適切に実装することで、安定した本番環境の運用が可能になります。特に、モニタリングとログ収集の仕組みを整備することで、問題発生時の早期発見と対応が容易になります。