You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker Compose部署Jetty+MariaDB应用时连接拒绝问题:如何让Jetty等待MariaDB就绪后启动

Great question! You're absolutely right about the limitation of depends_on — it only waits for the target container to start, not for the service inside it to be fully ready. MariaDB takes a few moments to initialize the database and accept connections after the container launches, which is why your Jetty app is throwing that connection refused error even if you wait for the DB to be ready later (and why restarting Jetty fixes it).

Here are three reliable solutions to fix this, ordered by recommended practice:


This is the cleanest Docker-native approach, requiring you to upgrade your Compose file to version 3.4 or higher. We'll add a health check to MariaDB to verify when it's ready, then configure Jetty to only start once the health check passes.

Update your docker-compose.yml like this:

version: '3.8' # Upgrade to support conditional dependencies
services:
  jetty:
    build:
      context: .
      dockerfile: docker/jetty/Dockerfile
    container_name: app-jetty
    ports:
      - "8080:8080"
    depends_on:
      mariadb:
        condition: service_healthy # Wait until MariaDB is healthy
    networks:
      - app
  mariadb:
    image: mariadb:10.7
    container_name: app-mariadb
    restart: always
    environment:
      MARIADB_ROOT_PASSWORD: myPassword
      MARIADB_DATABASE: APPBD
    ports:
      - "3307:3306"
    networks:
      - app
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MARIADB_ROOT_PASSWORD}"]
      interval: 5s       # Check every 5 seconds
      timeout: 5s        # Fail check after 5 seconds of no response
      retries: 10        # Allow up to 10 retries (total 50s wait time)
  adminer:
    image: adminer
    container_name: app-adminer
    restart: always
    ports:
      - "2002:8080"
    depends_on:
      mariadb:
        condition: service_healthy
    networks:
      - app
networks:
  app:
    driver: bridge

The mysqladmin ping command verifies that MariaDB is accepting connections. Jetty will only start once this check passes consistently.


2. Add a Wait Script to the Jetty Container

If you can't upgrade your Compose version, use a script like wait-for-it.sh to delay Jetty's startup until MariaDB's port is open.

Step 1: Get the wait script

Download the script to your project's docker/jetty/ directory and make it executable:

curl -o docker/jetty/wait-for-it.sh https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh
chmod +x docker/jetty/wait-for-it.sh

Step 2: Modify your Jetty Dockerfile

Update the Dockerfile to copy the script and use it to wait for MariaDB before starting Jetty:

FROM gradle:7.2-jdk17 as grad
WORKDIR /tmp
RUN mkdir src
COPY src /tmp/src
COPY build.gradle /tmp/build.gradle
RUN gradle --warning-mode all war

FROM jetty:latest
COPY --from=grad /tmp/build/libs/tmp.war /var/lib/jetty/webapps/ROOT.war
# Copy wait script into container
COPY docker/jetty/wait-for-it.sh /usr/local/bin/wait-for-it.sh
RUN chmod +x /usr/local/bin/wait-for-it.sh
# Wait for MariaDB port, then start Jetty
CMD ["wait-for-it.sh", "mariadb:3306", "--", "java", "-jar", "/usr/local/jetty/start.jar"]
EXPOSE 8080

Now the Jetty container will first wait for MariaDB's 3306 port to be reachable before launching the app server.


3. Add JDBC Connection Retry Logic to Your App

This is the most robust long-term fix, as it makes your app resilient to database restarts or temporary unavailability (not just startup delays).

Modify your JDBC connection string to include MariaDB's built-in retry parameters:

String jdbcUrl = "jdbc:mariadb://mariadb:3306/APPBD?user=root&password=myPassword"
    + "&connectTimeout=5000"    # Timeout after 5 seconds per connection attempt
    + "&autoReconnect=true"     # Automatically retry connections if dropped
    + "&maxReconnects=10"       # Max number of retry attempts
    + "&socketTimeout=30000";   # Timeout idle connections after 30 seconds

If you're using a framework like Spring Boot, you can also add a startup hook to loop until the database is reachable:

@PostConstruct
public void waitForDatabase() {
    int retries = 10;
    while (retries > 0) {
        try (Connection conn = DriverManager.getConnection(jdbcUrl)) {
            System.out.println("Successfully connected to database!");
            return;
        } catch (SQLException e) {
            retries--;
            System.out.println("Waiting for database... (" + retries + " retries left)");
            try { Thread.sleep(5000); } catch (InterruptedException ie) {}
        }
    }
    throw new RuntimeException("Failed to connect to database after multiple attempts");
}

Recommendation

Start with Solution 1 for a clean, Docker-native fix. Pair it with Solution 3 to make your app more resilient to runtime database issues.

内容的提问来源于stack exchange,提问作者Auraylien

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 06:47:57