DOCKER
Understanding Docker Basics
What is Docker?
Docker is a platform that allows developers to automate the deployment of
applications inside lightweight, portable containers. These containers package the
application and its dependencies, ensuring consistency across different
environments.
Key Concepts:
Images: Read-only templates used to create containers. An image contains
the application and all its dependencies.
Containers: Instances of Docker images. Containers are lightweight and share
the host OS kernel.
Dockerfile: A script containing a series of instructions to build a Docker
image.
Docker Hub: A cloud-based repository for sharing and storing Docker images.
Step 1. Installing Docker
1. Windows/Mac: Download Docker Desktop from the official Docker website.
2. Verify Installation:
docker --version
Docker Commands
Check Running Containers:
docker ps
List All Containers:
DOCKER 1
docker ps -a
Run a Container:
docker run <image-name
Stop a Running Container:
docker stop <container-id>
Remove a Container:
docker rm <container-id>
Run an specific docker container env:
Development: docker-compose -f docker-compose.dev.yml up
Production: docker-compose -f docker-compose.prod.yml up
Step 2. Creating a Simple Java Application
1. Set up a Java project using Maven
Example pom.xml for a Maven project:
xml
Copiar código
<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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
DOCKER 2
<artifactId>my-java-app</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- Add your dependencies here -->
</dependencies>
</project>
2. Create a simple Main.java class:
java
Copiar código
public class Main {
public static void main(String[] args) {
System.out.println("Hello, Docker!");
}
}
Step 3: Package the Application as a JAR
Build your Spring Boot application using Maven :
./mvnw clean package
💡 This will create a JAR file in the target/ directory, usually named
something like my-app-1.0-SNAPSHOT.jar .
Step 4. Creating a Dockerfile
DOCKER 3
1. In your project root, create a file named Dockerfile :
💡 A Dockerfile defines the environment and steps for building your Docker
image.
dockerfile
Copiar código
# Use an official Java runtime as a parent image
FROM openjdk:11-jre-slim
# Set the working directory in the container
WORKDIR /app
# Copy the local jar file to the container
COPY target/my-java-app-1.0-SNAPSHOT.jar app.jar
# Expose the port your application runs on
EXPOSE 8080
# Command to run the application
ENTRYPOINT ["java", "-jar", "app.jar"]
💡 A Dockerfile is used to define a custom image. It contains a
series of instructions on how to build the image, such as which
base image to use, what files to copy, and what commands to
run.
You typically create a Dockerfile when you want to customize
an image for your application.
DOCKER 4
💡 : This sets the base image, which includes
FROM openjdk:17-jdk-alpine
Java 17 on a lightweight Alpine Linux distribution.
WORKDIR Directive: The WORKDIR instruction sets the working directory
inside the Docker container for any subsequent instructions (like
COPY , RUN , CMD , etc.).
/app Directory: The path /app is just a directory name that you are
creating inside the container. It does not directly refer to your local
Java application; instead, it’s the directory where your application
files will reside inside the container.
: This is the source path of the JAR
target/my-java-app-1.0-SNAPSHOT.jar
file that has been generated by your build tool (Maven in this case)
after you executed the build command ( mvn clean package ). It’s the
original name of the JAR file produced from your Java project.
app.jar : This is the destination name you are giving to the JAR file
when it is copied into the Docker image. Essentially, you are
renaming the original JAR file to app.jar in the context of the Docker
image.
ENTRYPOINT:This instruction defines the command that will run when
the container starts. It allows you to set the main command for the
container that cannot be overridden easily when you run the
container.
java :
This is the Java runtime command. It invokes the Java Virtual
Machine (JVM) to run Java applications.
jar :
This option tells the Java command that you want to run a JAR
file. The jar flag specifically indicates that the following
argument is the path to a JAR file containing the application to be
executed.
app.jar :
DOCKER 5
This is the name of the JAR file that contains your Java
application. It is assumed that this file is present in the current
working directory of the Docker container (which we set with the
WORKDIR /app directive).
This file should contain the compiled Java code along with any
necessary dependencies, packaged in a way that the Java
runtime can execute it.
Step 5: Build the Docker Image
To build the Docker image from the Dockerfile , run the following commandin the
same directory as your Dockerfile ):
docker build -t my-java-app .
💡 t my-spring-boot-app
app .
: This tags the image with the name my-spring-boot-
The . at the end tells Docker to use the current directory as the
build context.
Step 6: Run the Docker Container
After the Docker image is built, you can run your Spring Boot app inside a Docker
container using:
docker run -p 8080:8080 my-java-app
DOCKER 6
💡 : Maps port 8080 on the host machine to port 8080 in the
p 8080:8080
Docker container, allowing you to access the application through
http://localhost:8080 .
my-java-app: The name of the Docker image you built.
Docker Ports
Step 7: Test the Application
Once the container is running, open a browser and go to:
http://localhost:8080
You should see your Spring Boot application running.
Step 8: Push the Docker Image to Docker Hub (Optional)
If you want to share your Docker image or deploy it to a cloud environment, you
can push it to Docker Hub:
1. Log in to Docker Hub:
docker login
2. Tag your image to match your Docker Hub repository:
docker tag your-app-name <your-dockerhub-username>/your-ap
p-name
3. Push the image to Docker Hub:
DOCKER 7
docker push <your-dockerhub-username>/your-app-name
Step 9: Use Docker Compose (Optional)
If you want to manage multiple services (like a database and the Spring Boot app)
together, you can use Docker Compose.
💡 is a tool for defining and running multi-container Docker applications. It
uses a docker-compose.yml file to specify the services, networks, and
volumes needed for the application.
It simplifies the management of multiple containers that need to work
together.
Example Workflow
1. Create a Dockerfile for your application to define how to build the
image.
2. Create a docker-compose.yml file to specify how to run the
application and manage its dependencies.
1. Create a docker-compose.yml file with the env variables
version: '3'
services:
app:
image: your-app-name
ports:
- "8080:8080"
depends_on:
- db
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/mydat
DOCKER 8
abase
- SPRING_DATASOURCE_USERNAME=amigoscode
- SPRING_DATASOURCE_PASSWORD=password
networks:
- my-network
db:
image: postgres:17
environment:
- POSTGRES_DB=mydatabase
- POSTGRES_USER=amigoscode
- POSTGRES_PASSWORD=password
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- my-network
networks:
my-network:
volumes:
postgres-data:
Breaking down the docker compose
💡 This keeps the configuration centralized in Spring Boot
version: '3'
services:
app:
image: your-app-name
ports:
DOCKER 9
- "8080:8080"
depends_on:
- db
db:
image: postgres
environment:
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
POSTGRES_DB: mydb
ports:
- "5432:5432"
spring:
datasource:
url: jdbc:postgresql://db:5432/mydatabase
username: amigoscode
password: password
1. Run Docker Compose:
docker-compose up
This will spin up both your Spring Boot app and a PostgreSQL database.
DOCKER 10
💡 Choosing Between the Two
1. Using docker-compose.yml (Environment Variables) for complex setups,
especially when using multiple environments (e.g., development,
staging, production):
This approach is considered best practice when:
Separation of Concerns: You want to keep environment-specific
configurations (e.g., database credentials, URLs, external service API
keys) outside your application code. This is especially useful when
deploying to multiple environments (development, staging,
production).
Sensitive Information: For security reasons, it’s better not to hard-
code sensitive information like passwords, database URLs, or API
keys in your source code or configuration files. Environment
variables allow you to inject these securely.
Different Environments: If your Spring Boot application will run in
different environments (e.g., local, staging, production) with different
database settings it’s generally better to keep environment-specific
settings (like database URLs, credentials, and API keys) outside your
application code.This avoids having to maintain multiple versions of
your application.yml or application.properties files for different
environments (e.g., local vs. production).
Dockerized Deployments: If your app runs in a Dockerized
environment, it’s more practical to define environment variables
directly in docker-compose.yml . This allows you to keep environment-
specific details out of your application code.
Best Practice: Use docker-compose.yml for variables that change per
environment, like:
Database URL, username, and password.
External services URLs or credentials.
API keys and secrets.
DOCKER 11
Advantages:
Switch environments without modifying your application code.
Store sensitive information securely using environment variables
(instead of hardcoding it).
Share the same Docker image across different environments (since
the image doesn’t include the configurations).
Key Differences:
Multiple
Aspect Multiple docker-compose.yml Files
application.yml Files
Configurations live
Environment variables live outside the
Where it lives inside the application
application (Docker settings).
(Spring Boot).
Managing Spring Boot
app-specific settings
Managing environment-specific variables (e.g., logging, cache
Used for like database credentials, external service settings). Static
URLs. Environment-specific configurations configurations that don’t
change between
environments.
Switching
Switch Docker Compose file ( docker- Switch Spring profiles
between
compose.prod.yml for production, etc.). ( dev , prod , etc.).
environments
Tied to the code; not as
Easier to inject environment-specific settings
Flexibility flexible for secrets and
at runtime without touching code.
sensitive info.
Smaller apps or
Large-scale applications with multiple
managing application-
Best for services/environments, sensitive information
specific configurations,
(credentials).
especially for local dev.
8. Best Practices
DOCKER 12
Keep Images Small: Use a minimal base image and remove unnecessary files.
Use Multi-Stage Builds: If your application requires build tools, use multi-
stage builds to separate the build environment from the runtime environment.
Version Control: Tag your images with version numbers (e.g., my-java-app:1.0 ).
Environment Variables: Use environment variables for configuration rather
than hardcoding values.
Network Configurations: Use Docker networks to facilitate communication
between containers.
Using docker-compose.yml to define instances of PostgreSQL and
pgAdmin
simplifies the setup and management of these services. Below is a sample docker-
compose.yml file that sets up a PostgreSQL database along with pgAdmin.
services:
postgres:
container_name: postgres
image: postgres
environment:
POSTGRES_USER: amigoscode
POSTGRES_PASSWORD: password
PGDATA:
volumes:
- postgres:/data/postgres
ports:
- "5432:5432"
networks:
- postgres
restart: unless-stopped
pgadmin:
container_name: pgadmin
image: dpage/pgadmin4
environment:
DOCKER 13
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:-pgadmin4@p
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-admi
PGADMIN_CONFIG_SERVER_MODE: 'False'
volumes:
- pgadmin:/var/lib/pgadmin
ports:
- "5050:80"
networks:
- postgres
restart: unless-stopped
networks:
postgres:
driver: bridge
volumes:
postgres:
pgadmin:
👇🏻to get things up and running
microservices docker-compose up -d
Microservices structure
DOCKER 14