Skip to content

Commit 71e5d4e

Browse files
committed
OCI DevOps Build Caching Example
1 parent 2b219ae commit 71e5d4e

File tree

11 files changed

+340
-0
lines changed

11 files changed

+340
-0
lines changed

oci-build-examples/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ All about OCI devops build samples ..
88

99
</details>
1010

11+
<details>
12+
<summary>Build Caching - click to expand</summary>
13+
14+
* [Speed up builds with caching](./oci-build-caching/)
15+
16+
</details>
1117

1218

1319
### Back to examples.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Maven build container
2+
3+
FROM maven:3.8.5-openjdk-11 AS maven_build
4+
5+
COPY pom.xml /tmp/
6+
7+
COPY src /tmp/src/
8+
9+
WORKDIR /tmp/
10+
11+
RUN --mount=type=cache,target=/root/.m2 mvn package
12+
13+
#pull base image
14+
15+
FROM openjdk
16+
17+
#maintainer
18+
19+
#expose port 8080
20+
EXPOSE 8080
21+
22+
#default command
23+
CMD java -jar /data/hello-world-0.1.0.jar
24+
25+
#copy hello world to docker image from builder image
26+
27+
COPY --from=maven_build /tmp/target/hello-world-0.1.0.jar /data/hello-world-0.1.0.jar
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# OCI DevOps - Speed up builds with caching
2+
3+
Most of the time the build time is consumed in downloading or preparing certain build dependancies like maven dependencies, node_modules, pip dependancies, etc... This document talks about on how to reduce time by caching those dependencies for the subsequent runs.
4+
5+
In this way, the first run would take full time to download and setup build dependancies. But the subsequent runs will be more efficient through the cache.
6+
7+
For this, sample java maven-based application is used to demonstrate build caching.
8+
9+
### Prerequisites/Assumptions
10+
* Assumed you are already familiar with OCI DevOps. Please refer [Documentation](https://www.oracle.com/devops/devops-service/)
11+
* To know how to run the this maven project in your local. Please refer [this](./SETUP-PROJECT.md)
12+
* Assumed that you are using docker build inside your `build_spec.yaml`
13+
14+
### Overview of Changes
15+
For any project, you may tweek `build_spec.yaml` to enable build cache.
16+
17+
#### Step 1:
18+
Docker BuildKit is installed to enable few advanced docker build commands for caching.
19+
```
20+
- type: Command
21+
name: "Docker BuildKit Setup"
22+
timeoutInSeconds: 140
23+
command: |
24+
wget https://github.com/docker/buildx/releases/download/v0.8.2/buildx-v0.8.2.linux-amd64 -O docker-buildx
25+
mkdir -p ~/.docker/cli-plugins
26+
mv docker-buildx ~/.docker/cli-plugins/
27+
chmod +x ~/.docker/cli-plugins/docker-buildx
28+
docker buildx install
29+
```
30+
#### Step 2
31+
`Build Cache Restore` stage is used to download the pre-uploaded cache from OCI Object Storage.
32+
33+
```
34+
- type: Command
35+
name: "Build Cache Restore"
36+
timeoutInSeconds: 140
37+
command: |
38+
oci os object get --bucket-name build-cache --file ${BUILD_CACHE_OS_FILE_NAME} --name ${BUILD_CACHE_OS_FILE_NAME} && unzip ${BUILD_CACHE_OS_FILE_NAME}
39+
echo "Done..."
40+
```
41+
42+
#### Step 3
43+
In actual build stage, below comands are used in the place of regular `docker build`.
44+
```
45+
- type: Command
46+
name: "Docker build"
47+
command: |
48+
export DOCKER_BUILDKIT=1
49+
export DOCKER_CLI_EXPERIMENTAL=enabled
50+
docker buildx create --use
51+
docker buildx build -t="hello-world-java" --cache-from=type=local,src=./cache --cache-to=type=local,dest=./cache --load .
52+
echo "DONE"
53+
```
54+
55+
#### Step 4
56+
`Build Cache Upload` stage is added to collect the generated build cache and upload to OCI Object Storage bucket. This is used for subsequent builds.
57+
58+
```
59+
- type: Command
60+
name: "Build Cache Upload"
61+
timeoutInSeconds: 140
62+
command: |
63+
rm ${BUILD_CACHE_OS_FILE_NAME} && zip -r ${BUILD_CACHE_OS_FILE_NAME} cache/*
64+
oci os object put --bucket-name build-cache --file ${BUILD_CACHE_OS_FILE_NAME} --force
65+
```
66+
67+
### Results
68+
69+
#### Before OCI Build Cache
70+
![6m 33s](images/BeforeOCIBuildCache.png "Before Caching")
71+
72+
#### After OCI Build Cache
73+
![0m 49s](images/AfterOCIBuildCache.png "After Caching")
74+
75+
### Contributors
76+
77+
- Author : Ashok CM
78+
- Collaborators : NA
79+
- Last release : May 2022
80+
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
Hello World sample shows how to deploy [SpringBoot](http://projects.spring.io/spring-boot/) RESTful web service application with [Docker](https://www.docker.com/)
2+
3+
#### Prerequisite
4+
5+
Installed:
6+
[Docker](https://www.docker.com/)
7+
[git](https://www.digitalocean.com/community/tutorials/how-to-contribute-to-open-source-getting-started-with-git)
8+
9+
Optional:
10+
[Docker-Compose](https://docs.docker.com/compose/install/)
11+
[Java 1.8 or 11.1](https://www.oracle.com/technetwork/java/javase/overview/index.html)
12+
[Maven 3.x](https://maven.apache.org/install.html)
13+
14+
#### Steps
15+
16+
##### Clone source code from git
17+
```
18+
$ git clone https://github.com/dstar55/docker-hello-world-spring-boot .
19+
```
20+
21+
##### Build Docker image
22+
```
23+
$ docker build -t="hello-world-java" .
24+
```
25+
Maven build will be executes during creation of the docker image.
26+
27+
>Note:if you run this command for first time it will take some time in order to download base image from [DockerHub](https://hub.docker.com/)
28+
29+
##### Run Docker Container
30+
```
31+
$ docker run -p 8080:8080 -it --rm hello-world-java
32+
```
33+
34+
##### Test application
35+
36+
```
37+
$ curl localhost:8080
38+
```
39+
40+
the respone should be:
41+
```
42+
Hello World
43+
```
44+
45+
##### Stop Docker Container:
46+
```
47+
docker stop `docker container ls | grep "hello-world-java:*" | awk '{ print $1 }'`
48+
```
49+
50+
## Run with docker-compose
51+
52+
Build and start the container by running
53+
54+
```
55+
$ docker-compose up -d
56+
```
57+
58+
##### Test application with ***curl*** command
59+
60+
```
61+
$ curl localhost:8080
62+
```
63+
64+
the respone should be:
65+
```
66+
Hello World
67+
```
68+
69+
##### Stop Docker Container:
70+
```
71+
docker-compose down
72+
```
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
version: 0.1
2+
component: build
3+
timeoutInSeconds: 1000
4+
shell: bash
5+
env:
6+
# these are local variables to the build config
7+
variables:
8+
BUILD_CACHE_OS_BUCKET_NAME: build-cache
9+
BUILD_CACHE_OS_FILE_NAME: cache.zip
10+
11+
# exportedVariables are made available to use as parameters in sucessor Build Pipeline stages
12+
# For this Build to run, the Build Pipeline needs to have a BUILDRUN_HASH parameter set
13+
exportedVariables:
14+
- BUILDRUN_HASH
15+
16+
steps:
17+
- type: Command
18+
name: "Define unique image tag"
19+
timeoutInSeconds: 140
20+
command: |
21+
echo "OCI_BUILD_RUN_ID: ${OCI_BUILD_RUN_ID}"
22+
export BUILDRUN_HASH=`echo ${OCI_BUILD_RUN_ID} | rev | cut -c 1-7`
23+
echo "BUILDRUN_HASH: " $BUILDRUN_HASH
24+
- type: Command
25+
name: "Docker BuildKit Setup"
26+
timeoutInSeconds: 140
27+
command: |
28+
wget https://github.com/docker/buildx/releases/download/v0.8.2/buildx-v0.8.2.linux-amd64 -O docker-buildx
29+
mkdir -p ~/.docker/cli-plugins
30+
mv docker-buildx ~/.docker/cli-plugins/
31+
chmod +x ~/.docker/cli-plugins/docker-buildx
32+
docker buildx install
33+
- type: Command
34+
name: "Build Cache Restore"
35+
timeoutInSeconds: 140
36+
command: |
37+
oci os object get --bucket-name build-cache --file ${BUILD_CACHE_OS_FILE_NAME} --name ${BUILD_CACHE_OS_FILE_NAME} && unzip ${BUILD_CACHE_OS_FILE_NAME}
38+
echo "Done..."
39+
- type: Command
40+
name: "Docker build"
41+
command: |
42+
export DOCKER_BUILDKIT=1
43+
export DOCKER_CLI_EXPERIMENTAL=enabled
44+
docker buildx create --use
45+
docker buildx build -t="hello-world-java" --cache-from=type=local,src=./cache --cache-to=type=local,dest=./cache --load .
46+
echo "DONE"
47+
onFailure:
48+
- type: Command
49+
command: |
50+
echo "Handling Failure"
51+
build_result=FAILURE
52+
echo "Failure successfully handled"
53+
- type: Command
54+
name: "Build Cache Upload"
55+
timeoutInSeconds: 140
56+
command: |
57+
rm ${BUILD_CACHE_OS_FILE_NAME} && zip -r ${BUILD_CACHE_OS_FILE_NAME} cache/*
58+
oci os object put --bucket-name build-cache --file ${BUILD_CACHE_OS_FILE_NAME} --force
59+
outputArtifacts:
60+
- name: Build_output_image
61+
type: DOCKER_IMAGE
62+
location: "hello-world-java"
1.53 MB
Loading
1.62 MB
Loading
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>com.dockerforjavadevelopers</groupId>
7+
<artifactId>hello-world</artifactId>
8+
<version>0.1.0</version>
9+
10+
<parent>
11+
<groupId>org.springframework.boot</groupId>
12+
<artifactId>spring-boot-starter-parent</artifactId>
13+
<version>2.6.6</version>
14+
</parent>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>org.springframework.boot</groupId>
19+
<artifactId>spring-boot-starter-web</artifactId>
20+
</dependency>
21+
22+
<dependency>
23+
<groupId>junit</groupId>
24+
<artifactId>junit</artifactId>
25+
<version>4.13.1</version>
26+
<scope>test</scope>
27+
</dependency>
28+
29+
</dependencies>
30+
31+
<properties>
32+
<start-class>com.dockerforjavadevelopers.hello.Application</start-class>
33+
<log4j2.version>2.17.0</log4j2.version>
34+
</properties>
35+
36+
<build>
37+
<plugins>
38+
<plugin>
39+
<groupId>org.springframework.boot</groupId>
40+
<artifactId>spring-boot-maven-plugin</artifactId>
41+
</plugin>
42+
</plugins>
43+
</build>
44+
45+
</project>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.dockerforjavadevelopers.hello;
2+
3+
4+
import org.springframework.boot.SpringApplication;
5+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
6+
import org.springframework.context.ApplicationContext;
7+
import org.springframework.context.annotation.ComponentScan;
8+
import org.springframework.context.annotation.Configuration;
9+
10+
@Configuration
11+
@EnableAutoConfiguration
12+
@ComponentScan
13+
public class Application {
14+
15+
public static void main(String[] args) {
16+
ApplicationContext ctx = SpringApplication.run(Application.class, args);
17+
18+
}
19+
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.dockerforjavadevelopers.hello;
2+
3+
4+
import org.springframework.web.bind.annotation.RestController;
5+
import org.springframework.web.bind.annotation.RequestMapping;
6+
7+
@RestController
8+
public class HelloController {
9+
10+
@RequestMapping("/")
11+
public String index() {
12+
return "Hello World123\n";
13+
}
14+
15+
}

0 commit comments

Comments
 (0)