DEV Community

Cover image for Docker 101: Basics and Practical Implementation with Spring REST API
Priya
Priya

Posted on

Docker 101: Basics and Practical Implementation with Spring REST API

Ever spent hours debugging an application only to find it works perfectly on your machine but breaks in production? This is a common frustration for developers.

Imagine a developer builds a web application that runs on Python 3.8 and needs specific libraries. In development, the app works perfectly. However, when deployed to a server running Python 3.9, it breaks due to compatibility issues.

So, what's the solution? Enter Docker.

docker

By using Docker, the developer can package the app with Python 3.8 and all necessary libraries in a container. This container can then be deployed anywhere without worrying about compatibility, ensuring it runs smoothly in any environment.

In other words, it solves the "works on my machine" problem by ensuring that the application runs the same regardless of the environment.


What is Docker?

Docker is a platform that allows developers to package applications and their dependencies into lightweight, portable containers. These containers ensure that an application runs the same way, regardless of the environment—whether it's on a developer's laptop, a testing server, or a production server.

Understanding the Basics

Docker image-file-container

Image credit: Senali

Docker Hub

  • Docker Hub is a cloud-based repository where you can store and share Docker images, allowing easy access for developers and teams.

Docker Image

  • A Docker image is a lightweight, read-only, and executable software package that includes everything needed to run an application: code, runtime, libraries, environment variables, and configuration files.
  • Think of an image as a blueprint for creating Docker containers.
  • You can have multiple containers running from the same image.

Docker Container

  • A Docker container is a running instance of a Docker image. It uses the image's content to execute an application.
  • Containers can be stopped, started, or removed without affecting the Docker image.

In simpler terms:

  • Image = Blueprint
  • Container = Running Application

Dockerfile

A Dockerfile is a script that contains a series of instructions for building a Docker image. It specifies how the application should be packaged and run inside a container.

FROM openjdk:17-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
Enter fullscreen mode Exit fullscreen mode

In this example:

  • FROM specifies the base image to use (a base image contains the necessary software, libraries, and files required to run your application or service). Here, openjdk is used because we are going to run a Java application.

  • ARG defines a variable to reference the JAR file. Here, the value assigned is the Spring Boot JAR that is built by Maven, located in the target directory.

  • COPY copies the JAR file into the container.

  • ENTRYPOINT defines the command to run the application.

Docker Compose

Docker Compose orchestrates multiple containers (for example, a Spring Boot app and MySQL). It defines how each container will be set up, how they communicate, and their environment configurations. The configuration for Docker Compose is specified in a YAML file, typically named docker-compose.yml.

version: '3'
services:
  mysql-db:
    image: mysql:8.0
    container_name: mysql-db
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: spring_docker_demo
    ports:
      - "3306:3306"
    networks:
      - spring-network

  spring-app:
    image: spring-docker-demo:latest
    container_name: spring-app
    build:
      context: .
      dockerfile: Dockerfile
    depends_on:
      - mysql-db
    ports:
      - "8080:8080"
    networks:
      - spring-network
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql-db:3306/spring_docker_demo
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: root

networks:
  spring-network:
    driver: bridge
Enter fullscreen mode Exit fullscreen mode

In this example:

  • version specifies the Docker Compose version that we are using.

  • services defines individual containers. In this case, mysql-db is the first service and the second one is spring-app.

  • The networks section defines a network named spring-network. Both the Spring Boot app and MySQL will be on this network, allowing them to communicate with each other.

Docker network
Image credit: Dhruv Saksena

Brief Overview of Services

1. MySQL (mysql-db)

  • image: Specifies the Docker image to use for this service. In this case, it's the official mysql:8.0 image.

  • container_name: This gives a name to the MySQL container, making it easier to reference.

  • environment: Passes environment variables into the container. Here, we’re setting:

    • MYSQL_ROOT_PASSWORD: The root password for MySQL.
    • MYSQL_DATABASE: The name of the initial database to create.
  • ports: Maps the MySQL container's internal port (3306) to the host machine’s port (3306), allowing access to the database from the host.

  • networks: Defines the network (spring-network) that the MySQL container will join.

2. Spring App (spring-app)

  • image: Specifies the Docker image to use for the Spring Boot app. In this case, it’s spring-docker-demo:latest, which will be built from the Dockerfile in this project.

  • build:

    • context: The directory where the Dockerfile and source code are located (. means the current directory).
    • dockerfile: The name of the Dockerfile to use (in this case, Dockerfile).
  • depends_on: Specifies that the spring-app service depends on the mysql-db service, ensuring that MySQL starts before the Spring Boot app.

  • ports: Maps the Spring Boot container’s internal port (8080) to the host machine’s port (8080), allowing access to the REST API.

  • networks: Defines the network that the Spring Boot container will join, allowing it to communicate with the MySQL container.

  • environment: Sets environment variables for the Spring Boot app. These variables override values in application.properties and allow the Spring Boot app to connect to the MySQL container.


Example: Dockerizing a Spring REST API

To understand it better, let me walk you through an example of dockerizing a Spring REST API.

1. Project Structure:

Before diving into the Docker configurations, ensure your project structure looks something like this:

   spring-docker-demo/
   ├── Dockerfile
   ├── docker-compose.yml
   ├── src/
   │   └── main/
   │       └── java/
   │           └── com/
   │               └── example/
   │                   └── demo/
   │                       └── DemoApplication.java
   │                       └── UserController.java
   └── pom.xml
Enter fullscreen mode Exit fullscreen mode

2. Build the Spring Boot Application:

Make sure your Spring Boot application is set up correctly and build it using Maven:

mvn clean package
Enter fullscreen mode Exit fullscreen mode

This command should create a JAR file in the target directory, which the Dockerfile will reference.

3. Using the Dockerfile:

The Dockerfile provided will be used to create an image for your Spring REST API, as discussed earlier.

FROM openjdk:17-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
Enter fullscreen mode Exit fullscreen mode

4. Using Docker Compose:

The docker-compose.yml file will help you orchestrate the application and its database (MySQL). Here’s the configuration:

version: '3'
services:
  mysql-db:
    image: mysql:8.0
    container_name: mysql-db
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: spring_docker_demo
    ports:
      - "3306:3306"
    networks:
      - spring-network

  spring-app:
    image: spring-docker-demo:latest
    container_name: spring-app
    build:
      context: .
      dockerfile: Dockerfile
    depends_on:
      - mysql-db
    ports:
      - "8080:8080"
    networks:
      - spring-network
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql-db:3306/spring_docker_demo
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: root

networks:
  spring-network:
    driver: bridge
Enter fullscreen mode Exit fullscreen mode

5. Running the Application:

Navigate to your project folder where the docker-compose.yml file is located and run the following command:

docker-compose up --build
Enter fullscreen mode Exit fullscreen mode

This command builds the Docker images and starts the containers for your application and the database.

6. Accessing the Application:

Once everything is up and running, you can access your Spring REST API at http://localhost:8080.


Sharing Your Docker Image

Once you've containerized your Spring REST API, sharing the Docker image with others is straightforward.

1. Build the Docker Image

Build your image with the following command:

docker build -t your-username/spring-docker-demo:latest .
Enter fullscreen mode Exit fullscreen mode

Replace your-username with your Docker Hub username and . indicates that the Dockerfile is located in the current directory.

2. Push to Docker Hub

Log in to Docker Hub and push your image:

docker login
docker push your-username/spring-docker-demo:latest
Enter fullscreen mode Exit fullscreen mode

Again, replace your-username with your actual Docker Hub username.

3. Pulling the Image

Others can easily pull and run your image by executing:

docker pull your-username/spring-docker-demo:latest
docker run -d -p 8080:8080 your-username/spring-docker-demo:latest
Enter fullscreen mode Exit fullscreen mode
  • pull command downloads your Docker image from Docker Hub to their local machine.
  • run command runs a container from the downloaded image.
    • -d: Runs the container in detached mode (in the background).
    • -p 8080:8080: Maps port 8080 of the host machine to port 8080 of the container, allowing access to the application.

Wrap Up

Docker is a game-changer for developers, making deployment seamless and ensuring your app runs consistently across environments. Say goodbye to "it works on my machine" frustrations!

Ready to dive into Docker? Share your experiences or questions below!

Happy Coding! 🐳

Top comments (0)