diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile new file mode 100644 index 00000000..ea8e72ec --- /dev/null +++ b/tools/docker/Dockerfile @@ -0,0 +1,58 @@ +FROM krallin/ubuntu-tini:16.04 + +LABEL name="Qinling" \ + description="Function Engine for OpenStack" \ + maintainers="Gaƫtan Trellu " + +RUN apt-get -qq update && \ + apt-get install -y \ + libffi-dev \ + libpq-dev \ + libssl-dev \ + libxml2-dev \ + libxslt1-dev \ + libyaml-dev \ + libmysqlclient-dev \ + python \ + python-dev \ + crudini \ + curl \ + git \ + gcc \ + libuv1 \ + libuv1-dev && \ + curl -f -o /tmp/get-pip.py https://bootstrap.pypa.io/3.2/get-pip.py && \ + python /tmp/get-pip.py && rm /tmp/get-pip.py && \ + pip install --upgrade pip + +RUN pip install pymysql psycopg2 py_mini_racer + +ENV QINLING_DIR="/opt/stack/qinling" \ + TMP_CONSTRAINTS="/tmp/upper-constraints.txt" \ + CONFIG_FILE="/etc/qinling/qinling.conf" \ + INI_SET="crudini --set /etc/qinling/qinling.conf" \ + MESSAGE_BROKER_URL="rabbit://guest:guest@rabbitmq:5672/" \ + DATABASE_URL="sqlite:///qinling.db" \ + UPGRADE_DB="false" \ + DEBIAN_FRONTEND="noninteractive" \ + QINLING_SERVER="all" \ + LOG_DEBUG="false" \ + AUTH_ENABLE="false" + +# We install dependencies separatly for a caching purpose +COPY requirements.txt "${QINLING_DIR}/" +RUN curl -o "${TMP_CONSTRAINTS}" \ + http://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt && \ + sed -i "/^qinling.*/d" "${TMP_CONSTRAINTS}" && \ + pip install -r "${QINLING_DIR}/requirements.txt" + +COPY . ${QINLING_DIR} + +RUN pip install -e "${QINLING_DIR}" && \ + mkdir /etc/qinling && \ + rm -rf /var/lib/apt/lists/* && \ + find ${QINLING_DIR} -name "*.sh" -exec chmod +x {} \; + +WORKDIR "${QINLING_DIR}" +EXPOSE 7070 +CMD "${QINLING_DIR}/tools/docker/start.sh" diff --git a/tools/docker/README.rst b/tools/docker/README.rst new file mode 100644 index 00000000..bec4a615 --- /dev/null +++ b/tools/docker/README.rst @@ -0,0 +1,95 @@ +Using Qinling with Docker +========================= + +Docker containers provide an easy way to quickly deploy independent or +networked Qinling instances in seconds. This guide describes the process +to launch an all-in-one Qinling container. + + +Docker Installation +------------------- + +The following links contain instructions to install latest Docker software: + +* `Docker Engine `_ +* `Docker Compose `_ + + +Build the Qinling Image Manually +-------------------------------- + +Execute the following command from the repository top-level directory:: + + docker build -t qinling -f tools/docker/Dockerfile . + +The Qinling Docker image has one build parameter: + + +Running Qinling using Docker Compose +------------------------------------ + +To launch Qinling in the single node configuration:: + + docker-compose -f tools/docker/docker-compose/infrastructure.yaml \ + -f tools/docker/docker-compose/qinling-single-node.yaml \ + -p qinling up -d + +To launch Qinling in the multi node configuration:: + + docker-compose -f tools/docker/docker-compose/infrastructure.yaml \ + -f tools/docker/docker-compose/qinling-multi-node.yaml \ + -p qinling up -d + +The `--build` option can be used when it is necessary to rebuild the image, +for example: + + docker-compose -f tools/docker/docker-compose/infrastructure.yaml \ + -f tools/docker/docker-compose/qinling-single-node.yaml \ + -p qinling up -d --build + +Running the Qinling client from the Docker Compose container +------------------------------------------------------------ + +To run the qinling client against the server in the container using the client +present in the container: + + docker run -it qinling_qinling1 qinling runtime list + +Configuring Qinling +------------------- + +The Docker image contains the minimal set of Qinling configuration parameters +by default: + ++--------------------+------------------+--------------------------------------+ +|Name |Default value | Description | ++====================+==================+======================================+ +|`MESSAGE_BROKER_URL`|rabbit://guest:gu\|The message broker URL | +| |est@rabbitmq:5672 | | ++--------------------+------------------+----------------------+---------------+ +|`DATABASE_URL` |sqlite:///qinling\|The database URL | +| |.db | | ++--------------------+------------------+----------------------+---------------+ +|`UPGRADE_DB` |false |If the `UPGRADE_DB` equals `true`, | +| | |a database upgrade will be launched | +| | |before Qinling main process | ++--------------------+------------------+----------------------+---------------+ +|`QINLING_SERVER` |all |Specifies which qinling server to | +| | |start by the launch script. | ++--------------------+------------------+----------------------+---------------+ +|`LOG_DEBUG` |false |If set to true, the logging level will| +| | |be set to DEBUG instead of the default| +| | |INFO level. | ++--------------------+------------------+----------------------+---------------+ + +The `/etc/qinling/qinling.conf` configuration file can be mounted to the Qinling +Docker container by uncommenting and editing the `volumes` sections in the Qinling +docker-compose files. + + +Using Qinling Client +-------------------- + +The Qinling API will be accessible from the host machine on the default +port 7070. Install `python-qinlingclient` on the host machine to +execute qinling commands. diff --git a/tools/docker/docker-compose/infrastructure.yaml b/tools/docker/docker-compose/infrastructure.yaml new file mode 100644 index 00000000..a4b2678e --- /dev/null +++ b/tools/docker/docker-compose/infrastructure.yaml @@ -0,0 +1,39 @@ +version: '3' +services: + + rabbitmq: + image: rabbitmq:3.7.2-management-alpine + restart: always + ports: + - "15672:15672" + networks: + - message-broker + hostname: rabbitmq + environment: + - RABBITMQ_VM_MEMORY_HIGH_WATERMARK=0.81 + - RABBITMQ_DEFAULT_USER=qinling + - RABBITMQ_DEFAULT_PASS=qinling + - RABBITMQ_DEFAULT_VHOST=qinling + + mysql: + image: mysql:8.0.3 + restart: always + ports: + - "3306:3306" + volumes: + - mysql:/var/lib/mysql + networks: + - database + environment: + - MYSQL_ROOT_PASSWORD=qinling + - MYSQL_DATABASE=qinling + - MYSQL_USER=qinling + - MYSQL_PASSWORD=qinling + +volumes: + rabbitmq: + mysql: + +networks: + database: + message-broker: diff --git a/tools/docker/docker-compose/qinling-multi-node.yaml b/tools/docker/docker-compose/qinling-multi-node.yaml new file mode 100644 index 00000000..b1c0a5f6 --- /dev/null +++ b/tools/docker/docker-compose/qinling-multi-node.yaml @@ -0,0 +1,34 @@ +version: '3' +services: + qinling-api: + build: + context: ../../.. + dockerfile: tools/docker/Dockerfile + restart: always + ports: + - "7070:7070" + networks: + database: + message-broker: + env_file: + - qinling.env +# volumes: +# - "/path/to/qinling.conf:/etc/qinling/qinling.conf" + environment: + - QINLING_SERVER=api + - UPGRADE_DB=true + + qinling-engine: + build: + context: ../../.. + dockerfile: tools/docker/Dockerfile + restart: always + networks: + - database + - message-broker + env_file: + - qinling.env +# volumes: +# - "/path/to/qinling.conf:/etc/qinling/qinling.conf" + environment: + - QINLING_SERVER=engine diff --git a/tools/docker/docker-compose/qinling-single-node.yaml b/tools/docker/docker-compose/qinling-single-node.yaml new file mode 100644 index 00000000..4d929e74 --- /dev/null +++ b/tools/docker/docker-compose/qinling-single-node.yaml @@ -0,0 +1,18 @@ +version: '3' +services: + qinling: + build: + context: ../../.. + dockerfile: "tools/docker/Dockerfile" + restart: always + ports: + - "7070:7070" + networks: + - database + - message-broker + env_file: + - qinling.env +# volumes: +# - "/path/to/qinling.conf:/etc/qinling/qinling.conf" + environment: + - UPGRADE_DB=true diff --git a/tools/docker/docker-compose/qinling.env b/tools/docker/docker-compose/qinling.env new file mode 100644 index 00000000..90118656 --- /dev/null +++ b/tools/docker/docker-compose/qinling.env @@ -0,0 +1,3 @@ +MESSAGE_BROKER_URL=rabbit://qinling:qinling@rabbitmq:5672/qinling +DATABASE_URL=mysql+pymysql://qinling:qinling@mysql:3306/qinling +AUTH_ENABLE=false diff --git a/tools/docker/start.sh b/tools/docker/start.sh new file mode 100755 index 00000000..3fae42bd --- /dev/null +++ b/tools/docker/start.sh @@ -0,0 +1,30 @@ +#!/bin/bash +set -e + +# If a Qinling config doesn't exist we should create it and fill in with +# parameters +if [ ! -f ${CONFIG_FILE} ]; then + oslo-config-generator \ + --config-file "${QINLING_DIR}/tools/config/config-generator.qinling.conf" \ + --output-file "${CONFIG_FILE}" + + ${INI_SET} DEFAULT debug "${LOG_DEBUG}" + ${INI_SET} DEFAULT auth_type ${AUTH_TYPE} + ${INI_SET} DEFAULT transport_url "${MESSAGE_BROKER_URL}" + ${INI_SET} oslo_policy policy_file "${QINLING_DIR}/etc/qinling/policy.json" + ${INI_SET} pecan auth_enable ${AUTH_ENABLE} + ${INI_SET} database connection "${DATABASE_URL}" +fi + +if [ ${DATABASE_URL} == "sqlite:///qinling.db" -a ! -f ./qinling.db ] +then + qinling-db-manage --config-file "${CONFIG_FILE}" upgrade head +fi + +if "${UPGRADE_DB}"; +then + qinling-db-manage --config-file "${CONFIG_FILE}" upgrade head +fi + +qinling-api --config-file "${CONFIG_FILE}" +qinling-engine --config-file "${CONFIG_FILE}"