How to Use Docker and Docker-Compose for MySql, PhpMyAdmin, Spring Boot, Angular Stack CRUD Web Application Development

A Star Wars Quotes Web Application

👋Introduction

👉What This Post NOT About👈

👉What This Post About👈

📖TLTR;

Create a Spring Boot BE

By spring initializr

By IntelliJ

Spring Boot “Hello World!”

@SpringBootApplication
//the following line has been added
@ComponentScan("com.example.crudapplication")
public class CrudApplication {

public static void main(String[] args) {
SpringApplication.run(CrudApplication.class, args);
}

}
@RestController
@RequestMapping("api/v1")
public class QuoteController {

@GetMapping
public String helloWorld(){
return "Hello World!";
}
}

Creating Application REST API Endpoints

Creating a MySql Container

docker run -d -p 3306:3306 --name=docker-mysql --env="MYSQL_ROOT_PASSWORD=password" --env="MYSQL_DATABASE=crud-application" mysql

Create a PhpMyAdmin Container and Connect the MySql Container

docker run -d --name docker-phpmyadmin --link docker-mysql:db -p 8081:80 phpmyadmin

What is Docker Compose

Use Docker Compose to Create MySql and PhpMyAdmin Containers

version: "3.3"
services:
db:
image: mysql
restart: always
container_name: mysql-db
environment:
MYSQL_ROOT_PASSWORD: 'password'
MYSQL_DATABASE: 'crud-application'
ports:
- 3306:3306
phpmyadmin:
image: phpmyadmin
restart: always
container_name: php-my-admin
ports:
- 8081:80
environment:
PMA_HOST: mysql-db
sudo docker-compose -f docker-compose.yaml up
$docker-compose -f docker-compose.yaml up -d

Connect Spring Boot to Docker MySql Container for Local Development

<dependency>
<
groupId>org.springframework.boot</groupId>
<
artifactId>spring-boot-starter-data-jpa</artifactId>
</
dependency>
<dependency>
<
groupId>mysql</groupId>
<
artifactId>mysql-connector-java</artifactId>
<
scope>runtime</scope>
</
dependency>
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Quote {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String title;
private String quote;
private String source;
@Builder.Default private long date = Instant.now().getEpochSecond();
}
public interface QuoteRepository extends CrudRepository<Quote, Integer> {
}
@SpringBootApplication
@ComponentScan("com.example.crudapplication")
@EnableJpaRepositories("com.example.crudapplication.repository")
@EntityScan("com.example.crudapplication.model")
public class CrudApplication {

public static void main(String[] args) {
SpringApplication.run(CrudApplication.class, args);
}

}

Creating Angular FE

ng new quote
ng g s services/quote
ng g c components/modal
ng generate class models/quote --type=model
ng serve

Reconfigure File Structure

‍🏭Dockerize Spring Boot Application

$touch Dockerfile
# Build Stage
FROM maven:3.6-openjdk-8-slim AS build
COPY pom.xml /app/
COPY src /app/src
RUN mvn -DskipTests -f /app/pom.xml clean package

# Run Stage
FROM openjdk:8-jre-alpine
COPY --from=build /app/target/crud-application*.jar /app/app.jar
ENTRYPOINT ["java", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCGroupMemoryLimitForHeap","-Djava.security.egd=file:/dev/./urandom","-jar","/app/app.jar"]

‍💻Dockerize Angular Application

$touch Dockerfile
# Build Stage
FROM node:12.7-alpine AS build
WORKDIR /app
COPY package*.json /app/
RUN npm install
RUN npm install -g @angular/cli@9.0.0-rc.2
COPY ./ /app/
RUN ng build --extract-css --output-path=dist --prod=true


# Run Stage
FROM nginx:1.17.1-alpine
COPY default.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist /usr/share/nginx/html
$touch default.conf
server {
listen 4200;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
error_page 404 =200 /index.html;
}
}

💃Use Docker Compose to Manage Life Cycle of Containers

$touch docker-compose.yaml
$docker-compose -f docker-compose.yaml up -d
$docker-compose -f docker-compose.yaml up -d --build

Configure FE to Communicate BE Over Docker Network

$docker network ls

What is Our BE URL at Docker Network

NGINX Reverse Proxy

server {
listen 4200;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
error_page 404 =200 /index.html;
}

location /api/v1{
proxy_pass http://springboot-app:8080/api/v1;
}
}

Configure Environment

export const environment = {
production: false,
apiUrl: 'http://localhost:8080/api/v1'
};
export const environment = {
production: true,
apiUrl: '/api/v1'
};
$docker-compose -f docker-compose.yaml up --build

Junior Full-Stack Developer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store