I am a Java backend developer and i want to dockerize the backend part in order for my front end college to easily run in on his local machine. I will describe my problem based on demo project. So the demo project consists out of mysql and a spring boot web app. The app is works fine when i am using docker-compose, all the dependecies are download before the start and the endpoint "test" is returning "Some message". The problem occurse when i change the code and docker-compose down and docker-compose up the app, the code isnt changing. What i can do to solve this problem is to package the app on local machine and then deliver it to docker, but then the local machine has to has maven in order to compile it, and i dont want that, i want my college just to use docker and dont care about how all this thing works. Another solution could be not to cache, but then the dependencies have to be downloaded every time we restart the app, that is also not acceptable. So my question is "Is there a way to cache the dependecies (to download it once) but not the code, so that when i am starting the app, a fresh app ,with updated code, would compile?" (Sorry for my english). Here is the demo project that i am testing on:
The controller:
@RestController
@RequestMapping("message")
@RequiredArgsConstructor
public class Controller {
private final MessageRepository messageRepository;
@GetMapping("/{id}")
public Message getById(@PathVariable Long id) {
return messageRepository.findById(id).get();
}
@PostMapping
public Message save(@RequestBody Message message){
return messageRepository.save(message);
}
@GetMapping("/test")
public String ss(){
return "Some message";
}
}
The model:
@Getter
@Setter
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "messages")
public class Message {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "text")
private String text;
}
The repository:
@Repository
public interface MessageRepository extends JpaRepository<Message,Long> {}
property file:
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?useUnicode=yes&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
username: root
password: 123456789
driver-class-name: com.mysql.cj.jdbc.Driver
sql-script-encoding: UTF-8
jpa:
database-platform: org.hibernate.dialect.MySQL8Dialect
hibernate:
ddl-auto: create-drop
Docker file that is in root of the spring project:
FROM maven:3.8.4-jdk-11
WORKDIR /demo
COPY . .
RUN mvn clean install package -Dmaven.test.skip
CMD mvn spring-boot:run
Docker compose file:
version: "3.8"
services:
mysqldb:
image: mysql:8.0.27
restart: unless-stopped
environment:
- MYSQL_DATABASE=db
- MYSQL_ROOT_PASSWORD=123456789
ports:
- 3307:3306
volumes:
- db:/var/lib/mysql
app:
depends_on:
- mysqldb
build: ./demo
ports:
- 8080:8080
environment:
SPRING_APPLICATION_JSON: '{
"spring.datasource.url" : "jdbc:mysql://mysqldb:3306/db?useUnicode=yes&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true",
"spring.datasource.username" : "root",
"spring.datasource.password" : "123456789",
"spring.jpa.database-platform" : "org.hibernate.dialect.MySQL8Dialect",
"spring.jpa.hibernate.ddl-auto" : "update"
}'
volumes:
- .:/root
stdin_open: true
tty: true
volumes:
db:
I found the solution. In order to not download the dependencies, i need to cache them in upper layer and code in lower layer so that when i change the code, i dont have to redownload the dependencies. The docker file looks like this.
FROM maven:3.8.4-jdk-11-slim
WORKDIR /opt/app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src/ src/
RUN mvn clean install -Dmaven.test.skip=true
ENTRYPOINT ["java", "-jar", "/opt/app/target/demo-0.0.1-SNAPSHOT.jar"]
And as @valerij-dobler said i need to remove my container in order for my code changes to take effect
docker-compose down && docker image rm -f myapp && docker-compose up -d