Skip to content

Commit f77c4a8

Browse files
authored
Allow deployment of multiple sets of services (#289)
Update the compose file to allow easy deployment of multiple sets of services: - ports are not bound by default, but through `compose.ports.yaml` - containers do not have a fixed name
1 parent 8e62afb commit f77c4a8

7 files changed

Lines changed: 59 additions & 49 deletions

File tree

.github/workflows/tests.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,18 @@ jobs:
2828
# https://github.com/docker/compose/issues/10596
2929
- name: Start services
3030
run: |
31-
profiles="--profile python"
31+
services="python-api"
3232
if [ "${{ matrix.php_api }}" = "true" ]; then
33-
profiles="$profiles --profile php"
33+
services="$services php-api"
3434
fi
35-
docker compose $profiles up --detach --wait --remove-orphans || exit $(docker compose ps -q | xargs docker inspect -f '{{.State.ExitCode}}' | grep -v '^0' | wc -l)
35+
docker compose up $services --detach --wait --remove-orphans || exit $(docker compose ps -q | xargs docker inspect -f '{{.State.ExitCode}}' | grep -v '^0' | wc -l)
3636
3737
- name: Run tests
3838
run: |
3939
marker="${{ matrix.php_api == true && 'php_api' || 'not php_api' }} and ${{ matrix.mutations == true && 'mut' || 'not mut' }}"
40-
docker exec openml-python-rest-api coverage run -m pytest -n auto -v -m "$marker"
40+
docker compose exec python-api coverage run -m pytest -n auto -v -m "$marker"
4141
- name: Produce coverage report
42-
run: docker exec openml-python-rest-api coverage xml
42+
run: docker compose exec python-api coverage xml
4343
- name: Upload results to Codecov
4444
uses: codecov/codecov-action@v4
4545
with:

compose.ports.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
services:
2+
database:
3+
ports:
4+
- "3306:3306"
5+
6+
docs:
7+
ports:
8+
- "8000:8000"
9+
10+
elasticsearch:
11+
ports:
12+
- "9200:9200"
13+
- "9300:9300"
14+
15+
php-api:
16+
ports:
17+
- "8002:80"
18+
19+
python-api:
20+
ports:
21+
- "8001:8000"
Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
services:
22
database:
3-
profiles: ["python", "php", "all"]
43
image: "openml/test-database:v0.1.20260204"
5-
container_name: "openml-test-database"
64
environment:
75
MYSQL_ROOT_PASSWORD: ok
8-
ports:
9-
- "3306:3306"
106
healthcheck:
117
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
128
start_period: 30s
@@ -20,19 +16,12 @@ services:
2016
build:
2117
context: .
2218
dockerfile: docker/docs/Dockerfile
23-
ports:
24-
- "8000:8000"
2519
volumes:
2620
- .:/docs
2721

2822
elasticsearch:
29-
profiles: ["php", "all"]
3023
image: docker.elastic.co/elasticsearch/elasticsearch:6.8.23
31-
container_name: "openml-elasticsearch"
3224
platform: "linux/amd64"
33-
ports:
34-
- "9200:9200" # also known as /es (nginx)
35-
- "9300:9300"
3625
env_file: docker/elasticsearch/.env
3726
healthcheck:
3827
test: curl 127.0.0.1:9200/_cluster/health | grep -e "green"
@@ -50,12 +39,9 @@ services:
5039
memory: 250M
5140

5241
php-api:
53-
profiles: ["php", "all"]
42+
profiles: ["apis", "all"]
5443
image: "openml/php-rest-api:v1.2.4"
55-
container_name: "openml-php-rest-api"
5644
env_file: docker/php/.env
57-
ports:
58-
- "8002:80"
5945
depends_on:
6046
elasticsearch:
6147
condition: service_healthy
@@ -69,13 +55,10 @@ services:
6955
interval: 1m
7056

7157
python-api:
72-
profiles: ["python", "all"]
73-
container_name: "openml-python-rest-api"
58+
profiles: ["apis", "all"]
7459
build:
7560
context: .
7661
dockerfile: docker/python/Dockerfile
77-
ports:
78-
- "8001:8000"
7962
volumes:
8063
- .:/app
8164
- ./src/config.toml:/config/config.toml

docs/contributing/contributing.md

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,31 +33,36 @@ required services for development is through [`docker compose`](https://docs.doc
3333
```bash
3434
docker compose --profile all up -d
3535
```
36+
or, to expose the services to the host network at the same time:
37+
```bash
38+
docker compose -f compose.yaml -f compose.ports.yaml --profile all up -d
39+
```
3640

37-
This will spin up 5 containers, as defined in the `docker-compose.yaml` file:
41+
This will spin up 5 services, as defined in the `compose.yaml` file:
3842

39-
- `openml-test-database`: this is a mysql database prepopulated with test data.
40-
It is reachable from the host machine with port `3306`, by default it is configured
41-
to have a root user with password `"ok"`.
42-
- `server-api-docs-1`: this container serves project documentation at `localhost:8000`.
43+
- `database`: this is a mysql database prepopulated with test data.
44+
By default it is configured to have a root user with password `"ok"`.
45+
- `docs`: this container serves project documentation at `localhost:8000`.
4346
These pages are built from the documents in the `docs/` directory of this repository,
4447
whenever you edit and save a file there, the page will immediately be updated.
45-
- `openml-php-rest-api`: this container serves the old PHP REST API at `localhost:8002`.
48+
- `elasticsearch`: Elasticsearch, required for the PHP REST API to function.
49+
- `php-api`: this container serves the old PHP REST API at `localhost:8002`.
4650
For example, visit [http://localhost:8002/api/v1/json/data/1](http://localhost:8002/api/v1/json/data/1)
4751
to fetch a JSON description of dataset 1.
48-
- `openml-elasticsearch`: Elasticsearch, required for the PHP REST API to function.
49-
- `openml-python-rest-api`: this container serves the new Python-based REST API at `localhost:8001`.
52+
- `python-api`: this container serves the new Python-based REST API at `localhost:8001`.
5053
For example, visit [http://localhost:8001/docs](http://localhost:8001/docs) to see
5154
the REST API documentation. Changes to the code in `src/` will be reflected in this
5255
container.
5356

57+
Exposing ports to the host network isn't needed for development, but may be useful to inspect responses directly from the host machine.
58+
5459
!!! note
5560
On arm-based Macs, you need to enable Rosetta emulation for Docker for the Elasticsearch container to work.
5661

5762
We can now run the full test suite, which takes about 4 minutes:
5863

5964
```bash
60-
docker exec openml-python-rest-api python -m pytest tests
65+
docker compose exec python-api python -m pytest tests
6166
```
6267
There are three important [test markers](https://docs.pytest.org/en/7.1.x/example/markers.html) to be aware of:
6368

@@ -69,15 +74,15 @@ In many cases during development it's sufficient to either run with `not php_api
6974
The `not slow` is only needed if a slow test would be included in your test selection. In many cases, you might prefer to only run the specific tests (or test modules) that you are working on and excluding it through markers may be unnecessary.
7075
Examples:
7176

72-
- `docker exec openml-python-rest-api python -m pytest tests -m "not php_api and not slow"`, here the test selection is made primarily through markers. This command takes a few seconds.
73-
- `docker exec openml-python-rest-api python -m pytest tests/routers/openml/dataset_tag_test.py`, here the test selection is made through specifying the file with tests. Since this test file naturally includes neither migration tests (in `tests/routers/openml/migration`) nor the slow test (at `tests/routers/openml/datasets_list_datasets_test.py`), excluding tests through markers is unnecessary. This command takes a few seconds.
77+
- `docker compose exec python-api python -m pytest tests -m "not php_api and not slow"`, here the test selection is made primarily through markers. This command takes a few seconds.
78+
- `docker compose exec python-api python -m pytest tests/routers/openml/dataset_tag_test.py`, here the test selection is made through specifying the file with tests. Since this test file naturally includes neither migration tests (in `tests/routers/openml/migration`) nor the slow test (at `tests/routers/openml/datasets_list_datasets_test.py`), excluding tests through markers is unnecessary. This command takes a few seconds.
7479

7580

7681
You don't always need every container, often just having a database and the Python-based
7782
REST API may be enough. In that case, only specify those services:
7883

7984
```bash
80-
docker compose --profile python up -d
85+
docker compose up python-api -d
8186
```
8287

8388
Refer to the `docker compose` documentation for more uses.
@@ -87,18 +92,18 @@ Refer to the `docker compose` documentation for more uses.
8792

8893
### Connecting to containers
8994

90-
To connect to a container, run:
95+
To connect to a container of a service, run:
9196

9297
```bash
93-
docker exec -it CONTAINER_NAME /bin/bash
98+
docker compose exec SERVICE_NAME /bin/bash
9499
```
95100

96-
where `CONTAINER_NAME` is the name of the container. If you are unsure of your container
97-
name, then `docker container ls` may help you find it. Assuming the default container
101+
where `SERVICE_NAME` is the name of the service. If you are unsure of the service
102+
name, then `docker compose ps` may help you find it. Assuming the default service
98103
names are used, you may connect to the Python-based REST API container using:
99104

100105
```bash
101-
docker exec -it openml-python-rest-api /bin/bash
106+
docker compose exec python-api /bin/bash
102107
```
103108

104109
This is useful, for example, to run unit tests in the container:

docs/installation.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ See also ["Contributing"](contributing/contributing.md).
44

55
The primary way to run this service is through a Docker container.
66
The REST API needs to be able to connect to a MySQL database with the OpenML "openml" and "openml_expdb" databases.
7-
The `docker-compose.yaml` file of this project defines these together out of the box.
7+
The `compose.yaml` file of this project defines these together out of the box.
88
This is useful for development purposes, but the database does not persist between restarts in the current configuration.
99
By default, the current code is also mounted into the Python REST API container (again, for development purposes).
1010

11-
For development, it should suffice to run the services from a fresh clone by running `docker compose --profile "python" up -d`.
12-
The REST API will be exposed on port 8001 on the host machine. To visit the Swagger Docs, visit http://localhost:8001/docs.
11+
For development, it should suffice to run the services from a fresh clone by running `docker compose up python-api -d`.
12+
If you want to make sure to bind the exposed container ports to the host machine then you will need to use the `compose.ports.yaml` file too (`docker compose -f compose.yaml -f compose.ports.yaml up python-api -d`).
13+
The REST API will then be exposed on port 8001 on the host machine. To visit the Swagger Docs, visit http://localhost:8001/docs.
1314

14-
Once the containers are started, you can run tests with `docker exec -it openml-python-rest-api python -m pytest -m "not php_api" tests`.
15-
For migration testing, which compares output of the Python-based REST API with the old PHP-based one, also start the PHP server (`docker compose --profile "php" --profile "python" up -d`) and include tests with the `php_api` marker/fixture: `docker exec -it openml-python-rest-api python -m pytest tests`.
15+
Once the containers are started, you can run tests with `docker compose exec python-api python -m pytest -m "not php_api" tests`.
16+
For migration testing, which compares output of the Python-based REST API with the old PHP-based one, also start the PHP server (`docker compose --profile "apis" up -d`) and include tests with the `php_api` marker/fixture: `docker compose exec python-api python -m pytest tests`.
1617

1718
!!! note
1819

@@ -21,4 +22,4 @@ For migration testing, which compares output of the Python-based REST API with t
2122
When we start testing more upload functionality, for which the PHP API needs built indices, we'll work on an ES image with prebuilt indices.
2223

2324
Information for a production deployment will follow, in a nutshell you need to configure the REST API to connect to a persistent database,
24-
which can be the one defined in `docker-compose.yaml` if has an appropriately mounted volume.
25+
which can be the one defined in `compose.yaml` if it has an appropriately mounted volume.

src/config.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ allow_test_api_keys=true
88
root_path=""
99

1010
[databases.defaults]
11-
host="openml-test-database"
11+
host="database"
1212
port="3306"
1313
# SQLAlchemy `dialect` and `driver`: https://docs.sqlalchemy.org/en/20/dialects/index.html
1414
drivername="mysql+aiomysql"

tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from main import create_api
1717
from routers.dependencies import expdb_connection, userdb_connection
1818

19-
PHP_API_URL = "http://openml-php-rest-api:80/api/v1/json"
19+
PHP_API_URL = "http://php-api:80/api/v1/json"
2020

2121

2222
@contextlib.asynccontextmanager

0 commit comments

Comments
 (0)