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:
3
Answers
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.
And as @valerij-dobler said i need to remove my container in order for my code changes to take effect
The image for your app is built and it reuses the same image for every next
docker-compose up
.If you want to force the rebuild you could use
docker-compose up --build
. Alternatively, you could remove the image by hand. But first, you should name your image, by using this property:then by using
docker image rm my_app
you could remove it. After that, thedocker-compose up
should rebuild your app.So you could give your frontend colleague following one-liner:
Note that
-d
runs the docker-compose detached from the terminal.1.In your project create a jar. since i use eclipse i just click maven install or maven build to create jar.
4.Inorder to run with updated code you must use this comman for docker
docker-compose -f dockercomposeYourFile.yaml up --build
.depends_on
then if the conatiner need to wait and cause to stop you needrestart: always
or anything aboutrestart