Skip to content

Commit 2861570

Browse files
authored
Merge pull request #81 from marshallmcdonnell/add-docker
Add docker
2 parents 16bc429 + f52e31d commit 2861570

11 files changed

Lines changed: 283 additions & 2 deletions

File tree

.github/workflows/docs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ on: [push, pull_request, delete]
99
jobs:
1010
docs:
1111
runs-on: ubuntu-latest
12+
if: github.repository == 'usnistgov/AFL-agent'
1213
steps:
1314
- name: Free Disk Space (Ubuntu)
1415
uses: jlumbroso/free-disk-space@v1.3.1
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Publish to GitHub Container Registry
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
workflow_dispatch: {}
8+
9+
jobs:
10+
build-and-push-agent:
11+
runs-on: ubuntu-latest
12+
13+
permissions:
14+
contents: read
15+
packages: write
16+
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
21+
- name: Set lowercase repository name
22+
run: echo "REPO_LOWER=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
23+
24+
- name: Set up Docker Buildx
25+
uses: docker/setup-buildx-action@v3
26+
27+
- name: Log in to GitHub Container Registry
28+
uses: docker/login-action@v3
29+
with:
30+
registry: ghcr.io
31+
username: ${{ github.actor }}
32+
password: ${{ secrets.GITHUB_TOKEN }}
33+
34+
- name: Build and push Agent image
35+
uses: docker/build-push-action@v5
36+
with:
37+
context: .
38+
file: ./docker/Dockerfile.agent
39+
push: true
40+
tags: |
41+
ghcr.io/${{ env.REPO_LOWER }}/agent:latest
42+
ghcr.io/${{ env.REPO_LOWER }}/agent:${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || github.sha }}
43+
ghcr.io/${{ env.REPO_LOWER }}/agent:${{ github.sha }}
44+
cache-from: type=registry,ref=ghcr.io/${{ env.REPO_LOWER }}/agent:buildcache
45+
cache-to: type=registry,ref=ghcr.io/${{ env.REPO_LOWER }}/agent:buildcache,mode=max

.github/workflows/publish_pypi.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ permissions:
1111
jobs:
1212
build-and-publish:
1313
runs-on: ubuntu-latest
14+
if: github.repository == 'usnistgov/AFL-agent'
1415
steps:
1516
- uses: actions/checkout@v4
1617
- uses: actions/setup-python@v5
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: Integration Tests
2+
3+
# TODO: remove the add-docker branch before merging to main
4+
on:
5+
push:
6+
branches: [ main, add-docker ]
7+
pull_request:
8+
branches: [ main, add-docker ]
9+
workflow_dispatch: {}
10+
11+
jobs:
12+
integration:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v4
17+
18+
- name: Build and start stack
19+
run: |
20+
docker compose up -d --build
21+
- name: Wait for services to become healthy
22+
run: |
23+
set -euo pipefail
24+
tiled_id=$(docker compose ps -q tiled)
25+
agent_id=$(docker compose ps -q agent)
26+
for i in $(seq 1 30); do
27+
th=$(docker inspect --format '{{.State.Health.Status}}' "$tiled_id") || true
28+
ah=$(docker inspect --format '{{.State.Health.Status}}' "$agent_id") || true
29+
if [ "$th" = "healthy" ] && [ "$ah" = "healthy" ]; then
30+
echo "Services healthy"; exit 0
31+
fi
32+
sleep 2
33+
done
34+
echo "Services did not become healthy" >&2
35+
docker compose ps
36+
exit 1
37+
38+
- name: Smoke test Tiled API
39+
run: |
40+
set -euo pipefail
41+
code=$(curl -s -o /dev/null -w "%{http_code}" -H "X-Tiled-Api-Key: devkey" http://localhost:8000/api/v1/metadata/)
42+
if [ "$code" != "200" ] && [ "$code" != "401" ]; then
43+
echo "Unexpected Tiled status: $code" >&2
44+
exit 1
45+
fi
46+
47+
- name: Smoke test Agent driver status
48+
run: |
49+
set -euo pipefail
50+
code=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:5003/driver_status)
51+
body=$(curl -s http://localhost:5003/driver_status)
52+
if [ "$code" != "200" ]; then
53+
echo "Unexpected agent status: $code" >&2
54+
exit 1
55+
fi
56+
echo "$body" | grep -q "mock_mode"
57+
58+
- name: Teardown
59+
if: always()
60+
run: docker compose down -v

.github/workflows/tests.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
name: Run Tests
22

3+
# TODO: remove the add-docker branch before merging to main
34
on:
45
push:
5-
branches: [ 'main' ]
6+
branches: [ 'main', 'add-docker' ]
67
pull_request:
78
branches: [ '*' ]
89

@@ -29,7 +30,7 @@ jobs:
2930
- name: Install dependencies
3031
run: |
3132
python -m pip install --upgrade pip
32-
pip install -e ".[dev]"
33+
pip install -e ".[dev,mlmodels]"
3334
3435
- name: Run tests
3536
run: |

AFL/double_agent/AgentDriver.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ def __init__(
261261

262262
def status(self):
263263
status = []
264+
if 'mock_mode' in self.config:
265+
status.append(f'mock_mode: {self.config["mock_mode"]}')
264266
if self.input:
265267
status.append(f'Input Dims: {self.input.sizes}')
266268
if self.pipeline:

docker-compose.yaml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
services:
2+
tiled:
3+
build:
4+
context: .
5+
dockerfile: docker/Dockerfile.tiled
6+
ports:
7+
- "8000:8000"
8+
environment:
9+
- TILED_PORT=8000
10+
volumes:
11+
- tiled-data:/app/data
12+
healthcheck:
13+
test: ["CMD", "python", "-c", "import requests,sys; r=requests.get('http://localhost:8000/api/v1/metadata', headers={'X-Tiled-Api-Key':'devkey'}); sys.exit(0 if r.status_code in (200,401,403,404) else 1)"]
14+
interval: 30s
15+
timeout: 10s
16+
retries: 5
17+
start_period: 10s
18+
19+
agent:
20+
build:
21+
context: .
22+
dockerfile: docker/Dockerfile.agent
23+
ports:
24+
- "5003:5003"
25+
environment:
26+
- AFL_AGENT_PORT=5003
27+
- TILED_SERVER=http://tiled:8000
28+
- TILED_API_KEY=devkey
29+
depends_on:
30+
- tiled
31+
volumes:
32+
- ./docker/config/agent-config.json:/root/.afl/config.json:ro
33+
command: ["python", "-m", "AFL.double_agent.AgentDriver"]
34+
35+
volumes:
36+
tiled-data:

docker/Dockerfile.agent

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Dockerfile for DoubleAgent service
2+
FROM python:3.12-slim AS builder
3+
4+
WORKDIR /build
5+
6+
RUN apt-get update && apt-get install -y --no-install-recommends \
7+
build-essential \
8+
git \
9+
ca-certificates \
10+
&& rm -rf /var/lib/apt/lists/*
11+
12+
COPY . .
13+
RUN python -m pip install --user --no-cache-dir --upgrade pip setuptools wheel
14+
RUN python -m pip install --user --no-cache-dir .[automation,apdist,mlmodels,tensorflow]
15+
# Install AFL-automation from fork (add-docker branch)
16+
#
17+
# TODO: change this to https://github.com/usnistgov/AFL-automation
18+
# if this PR gets merged: https://github.com/usnistgov/AFL-automation/pull/120
19+
RUN python -m pip install --user --no-cache-dir \
20+
"AFL-automation @ git+https://github.com/marshallmcdonnell/AFL-automation@add-docker"
21+
22+
FROM python:3.12-slim
23+
WORKDIR /app
24+
25+
RUN apt-get update && apt-get install -y --no-install-recommends \
26+
ca-certificates \
27+
curl \
28+
&& rm -rf /var/lib/apt/lists/*
29+
30+
# Copy installed packages from builder
31+
COPY --from=builder /root/.local /root/.local
32+
33+
# Make sure scripts in .local are usable
34+
ENV PATH=/root/.local/bin:$PATH \
35+
PYTHONUNBUFFERED=1 \
36+
PYTHONDONTWRITEBYTECODE=1 \
37+
PYTHONPATH=/app:$PYTHONPATH \
38+
AFL_AGENT_PORT=5003 \
39+
TILED_SERVER=http://tiled:8000 \
40+
TILED_API_KEY=devkey
41+
42+
# Create configuration directory
43+
RUN mkdir -p /root/.afl
44+
45+
# Copy agent configuration
46+
COPY docker/config/agent-config.json /root/.afl/config.json
47+
48+
# Expose the agent port
49+
EXPOSE 5003
50+
51+
# Health check against driver_status endpoint
52+
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
53+
CMD curl -f http://localhost:5003/driver_status || exit 1
54+
55+
# Default entry point: run the agent driver
56+
CMD ["python", "-m", "AFL.double_agent.AgentDriver"]

docker/Dockerfile.tiled

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Dockerfile for Tiled Data Catalog Server
2+
# Tiled provides a HTTP REST API for storing and querying time-series and tabular data
3+
4+
FROM python:3.12-slim
5+
6+
WORKDIR /app
7+
8+
# Install system dependencies
9+
RUN apt-get update && apt-get install -y --no-install-recommends \
10+
ca-certificates \
11+
&& rm -rf /var/lib/apt/lists/*
12+
13+
# Install Tiled server with optional dependencies for better database support
14+
RUN pip install --no-cache-dir \
15+
tiled[server] \
16+
aiosqlite
17+
18+
# Create data directories
19+
RUN mkdir -p /app/data /root/.afl
20+
21+
# Copy Tiled configuration for container use
22+
COPY docker/config/tiled-config.yml /app/config.yml
23+
24+
# Set environment variables
25+
ENV PYTHONUNBUFFERED=1 \
26+
PYTHONDONTWRITEBYTECODE=1 \
27+
TILED_PORT=8000
28+
29+
# Expose the Tiled server port
30+
EXPOSE 8000
31+
32+
# Health check against root metadata endpoint; 200/404/403 all indicate server responding
33+
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
34+
CMD python -c "import requests; r = requests.get('http://localhost:8000'); exit(0 if r.status_code in [200, 404, 403] else 1)" || exit 1
35+
36+
# Default entry point: run the Tiled server. Note: `tiled serve config <file>` is the correct syntax.
37+
CMD ["tiled", "serve", "config", "/app/config.yml"]

docker/config/agent-config.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"26/16/01 11:00:00.000000": {
3+
"owner_email": "",
4+
"system_serial": "Default",
5+
"tiled_server": "http://tiled:8000",
6+
"tiled_api_key": "devkey",
7+
"bind_address": "0.0.0.0",
8+
"ports": {
9+
"DoubleAgentDriver": 5003
10+
},
11+
"driver_custom_configs": {
12+
"DoubleAgentDriver": {
13+
"_classname": "AFL.double_agent.AgentDriver.DoubleAgentDriver",
14+
"overrides": {
15+
"mock_mode": true,
16+
"pipeline": {},
17+
"tiled_input_groups": []
18+
}
19+
}
20+
},
21+
"ca_status_enabled": false,
22+
"ca_status_ports": {}
23+
}
24+
}

0 commit comments

Comments
 (0)