Skip to content

Commit 009849e

Browse files
authored
Merge pull request #49 from meilisearch/feature/add-docker-support
Add Docker support for containerized deployments
2 parents c71ac74 + 7f41370 commit 009849e

File tree

5 files changed

+259
-3
lines changed

5 files changed

+259
-3
lines changed

.dockerignore

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Python cache
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.so
6+
.Python
7+
build/
8+
develop-eggs/
9+
dist/
10+
downloads/
11+
eggs/
12+
.eggs/
13+
lib/
14+
lib64/
15+
parts/
16+
sdist/
17+
var/
18+
wheels/
19+
*.egg-info/
20+
.installed.cfg
21+
*.egg
22+
23+
# Virtual environments
24+
.venv/
25+
venv/
26+
ENV/
27+
env/
28+
29+
# Testing
30+
.pytest_cache/
31+
.coverage
32+
htmlcov/
33+
.tox/
34+
.hypothesis/
35+
36+
# IDE
37+
.vscode/
38+
.idea/
39+
*.swp
40+
*.swo
41+
*~
42+
43+
# Git
44+
.git/
45+
.gitignore
46+
47+
# Documentation
48+
docs/
49+
*.md
50+
!README.md
51+
52+
# CI/CD
53+
.github/
54+
55+
# Development files
56+
.env
57+
.env.*
58+
CLAUDE.md
59+
60+
# Logs
61+
logs/
62+
*.log
63+
64+
# macOS
65+
.DS_Store
66+
67+
# Test data
68+
tests/
69+
data.ms/

.github/workflows/publish.yml

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Publish to PyPI
1+
name: Publish to PyPI and Docker Hub
22

33
on:
44
push:
@@ -24,7 +24,7 @@ jobs:
2424
echo "version_changed=true" >> $GITHUB_OUTPUT
2525
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
2626
27-
build-and-publish:
27+
build-and-publish-pypi:
2828
needs: check-version
2929
if: needs.check-version.outputs.version_changed == 'true'
3030
runs-on: ubuntu-latest
@@ -54,4 +54,44 @@ jobs:
5454
uses: pypa/gh-action-pypi-publish@release/v1
5555
with:
5656
verbose: true
57-
print-hash: true
57+
print-hash: true
58+
59+
build-and-publish-docker:
60+
needs: check-version
61+
if: needs.check-version.outputs.version_changed == 'true'
62+
runs-on: ubuntu-latest
63+
64+
steps:
65+
- uses: actions/checkout@v3
66+
67+
- name: Set up QEMU
68+
uses: docker/setup-qemu-action@v3
69+
70+
- name: Set up Docker Buildx
71+
uses: docker/setup-buildx-action@v3
72+
73+
- name: Log in to Docker Hub
74+
uses: docker/login-action@v3
75+
with:
76+
username: ${{ secrets.DOCKERHUB_USERNAME }}
77+
password: ${{ secrets.DOCKERHUB_TOKEN }}
78+
79+
- name: Extract metadata
80+
id: meta
81+
uses: docker/metadata-action@v5
82+
with:
83+
images: meilisearch/meilisearch-mcp
84+
tags: |
85+
type=raw,value=${{ needs.check-version.outputs.new_version }}
86+
type=raw,value=latest
87+
88+
- name: Build and push Docker image
89+
uses: docker/build-push-action@v5
90+
with:
91+
context: .
92+
platforms: linux/amd64,linux/arm64
93+
push: true
94+
tags: ${{ steps.meta.outputs.tags }}
95+
labels: ${{ steps.meta.outputs.labels }}
96+
cache-from: type=gha
97+
cache-to: type=gha,mode=max

Dockerfile

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Use Python 3.12 slim image for smaller size
2+
FROM python:3.12-slim
3+
4+
# Set working directory
5+
WORKDIR /app
6+
7+
# Install system dependencies
8+
RUN apt-get update && apt-get install -y --no-install-recommends \
9+
curl \
10+
&& rm -rf /var/lib/apt/lists/*
11+
12+
# Install uv for faster Python package management
13+
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
14+
ENV PATH="/root/.local/bin:${PATH}"
15+
16+
# Copy project files
17+
COPY pyproject.toml README.md ./
18+
COPY src/ ./src/
19+
20+
# Install the package
21+
RUN uv pip install --system .
22+
23+
# Set default environment variables
24+
ENV MEILI_HTTP_ADDR=http://meilisearch:7700
25+
ENV MEILI_MASTER_KEY=""
26+
27+
# Run the MCP server
28+
CMD ["python", "-m", "src.meilisearch_mcp"]

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,48 @@ source .venv/bin/activate # On Windows: .venv\Scripts\activate
137137
uv pip install -e .
138138
```
139139

140+
### Using Docker
141+
142+
Perfect for containerized environments like n8n workflows!
143+
144+
#### From Docker Hub (Recommended)
145+
146+
```bash
147+
# Pull the latest image
148+
docker pull meilisearch/meilisearch-mcp:latest
149+
150+
# Or a specific version
151+
docker pull meilisearch/meilisearch-mcp:0.5.0
152+
153+
# Run the container
154+
docker run -it \
155+
-e MEILI_HTTP_ADDR=http://your-meilisearch:7700 \
156+
-e MEILI_MASTER_KEY=your-master-key \
157+
meilisearch/meilisearch-mcp:latest
158+
```
159+
160+
#### Build from Source
161+
162+
```bash
163+
# Build your own image
164+
docker build -t meilisearch-mcp .
165+
docker run -it \
166+
-e MEILI_HTTP_ADDR=http://your-meilisearch:7700 \
167+
-e MEILI_MASTER_KEY=your-master-key \
168+
meilisearch-mcp
169+
```
170+
171+
#### Integration with n8n
172+
173+
For n8n workflows, you can use the Docker image directly in your setup:
174+
```yaml
175+
meilisearch-mcp:
176+
image: meilisearch/meilisearch-mcp:latest
177+
environment:
178+
- MEILI_HTTP_ADDR=http://meilisearch:7700
179+
- MEILI_MASTER_KEY=masterKey
180+
```
181+
140182
## 🛠️ What Can You Do?
141183
142184
<details>

tests/test_docker_integration.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
"""
2+
Integration tests for Docker image build.
3+
4+
These tests verify that the Docker image can be built successfully.
5+
"""
6+
import subprocess
7+
import pytest
8+
import shutil
9+
10+
11+
# Check if Docker is available
12+
def docker_available():
13+
"""Check if Docker is available on the system."""
14+
if not shutil.which("docker"):
15+
return False
16+
# Try to run docker version to ensure it's working
17+
try:
18+
result = subprocess.run(
19+
["docker", "version"],
20+
capture_output=True,
21+
text=True,
22+
timeout=5
23+
)
24+
return result.returncode == 0
25+
except (subprocess.TimeoutExpired, FileNotFoundError):
26+
return False
27+
28+
29+
# Skip all tests in this module if Docker is not available
30+
pytestmark = pytest.mark.skipif(
31+
not docker_available(),
32+
reason="Docker not available on this system"
33+
)
34+
35+
36+
def test_docker_build():
37+
"""Test that the Docker image can be built successfully."""
38+
result = subprocess.run(
39+
["docker", "build", "-t", "meilisearch-mcp-test", "."],
40+
capture_output=True,
41+
text=True
42+
)
43+
assert result.returncode == 0, f"Docker build failed: {result.stderr}"
44+
45+
46+
def test_docker_image_runs():
47+
"""Test that the Docker image can run and show help."""
48+
# First build the image
49+
build_result = subprocess.run(
50+
["docker", "build", "-t", "meilisearch-mcp-test", "."],
51+
capture_output=True,
52+
text=True
53+
)
54+
if build_result.returncode != 0:
55+
pytest.skip(f"Docker build failed: {build_result.stderr}")
56+
57+
# Try to run the container and check it starts
58+
result = subprocess.run(
59+
[
60+
"docker", "run", "--rm",
61+
"-e", "MEILI_HTTP_ADDR=http://localhost:7700",
62+
"-e", "MEILI_MASTER_KEY=test",
63+
"meilisearch-mcp-test",
64+
"python", "-c", "import src.meilisearch_mcp; print('MCP module loaded successfully')"
65+
],
66+
capture_output=True,
67+
text=True,
68+
timeout=30
69+
)
70+
71+
assert result.returncode == 0, f"Docker run failed: {result.stderr}"
72+
assert "MCP module loaded successfully" in result.stdout
73+
74+
75+
if __name__ == "__main__":
76+
# Run tests
77+
pytest.main([__file__, "-v"])

0 commit comments

Comments
 (0)