Skip to content

Commit e1aa5da

Browse files
eddumelendezkiview
authored andcommitted
Add Ollama module (testcontainers#8369)
Co-authored-by: Kevin Wittek <[email protected]>
1 parent ea5ebf7 commit e1aa5da

File tree

12 files changed

+206
-0
lines changed

12 files changed

+206
-0
lines changed

.github/ISSUE_TEMPLATE/bug_report.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ body:
4343
- Neo4j
4444
- NGINX
4545
- OceanBase
46+
- Ollama
4647
- OpenFGA
4748
- Oracle Free
4849
- Oracle XE

.github/ISSUE_TEMPLATE/enhancement.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ body:
4343
- Neo4j
4444
- NGINX
4545
- OceanBase
46+
- Ollama
4647
- OpenFGA
4748
- Oracle Free
4849
- Oracle XE

.github/ISSUE_TEMPLATE/feature.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ body:
4343
- Neo4j
4444
- NGINX
4545
- OceanBase
46+
- Ollama
4647
- OpenFGA
4748
- Oracle Free
4849
- Oracle XE

.github/dependabot.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,11 @@ updates:
224224
schedule:
225225
interval: "weekly"
226226
open-pull-requests-limit: 10
227+
- package-ecosystem: "gradle"
228+
directory: "/modules/ollama"
229+
schedule:
230+
interval: "weekly"
231+
open-pull-requests-limit: 10
227232
- package-ecosystem: "gradle"
228233
directory: "/modules/openfga"
229234
schedule:

.github/labeler.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@
139139
- changed-files:
140140
- any-glob-to-any-file:
141141
- modules/oceanbase/**/*
142+
"modules/ollama":
143+
- changed-files:
144+
- any-glob-to-any-file:
145+
- modules/ollama/**/*
142146
"modules/openfga":
143147
- changed-files:
144148
- any-glob-to-any-file:

.github/settings.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ labels:
196196
- name: modules/oceanbase
197197
color: '#006b75'
198198

199+
- name: modules/ollama
200+
color: '#006b75'
201+
199202
- name: modules/openfga
200203
color: '#006b75'
201204

docs/modules/ollama.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Ollama
2+
3+
Testcontainers module for [Ollama](https://hub.docker.com/r/ollama/ollama) .
4+
5+
## Ollama's usage examples
6+
7+
You can start an Ollama container instance from any Java application by using:
8+
9+
<!--codeinclude-->
10+
[Ollama container](../../modules/ollama/src/test/java/org/testcontainers/ollama/OllamaContainerTest.java) inside_block:container
11+
<!--/codeinclude-->
12+
13+
## Adding this module to your project dependencies
14+
15+
Add the following dependency to your `pom.xml`/`build.gradle` file:
16+
17+
=== "Gradle"
18+
```groovy
19+
testImplementation "org.testcontainers:ollama:{{latest_version}}"
20+
```
21+
22+
=== "Maven"
23+
```xml
24+
<dependency>
25+
<groupId>org.testcontainers</groupId>
26+
<artifactId>ollama</artifactId>
27+
<version>{{latest_version}}</version>
28+
<scope>test</scope>
29+
</dependency>
30+
```

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ nav:
9090
- modules/minio.md
9191
- modules/mockserver.md
9292
- modules/nginx.md
93+
- modules/ollama.md
9394
- modules/openfga.md
9495
- modules/pulsar.md
9596
- modules/qdrant.md

modules/ollama/build.gradle

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
description = "Testcontainers :: Ollama"
2+
3+
dependencies {
4+
api project(':testcontainers')
5+
6+
testImplementation 'org.assertj:assertj-core:3.25.1'
7+
testImplementation 'io.rest-assured:rest-assured:5.4.0'
8+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package org.testcontainers.ollama;
2+
3+
import com.github.dockerjava.api.DockerClient;
4+
import com.github.dockerjava.api.model.DeviceRequest;
5+
import com.github.dockerjava.api.model.Image;
6+
import com.github.dockerjava.api.model.Info;
7+
import com.github.dockerjava.api.model.RuntimeInfo;
8+
import org.testcontainers.DockerClientFactory;
9+
import org.testcontainers.containers.GenericContainer;
10+
import org.testcontainers.utility.DockerImageName;
11+
12+
import java.util.Collections;
13+
import java.util.List;
14+
import java.util.Map;
15+
16+
/**
17+
* Testcontainers implementation for Ollama.
18+
* <p>
19+
* Supported image: {@code ollama/ollama}
20+
* <p>
21+
* Exposed ports: 11434
22+
*/
23+
public class OllamaContainer extends GenericContainer<OllamaContainer> {
24+
25+
private static final DockerImageName DOCKER_IMAGE_NAME = DockerImageName.parse("ollama/ollama");
26+
27+
public OllamaContainer(String image) {
28+
this(DockerImageName.parse(image));
29+
}
30+
31+
public OllamaContainer(DockerImageName dockerImageName) {
32+
super(dockerImageName);
33+
dockerImageName.assertCompatibleWith(DOCKER_IMAGE_NAME);
34+
35+
Info info = this.dockerClient.infoCmd().exec();
36+
Map<String, RuntimeInfo> runtimes = info.getRuntimes();
37+
if (runtimes != null) {
38+
if (runtimes.containsKey("nvidia")) {
39+
withCreateContainerCmdModifier(cmd -> {
40+
cmd
41+
.getHostConfig()
42+
.withDeviceRequests(
43+
Collections.singletonList(
44+
new DeviceRequest()
45+
.withCapabilities(Collections.singletonList(Collections.singletonList("gpu")))
46+
.withCount(-1)
47+
)
48+
);
49+
});
50+
}
51+
}
52+
withExposedPorts(11434);
53+
}
54+
55+
/**
56+
* Commits the current file system changes in the container into a new image.
57+
* Should be used for creating an image that contains a loaded model.
58+
* @param imageName the name of the new image
59+
*/
60+
public void commitToImage(String imageName) {
61+
DockerImageName dockerImageName = DockerImageName.parse(getDockerImageName());
62+
if (!dockerImageName.equals(DockerImageName.parse(imageName))) {
63+
DockerClient dockerClient = DockerClientFactory.instance().client();
64+
List<Image> images = dockerClient.listImagesCmd().withReferenceFilter(imageName).exec();
65+
if (images.isEmpty()) {
66+
DockerImageName imageModel = DockerImageName.parse(imageName);
67+
dockerClient
68+
.commitCmd(getContainerId())
69+
.withRepository(imageModel.getUnversionedPart())
70+
.withLabels(Collections.singletonMap("org.testcontainers.sessionId", ""))
71+
.withTag(imageModel.getVersionPart())
72+
.exec();
73+
}
74+
}
75+
}
76+
77+
public String getEndpoint() {
78+
return "http://" + getHost() + ":" + getMappedPort(11434);
79+
}
80+
}

0 commit comments

Comments
 (0)