Welcome to the core of modern development practices, where Docker Compose orchestrates a symphony for your fullstack app. As a dynamic Fullstack Software Engineer, you grasp the pivotal role containerization plays in shaping software development.
This blog is your guide to unlocking Docker Compose's potential in building a fullstack app with MySQL, Spring Boot, and React. Docker Compose acts as the linchpin, streamlining the encapsulation, and management of each component.
We'll navigate setting up a development environment within Docker containers, explore the relationship between database design and Dockerized Spring Boot backends, and witness the magic of containerized React frontends. At every step, Docker Compose ensures cohesion and consistency across the development lifecycle.
Whether you're refining containerization skills or demystifying Docker, this blog empowers both seasoned developers and curious enthusiasts. Join us as we unravel Docker Compose's potential, elevating your fullstack development experience.
Fasten your seatbelt, and lets sail through the realms of Docker Compose-driven fullstack development. 🚢
What are containers and how docker comes into picture?
Containers are lightweight, portable, and self-sufficient units that encapsulate software and its dependencies. They provide a consistent and isolated environment for running applications, allowing developers to package an application along with its dependencies, libraries, and runtime into a single container image. Containers are designed to be easily deployable across various environments, ensuring consistency from development to production.
Docker is a platform that enables the creation, deployment, and management of containers. It utilizes containerization technology to package applications and their dependencies into containers. Docker provides a set of tools and a runtime environment to build, ship, and run containers efficiently.
The typical Docker workflow involves creating a Dockerfile, which defines the steps to build a container image, and then using Docker commands to build, tag, and run containers based on that image. Docker Hub is a registry service provided by Docker, where container images can be stored and shared publicly or privately.
What does docker compose do?
Docker Compose is a tool for defining and running multi-container Docker applications. It allows you to define a multi-container environment using a simple YAML file, often named docker-compose.yml, and then use a single command to start and run the entire application stack. Docker Compose is particularly useful for managing the orchestration of complex applications that require multiple services and containers to work together.
Here are some key aspects and functionalities of Docker Compose:
Declarative Configuration: Docker Compose uses a declarative YAML file to define the services, networks, and volumes required for your application. This file specifies how containers should be configured and how they should interact.
Service Definition: Each containerized component of your application is defined as a service in the
docker-compose.ymlfile. Services can include information such as the base Docker image, container name, ports to expose, environment variables, and more.Networking: Docker Compose automatically creates a network for your services, allowing containers within the same
docker-compose.ymlfile to communicate with each other using service names as hostnames.Volume Sharing: You can define volumes in the
docker-compose.ymlfile, enabling data persistence and sharing between containers. This is useful for scenarios where you want to persist data beyond the lifecycle of a single container.Environment Variables: Docker Compose allows you to set environment variables for each service, making it easy to configure different aspects of your application without modifying the container images.
Orchestration and Scaling: Docker Compose simplifies the process of orchestrating multiple containers. You can start, stop, and scale your entire application with a single command. This makes it convenient for development, testing, and even production environments.
Ease of Use: Docker Compose provides a user-friendly command-line interface, making it accessible to both developers and system administrators. Common operations like starting, stopping, and inspecting the status of services are straightforward.
Pre-requisites
Install Docker
Install Docker Compose if not already installed through the Docker installation above
Java & Maven - The example in this blog uses Java v21 and Maven v3.9.5
Node - The example in this blog uses node v18
The project structure used for the example in this blog is as follows:-
Setup a spring application with docker configuration
Create a Spring project with appropriate dependencies like Spring Web, Spring Data JPA and MySQL Driver.
Insert your MySQL configuration in the application properties
The back-end should be running at http://localhost:8080
Setup a React application with docker configuration
Create a react app and install axios to call apis
The example in this blog uses a react project created by Vite, so we need to modify the
vite.config.tsto run the app on fixed port 3000 in our machine as well as in the container. Ignore this step if you are not using vite.Create a basic html table with Edit and Delete button for each row and add new product form below the table
The front-end should be running at http://localhost:3000
Docker Compose Config
Create a
Dockerfilein backend directoryCreate a
Dockerfilein frontend directoryAdd a .dockerignore in the frontend directory to restrict node_modules directory to hold up space
We can update the
application.propertiesin the backend to support dynamic environment variables now.
In the project source directory i.e. docker-compose-demo directory, we need to add a docker-compose.yml. The environment variables should be appropriately used in the docker-compose.yml and application.properties.
# Specify the version of the Docker Compose file formatversion: '3.8'# Define the services that will run in your applicationservices: # Configuration for the MySQL database service database: # Use the MySQL 8 Docker image image: mysql:8 environment: # Set the root password for MySQL MYSQL_ROOT_PASSWORD: password # Specify the name of the database to be created MYSQL_DATABASE: product # Specify the MySQL user and its password MYSQL_USER: product MYSQL_PASSWORD: password volumes: # Mount a volume to persist MySQL data - mysql_data:/var/lib/mysql # Configuration for the backend application server: # Build the server image using the Dockerfile in the ./server directory build: context: ./backend # Expose port 8080 on the host and map it to port 8080 in the container ports: - "8080:8080" environment: # Set the Spring DataSource URL to connect to the MySQL database service SPRING_DATASOURCE_URL: jdbc:mysql://database:3306/product # Set the username for connecting to the MySQL database SPRING_DATASOURCE_USERNAME: product # Set the password for connecting to the MySQL database SPRING_DATASOURCE_PASSWORD: password # Depend on the database service, ensuring it starts before the server depends_on: - database # Configuration for the frontend application client: # Build the client image using the Dockerfile in the ./client directory build: context: ./frontend # Expose port 3000 on the host and map it to port 5173 in the container ports: - "3000:3000" # Depend on the server service, ensuring it starts before the client depends_on: - server# Define a volume named mysql_data for persisting MySQL datavolumes: mysql_data:
Running the database, back-end and front-end containers in the docker network
Run the following command to create images of mysql, server and client services provided in
docker-compose.yml, create and run the images in containers in a single network in detached mode i.e. run the containers in the background, detached from the terminalWe can use the following command to stop and remove the containers.
If we restart our containers again by
docker-compose up -d, we should have our inserted data from before since we provided a volume namedmysql_dataindocker-compose.ymlfor persisting MySQL data.
Resources
Github repository to the provided example - Docker Compose Demo
Conclusion
In conclusion, this blog covered the fundamental concepts of containers and how Docker facilitates their creation, deployment, and management. It delved into the role of Docker Compose as a tool for orchestrating multi-container Docker applications, emphasizing its declarative configuration, service definition, networking, volume sharing, environment variable setup, and ease of use.
The blog provides streamlined steps for configuring a Spring backend and a React frontend application with Docker, along with Dockerfiles for building container images. The Docker Compose configuration file is introduced briefly, emphasizing service setups and volume usage for data persistence.
The concluding section briefly guides readers on running the entire application stack with Docker Compose, underscoring the importance of volumes in persisting data.
In essence, this blog serves as a quick reference for developers seeking practical insights into containerization using Docker and Docker Compose, offering a simplified guide for a multi-container application environment.


Top comments (0)