Before we start using Docker, let’s recall its key components:
| Term | Description |
|---|---|
| Dockerfile | A file with instructions that describe how to build a Docker image |
| Image | A snapshot of an app with its entire environment. Created from a Dockerfile |
| Container | A running copy of a Docker image, launched as a separate process |
| Registry | A repository where images are stored (e.g., Docker Hub) |
Step 1: Preparing the Dockerfile
Dockerfile — is the recipe used to build a Docker image. For our Spring Boot app it will look like this:
# Use base image with Java 17
FROM openjdk:17-jdk-slim
# Set the working directory inside the container
WORKDIR /app
# Copy our compiled JAR into the container
COPY target/myapp-0.0.1-SNAPSHOT.jar app.jar
# Specify the command to run the app
ENTRYPOINT ["java", "-jar", "app.jar"]
Dockerfile structure
- FROM: Specifies the base image. In our case it's Java 17. Later, when you change the JDK version, just replace this line.
- WORKDIR: Sets the working directory inside the container where our code will run.
- COPY: Copies the
myapp-0.0.1-SNAPSHOT.jarfile from the current folder into the container. - ENTRYPOINT: Defines the command that runs when the container starts.
Note: Before building the Docker image make sure your Spring Boot project is built with mvn clean package or ./gradlew bootJar. The JAR file is created in target or build/libs.
Step 2: Building the Docker image
Now that our Dockerfile is ready, let's build the Docker image. Open a terminal in the project's root folder (where the Dockerfile is) and run:
docker build -t myapp .
Let's break down the command just in case:
docker build: The instruction for Docker to build the image.-t myapp: Specifies the name for the image (myapp)..: Uses the current directory as the build context.
If everything went right, you'll see something like:
Successfully built <image-id>
Successfully tagged myapp:latest
You can check the built image with:
docker images
Step 3: Running the container
You run a container from the image with the docker run command. Here's how:
docker run -p 8080:8080 myapp
In that command:
-p 8080:8080: Maps container port 8080 to the host machine.myapp: The name of our image.
If everything worked, your app will be available at: http://localhost:8080. Congrats — you just ran your Spring Boot app in a container!
Step 4: Optimizing the Dockerfile
Your Docker image is working, but it might be heavy and slow to deploy. Let's optimize it!
We'll use a multi-stage build:
# Stage 1: Build the app
FROM maven:3.8.5-openjdk-17 AS builder
WORKDIR /build
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests
# Stage 2: Create a lightweight image
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY --from=builder /build/target/myapp-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
Now we use Maven only during the build stage, and for running the app we use the lightweight image openjdk:17-jdk-slim. This significantly reduces the final Docker image size.
Step 5: Publishing the Docker image
To share your image or deploy it on a server you need to push it to a Docker Registry. The most popular one is Docker Hub.
1. Log in to Docker Hub:
docker login
2. Tag the image (replace username with your Docker Hub username):
docker tag myapp username/myapp:latest
3. Push the image:
docker push username/myapp:latest
Now the image is available to pull:
docker pull username/myapp:latest
Step 6: Troubleshooting
When working with containers you may run into a few issues:
- JAR file not found: Make sure you've built the project before running
docker build. - Port conflicts: If port 8080 is taken, use another one, for example:
docker run -p 9090:8080 myapp - Huge image size: Use lightweight base images (for example,
openjdk:17-jdk-slim). - Can't access services (e.g., DB): Containers are isolated; make sure they can "see" your database. Use Docker Compose for networking.
Step 7: Using Docker Compose
If your app uses multiple services (e.g., a database + the app), you can configure them with Docker Compose.
Create a docker-compose.yml file:
version: '3.8'
services:
app:
build:
context: .
ports:
- "8080:8080"
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: myappdb
Command to run:
docker-compose up
Now Docker Compose will bring up both the app and the database at the same time!
Containerization isn't just a fad — it's a standard in modern software development. Docker images help you:
- Quickly deploy the app to a server or the cloud.
- Provide environment isolation and consistency.
- Automate CI/CD pipelines.
On interviews employers will definitely value your Docker skills, and in real projects you'll save a lot of time on environment setup.
Now you've got everything you need to package and deploy your project! 🎉
GO TO FULL VERSION