
What is Docker Compose and how to use?
Natan Ferreira
- 0
- 106
Docker Compose is a tool that allows you to define and manage multi-container applications for Docker using a single YML file (docker-compose.yml
). With it, you can configure services, networks, and volumes in a readable and reproducible format. It is ideal for managing complex environments where multiple services (such as a database, cache, and backend) need to be orchestrated together.
This way, services that depend on each other are orchestrated. For example, imagine an API that needs to use a database, cache, messaging, etc. Docker Compose can orchestrate them.
This post is a continuation of the previous one; if you have any questions, feel free to check it out: previous post.
Let’s practice

version: "3.9"
networks:
company-network:
driver: bridge
services:
company-mysql:
image: mysql:8.0
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
ports:
- "3306:3306"
networks:
- company-network
company-api:
image: company-api
environment:
DATABASE_HOST: company-mysql
ports:
- "8080:8080"
networks:
- company-network
depends_on:
- company-mysql
This docker-compose.yml
file defines a container environment with a network and two services, company-mysql
and company-api
. Each configuration has a specific role in the creation and orchestration of these containers.
version: "3.9"
- Defines the Docker Compose version.
networks
- Creates a network named
company-network
with thebridge
driver, which is Docker’s default network for container communication. - This network allows services to communicate using the container name, making it easier for them to access each other.
services
- Defines the containers and their specific configurations.
company-mysql
image: mysql:8.0
: Specifies the Docker imagemysql:8.0
for the service, installing MySQL version 8.0.environment
: Configures an environment variableMYSQL_ALLOW_EMPTY_PASSWORD: "yes"
, allowing the use of an empty password for the root user (intended for development only, not recommended for production).ports
: Maps port 3306 of the MySQL container to port 3306 of the host, enabling database access from outside the container.networks
: Connects thecompany-mysql
container to thecompany-network
, facilitating communication with other services on the same network.
company-api
image: company-api
: Specifies that the service will use thecompany-api
image.environment
: Sets the environment variableDATABASE_HOST: company-mysql
, defining the hostnamecompany-mysql
(the service name) for database connection.ports
: Maps port 8080 of the container to port 8080 of the host, exposing the API for external access.networks
: Connects thecompany-api
to the samecompany-network
for communication with the database.depends_on
: Specifies thatcompany-api
depends on thecompany-mysql
service.
This docker-compose.yml creates two containers connected by a shared network.
DockerFile.
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
ARG JAR_FILE
COPY target/${JAR_FILE} /app/api.jar
EXPOSE 8080
CMD ["java", "-jar", "api.jar"]
Before running the command, make sure the Docker image of the application is available. If not, it is necessary to create it.
docker compose up
It may happen that the API runs before MySQL is available, even when specifying depends_on
.


Don’t worry, we can force the API to run only when MySQL is available.
We can use wait-for-it.sh
, a bash script that waits until a host is available before running a command. Download the wait-for-it.sh
file and place it in the root folder of the project. We can specify the host and port we are waiting for, in this case, MySQL, and the command that needs to be executed after the host (MySQL) is running on the specified port.

We make the wait-for-it.sh
file available inside the image by specifying it in the Dockerfile.
RUN apk add --no-cache bash
COPY wait-for-it.sh /wait-for-it.sh
RUN chmod +x /wait-for-it.sh
In the docker-compose file, it is necessary to add the command
to the company-api
service.
command: ["/wait-for-it.sh", "company-mysql:3306", "-t", "30", "--", "java", "-jar", "api.jar"]
This way, the command
in the Dockerfile is replaced by the one in the docker-compose file. It waits for the MySQL container to start with a timeout of 30 seconds, indicated by the -t
parameter. Once MySQL is available on port 3306, it runs the command java -jar api.jar
.
Reviewing the files before running the commands.
Dockerfile
FROM eclipse-temurin:17-jre-alpine
RUN apk add --no-cache bash
WORKDIR /app
ARG JAR_FILE
COPY target/${JAR_FILE} /app/api.jar
COPY wait-for-it.sh /wait-for-it.sh
RUN chmod +x /wait-for-it.sh
EXPOSE 8080
CMD ["java", "-jar", "api.jar"]
docker-compose
version: "3.9"
networks:
company-network:
driver: bridge
services:
company-mysql:
image: mysql:8.0
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
ports:
- "3306:3306"
networks:
- company-network
company-api:
image: company-api
command: ["/wait-for-it.sh", "company-mysql:3306", "-t", "30", "--", "java", "-jar", "api.jar"]
environment:
DATABASE_HOST: company-mysql
ports:
- "8080:8080"
networks:
- company-network
depends_on:
- company-mysql
Before running docker-compose, we need to create the API image and ensure that the wait-for-it.sh file has the correct Line Separator if you’re using Windows. In IntelliJ, you can check it here.

Set it to LF, save the file, and build the API image. Now we can run the docker compose command.
docker-compose up



When calling the endpoint, I get the result.


Author
-
I am a seasoned Full Stack Software Developer with 8+ years of experience, including 6+ years specializing in Java with Spring and Quarkus. My core expertise lies in developing robust RESTful APIs integrated with Cosmos Db, MySQL, and cloud platforms like Azure and AWS. I have extensive experience designing and implementing microservices architectures, ensuring performance and reliability for high-traffic systems. In addition to backend development, I have experience with Angular to build user-friendly interfaces, leveraging my postgraduate degree in frontend web development to deliver seamless and responsive user experiences. My dedication to clean and secure code led me to present best practices to my company and clients, using tools like Sonar to ensure code quality and security. I am a critical thinker, problem solver, and team player, thriving in collaborative environments while tackling complex challenges. Beyond development, I share knowledge through my blog, NatanCode, where I write about Java, Spring, Quarkus, databases, and frontend development. My passion for learning and delivering innovative solutions drives me to excel in every project I undertake.