← Назад к вопросам

Как сделать так, чтобы сервер запускался после запуска БД в Docker Compose

1.8 Middle🔥 121 комментариев
#Другое

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Запуск сервера после инициализации БД в Docker Compose

Проблема зависимостей между сервисами в Docker Compose часто встречается при развертывании многосервисных приложений. Нужно убедиться, что база данных полностью инициализирована и готова принимать запросы перед запуском приложения.

Способ 1: depends_on с condition (рекомендуемый)

Используй параметр depends_on с проверкой статуса сервиса:

version: "3.8"
services:
  postgres:
    image: postgres:15-alpine
    container_name: postgres_db
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: password
      POSTGRES_DB: myapp_db
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U admin"]
      interval: 10s
      timeout: 5s
      retries: 5
    volumes:
      - postgres_data:/var/lib/postgresql/data

  java_app:
    image: java_app:latest
    container_name: java_server
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      DATABASE_URL: jdbc:postgresql://postgres:5432/myapp_db
      DATABASE_USER: admin
      DATABASE_PASSWORD: password
    ports:
      - "8080:8080"
    links:
      - postgres

volumes:
  postgres_data:

Ключевые моменты:

  • healthcheck проверяет, что БД готова
  • condition: service_healthy — запуск только после успешной проверки
  • links — добавляет сетевое имя для связи между контейнерами

Способ 2: wait-for-it.sh скрипт

Для старых версий Docker Compose используй скрипт ожидания:

version: "3.8"
services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: password
      POSTGRES_DB: myapp_db
    ports:
      - "5432:5432"

  java_app:
    image: java_app:latest
    depends_on:
      - postgres
    environment:
      DATABASE_URL: jdbc:postgresql://postgres:5432/myapp_db
      DATABASE_USER: admin
      DATABASE_PASSWORD: password
    ports:
      - "8080:8080"
    entrypoint: ["/app/wait-for-it.sh", "postgres:5432", "--", "java", "-jar", "app.jar"]

Сам скрипт wait-for-it.sh:

#!/bin/bash
# wait-for-it.sh

HOST=$1
SHIFT
CMD=$@

echo "Ожидание $HOST"
while ! nc -z $HOST; do
  sleep 1
done

echo "$HOST доступен, запускаем: $CMD"
exec $CMD

Добавь скрипт в Dockerfile:

FROM openjdk:17-jdk-slim

WORKDIR /app

COPY wait-for-it.sh /app/
RUN chmod +x /app/wait-for-it.sh

COPY target/app.jar /app/app.jar

EXPOSE 8080

Способ 3: Проверка в коде Java приложения

Используй Spring Boot для ожидания подключения к БД:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;

@SpringBootApplication
public class Application {
    
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    
    @Bean
    public CommandLineRunner checkDatabase(DataSource dataSource) {
        return args -> {
            int retries = 30;
            boolean connected = false;
            
            while (retries > 0 && !connected) {
                try (Connection conn = dataSource.getConnection()) {
                    System.out.println("Успешно подключено к БД");
                    connected = true;
                } catch (SQLException e) {
                    System.out.println("Ожидание БД... осталось попыток: " + retries);
                    Thread.sleep(1000);
                    retries--;
                }
            }
            
            if (!connected) {
                throw new RuntimeException("Не удалось подключиться к БД за отведённое время");
            }
        };
    }
}

Способ 4: Использование инициализирующих скриптов

Передай скрипты инициализации БД при запуске:

services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: password
      POSTGRES_DB: myapp_db
    volumes:
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U admin"]
      interval: 10s
      timeout: 5s
      retries: 5

  java_app:
    image: java_app:latest
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      DATABASE_URL: jdbc:postgresql://postgres:5432/myapp_db
    ports:
      - "8080:8080"

Рекомендации

  • Используй healthcheck для проверки готовности сервиса
  • depends_on с condition — встроенное решение Docker Compose
  • Логируй попытки подключения в Java коде для отладки
  • Установи timeout чтобы контейнер не вешался бесконечно
  • В продакшене используй оркестрацию (Kubernetes) с более продвинутыми механизмами

Этот подход обеспечивает надёжное и предсказуемое поведение при запуске многосервисного приложения.