Docker Desktop fail to start MySQL service when pulled from DockerHub

I am making a fullstack application for school and my project include a backend SpringBoot app that connect to a MySQL database in a docker container. I have no problem running the application locally but when I push it to Github and get it from DockerHub using Docker Desktop, the app fails to start the MySQL server and only start the Springboot application. This result in the application failing to start because its unable to connect to a Database. I’ve already tried to edit the configuration multiple times but haven’t found a solution yet.

Here is my pom.xml file,

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.5.13</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.iscod</groupId>
	<artifactId>api-project-pmt</artifactId>
	<version>1.0.0</version>
	<name>api-project-pmt</name>
	<description>The backend API of project PMT</description>
	<url/>
	<licenses>
		<license/>
	</licenses>
	<developers>
		<developer/>
	</developers>
	<scm>
		<connection/>
		<developerConnection/>
		<tag/>
		<url/>
	</scm>
	<properties>
		<java.version>21</java.version>
	</properties>
	<dependencies>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
            <exclusions>
                <!-- Exclude Hibernate core -->
                <exclusion>
                    <groupId>org.hibernate</groupId>
                    <artifactId>hibernate-core</artifactId>
                </exclusion>
            </exclusions>
		</dependency>
        <dependency>
            <groupId>org.hibernate.orm</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>6.5.2.Final</version>
        </dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>com.mysql</groupId>
			<artifactId>mysql-connector-j</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.6.3</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.6.3</version>
        </dependency>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.14.1</version>
        </dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-mail</artifactId>
			<version>3.5.12</version>
		</dependency>
        <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <scope>compile</scope>
        </dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<annotationProcessorPaths>
						<path>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</path>
						<path>
							<groupId>org.mapstruct</groupId>
							<artifactId>mapstruct-processor</artifactId>
							<version>1.6.3</version>
						</path>
						<path>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok-mapstruct-binding</artifactId>
							<version>0.2.0</version>
						</path>
					</annotationProcessorPaths>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
			<plugin>
    			<groupId>org.apache.maven.plugins</groupId>
    			<artifactId>maven-surefire-plugin</artifactId>
			    <configuration>
			        <argLine>
			            -javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar
			            -Xshare:off
			        </argLine>
			    </configuration>
			</plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.8.14</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>report</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
	</build>

</project>

my application.properties file,

spring.application.name=api-project-pmt
server.port=8081

spring.datasource.url=jdbc:mysql://mysql-db:3306/pmt?createDatabaseIfNotExist=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true&autoReconnect=true
spring.datasource.username=root
spring.datasource.password=3de7Qt?bMtHXGJpo
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect

spring.datasource.hikari.initializationFailTimeout=60000
spring.datasource.hikari.connectionTimeout=30000

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.defer-datasource-initialization=true
spring.sql.init.mode=always

spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=username.apppmt@gmail.com
spring.mail.password=password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

logging.level.org.springframework=DEBUG
logging.level.org.springframework.boot.context=DEBUG

my docker-compose.yml,

services:
  mysql-db:
    container_name: mysql-db
    image: mysql:8.4.7
    environment:
      MYSQL_ROOT_PASSWORD: 3de7Qt?bMtHXGJpo
      MYSQL_DATABASE: pmt
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    volumes:
      - db:/var/lib/mysql
    ports:
      - "3305:3306"
    networks:
      - spring-cloud-network
    restart: unless-stopped
    healthcheck:
      test: [ "CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}" ]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s          # gives MySQL time to initialize on first run
  project-server:
    container_name: tmp-server
    image: gwendal25/api-project-pmt
    ports:
      - "8081:8081"
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql-db:3306/pmt?createDatabaseIfNotExist=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true&autoReconnect=true
      SPRING_DATASOURCE_USERNAME: user
      SPRING_DATASOURCE_PASSWORD: password
      MYSQL_HOST: mysql-db
    networks:
      - spring-cloud-network
    depends_on:
      mysql-db:
        condition: service_healthy    # ← this is the critical change
    restart: on-failure:10

networks:
  spring-cloud-network:
    driver: bridge

volumes:
  db:

my Dockerfile,

# Use a base image with OpenJDK Java 17 installed
FROM eclipse-temurin:21

# Set the working directory in the container
WORKDIR /app

# Copy the packaged Spring Boot application JAR file into the container
COPY target/api-project-pmt-1.0.0.jar /app/api-project-pmt-1.0.0.jar

# Expose port 8081
EXPOSE 8081

# Specify the command to run the Spring Boot application when the container starts
CMD ["java", "-jar", "api-project-pmt-1.0.0.jar"]

and my maven-publish.yml file

name: Build and Push Docker Image
on: 
  push:
    branches:
      - main
jobs:
  test:
    runs-on: ubuntu-24.04
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
      - name: Setup JDK 21
        uses: actions/setup-java@v5
        with:
          java-version: '21'
          distribution: 'temurin'
      - name: Running Unit Tests
        run:
          mvn -f pom.xml clean test
  build:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v4
      - name: Set up JDK 21
        uses: actions/setup-java@v4
        with:
          java-version: '21'
          distribution: 'temurin'
      - name: Build with Maven
        run: mvn -f pom.xml clean package
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3.12.0
      - name: Login to Docker Hub
        uses: docker/login-action@v3.7.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Build and push Docker image
        uses: docker/build-push-action@v6.19.2
        with:
          context: .
          push: true
          tags: ${{ secrets.DOCKERHUB_USERNAME }}/api-project-pmt:latest 

If MySQL itself stops, you should check the mysql logs first. That likely shows the exact problem. For example misconfiguration, missing variable or MySQL version not compatible with already initialized data.

docker compose logs mysql-db

is the command

But as I said in my 1st post the MySQL server doesn’t even start.

And the logging command outputs nothing when I run it, because the server hasn’t started at all.

So I didn’t understand how to use DockerHub correctly.
After testing the image locally with Docker Compose, I would push my code to Github, then it ran trougth the CI/CD pipeline and was automatically pushed to DockerHub. Then I would pull the generated image and try to run it from Docker Desktop using the Run button.

When pulling my image from DockerHub, it doesnt include the mysql service because it only contain my SpringBoot application. Meaning that I need to create a bridge network and launch both services manually. I solved it by using these 3 commands.
The 1st command create the brige, the 2nd start MySQL and the 3rd start the SpringBoot app

docker network create spring-cloud-network

docker run -it --rm --name mysql-db --network spring-cloud-network `
		-e MYSQL_ROOT_PASSWORD=3de7Qt?bMtHXGJpo `
		-e MYSQL_DATABASE=pmt `
		-e MYSQL_USER=user `
		-e MYSQL_PASSWORD=password `
		-v mysql-db:/var/lib/mysql `
		-p 3305:3306 `
		mysql:8.4.7
		
docker container run -it --rm --name api-project-pmt-hub --network spring-cloud-network `
		-e MYSQL_DATABASE=pmt `
		-e MYSQL_USER=user `
		-e MYSQL_PASSWORD=password `
		-p 8081:8081 `
		gwendal25/api-project-pmt:latest 

I know you marked the topic as solved, but

I don’t know what that is supposed to mean. There is a MySQL server that doesn’t start and another MySQL (not server?) that doesn’t stop?

That doesn’t make sense. I just assume when you wrote “When pulling an image from Docker Hub”, you just wanted to say that the image description didn’t show how to create a Docker network. That is true, but you had your Docker Compsoe project which creates the network as well. Thre is nothing to create manually for inter-service communication. You could have even use the default settings without defining the bridge network and attaching it to the services, as compose does that by default after creating a “default” bridge for the compsoe project.

What I see as a possible difference is that now you already have the MySQL service before creating the one that uses it.

I edited my posts to try and make my situation clearer.
I was testing my project locally using Docker compose with the files included in my 1st post.
I am using Github CI/CD to build my SpringBoot application and push it to DockerHub automatically with the maven-publish file also included in my 1st post.
Then I would pull my image from DockerHub and try to run it by using Docker Desktop, wich started the SpringBoot application but not the MySQL server because it wasn’t included in the image.
I believed that the generated image contained both the SpringBoot application and the MySQL server, wich it doesn’t, and was the reason my project couldn’t work.