diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..05c0b4d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,28 @@ +* +!LICENSE + +# opentts-abc +!opentts-abc/setup.py +!opentts-abc/LICENSE +!opentts-abc/MANIFEST.in +!opentts-abc/opentts_abc/*.py +!opentts-abc/opentts_abc/VERSION + +# Mimic 3 TTS +!mimic3-tts/setup.py +!mimic3-tts/LICENSE +!mimic3-tts/MANIFEST.in +!mimic3-tts/requirements.txt +!mimic3-tts/mimic3_tts/*.py +!mimic3-tts/mimic3_tts/VERSION + +# HTTP server +!mimic3-http/setup.py +!mimic3-http/LICENSE +!mimic3-http/MANIFEST.in +!mimic3-http/requirements.txt +!mimic3-http/mimic3_http/css/ +!mimic3-http/mimic3_http/img/ +!mimic3-http/mimic3_http/templates/ +!mimic3-http/mimic3_http/*.py +!mimic3-http/mimic3_http/VERSION diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..155540b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,82 @@ +# Copyright 2022 Mycroft AI Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# ----------------------------------------------------------------------------- +# Dockerfile for Mimic 3 (https://github.com/MycroftAI/mimic3) +# +# Requires Docker buildx: https://docs.docker.com/buildx/working-with-buildx/ +# ----------------------------------------------------------------------------- + +FROM debian:bullseye as build +ARG TARGETARCH +ARG TARGETVARIANT + +ENV LANG C.UTF-8 +ENV DEBIAN_FRONTEND=noninteractive + +RUN echo "Dir::Cache var/cache/apt/${TARGETARCH}${TARGETVARIANT};" > /etc/apt/apt.conf.d/01cache + +RUN --mount=type=cache,id=apt-build,target=/var/cache/apt \ + mkdir -p /var/cache/apt/${TARGETARCH}${TARGETVARIANT}/archives/partial && \ + apt-get update && \ + apt-get install --yes --no-install-recommends \ + python3 python3-pip python3-venv \ + build-essential python3-dev + +RUN mkdir -p /home/mimic3/app +WORKDIR /home/mimic3/app + +# Create virtual environment +RUN --mount=type=cache,id=pip-venv,target=/root/.cache/pip \ + python3 -m venv .venv && \ + .venv/bin/pip3 install --upgrade pip && \ + .venv/bin/pip3 install --upgrade wheel setuptools + +COPY ./ /home/mimic3/app/ + +# Install packages in order +RUN --mount=type=cache,id=pip-requirements,target=/root/.cache/pip \ + .venv/bin/pip3 install -e opentts-abc && \ + .venv/bin/pip3 install -e mimic3-tts && \ + .venv/bin/pip3 install -e mimic3-http + +# ----------------------------------------------------------------------------- + +FROM debian:bullseye as run +ARG TARGETARCH +ARG TARGETVARIANT + +ENV LANG C.UTF-8 +ENV DEBIAN_FRONTEND=noninteractive + +RUN echo "Dir::Cache var/cache/apt/${TARGETARCH}${TARGETVARIANT};" > /etc/apt/apt.conf.d/01cache + +RUN --mount=type=cache,id=apt-run,target=/var/cache/apt \ + mkdir -p /var/cache/apt/${TARGETARCH}${TARGETVARIANT}/archives/partial && \ + apt-get update && \ + apt-get install --yes --no-install-recommends \ + python3 ca-certificates + +RUN useradd -ms /bin/bash mimic3 + +# Copy virtual environment and source code +COPY --from=build /home/mimic3/app/ /home/mimic3/app/ + +USER mimic3 +WORKDIR /home/mimic3/app + +EXPOSE 59125 + +ENTRYPOINT ["/home/mimic3/app/.venv/bin/python3", "-m", "mimic3_http"] diff --git a/Makefile b/Makefile index 2e100d0..d4a2871 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # -.PHONY: dist +.PHONY: dist docker dist: cd opentts-abc && python3 setup.py sdist @@ -23,3 +23,6 @@ dist: cp opentts-abc/dist/opentts_abc-*.tar.gz dist/ cp mimic3-tts/dist/mimic3_tts-*.tar.gz dist/ cp mimic3-http/dist/mimic3_http-*.tar.gz dist/ + +docker: + docker buildx build . -f Dockerfile --tag mycroftai/mimic3 --load diff --git a/docker/mimic3 b/docker/mimic3 new file mode 100755 index 0000000..4c3609f --- /dev/null +++ b/docker/mimic3 @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +# Copyright 2022 Mycroft AI Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# + +# Run mimic3 --update to update Docker image + +args=() +repo='mycroftai/mimic3' +tag='latest' +docker='docker' + +while [[ -n "$1" ]]; do + if [[ "$1" == '--update' ]]; then + # Update Docker image + update='1' + args+=("$1") + else + args+=("$1") + fi + + shift 1 +done + +if [[ -n "${update}" ]]; then + docker pull "${repo}:${tag}" +fi + +docker_run_args=() + +if [[ -d /etc/ssl/certs ]]; then + # This directory seems to usually have symlinks to other directories + docker_run_args+=('-v' '/etc/ssl/certs:/etc/ssl/certs:ro') + + # Create temp file with all certificate directories found + cert_dirs_file="$(mktemp)" + function finish { + rm -rf "${cert_dirs_file}" + } + trap finish EXIT + + while read -r cert_path; do + # Follow symlinks and record directory paths + cert_path="$(readlink -f "${cert_path}")" + cert_dir="$(dirname "${cert_path}")" + echo $cert_dir >> "${cert_dirs_file}" + done < <(find /etc/ssl/certs -name '*.pem' -type l) + + # Map unique certificate directories + while read -r cert_dir; do + docker_run_args+=('-v' "${cert_dir}:${cert_dir}:ro") + done < <(sort < "${cert_dirs_file}" | uniq) +fi + +"${docker}" run \ + -i \ + -e "HOME=${HOME}" \ + -v "$HOME:${HOME}" \ + -w "${PWD}" \ + --device /dev/snd:/dev/snd \ + --user "$(id -u):$(id -g)" "${docker_run_args[@]}" \ + --entrypoint '/home/mimic3/app/.venv/bin/python3' \ + "${repo}:${tag}" \ + -m mimic3_tts \ + --stdout \ + "${args[@]}" diff --git a/docker/mimic3-server b/docker/mimic3-server new file mode 100755 index 0000000..f6b137c --- /dev/null +++ b/docker/mimic3-server @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +# Copyright 2022 Mycroft AI Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# + +# Run mimic3-server --update to update Docker image + +args=() +repo='mycroftai/mimic3' +tag='latest' +docker='docker' +port='59125' + +while [[ -n "$1" ]]; do + if [[ "$1" == '--update' ]]; then + # Update Docker image + update='1' + elif [[ "$1" == '--port' ]]; then + port="$2" + args+=('--port' "${port}") + shift 1 + else + args+=("$1") + fi + + shift 1 +done + +if [[ -n "${update}" ]]; then + docker pull "${repo}:${tag}" +fi + +docker_run_args=() + +if [[ -d /etc/ssl/certs ]]; then + # This directory seems to usually have symlinks to other directories + docker_run_args+=('-v' '/etc/ssl/certs:/etc/ssl/certs:ro') + + # Create temp file with all certificate directories found + cert_dirs_file="$(mktemp)" + function finish { + rm -rf "${cert_dirs_file}" + } + trap finish EXIT + + while read -r cert_path; do + # Follow symlinks and record directory paths + cert_path="$(readlink -f "${cert_path}")" + cert_dir="$(dirname "${cert_path}")" + echo $cert_dir >> "${cert_dirs_file}" + done < <(find /etc/ssl/certs -name '*.pem' -type l) + + # Map unique certificate directories + while read -r cert_dir; do + docker_run_args+=('-v' "${cert_dir}:${cert_dir}:ro") + done < <(sort < "${cert_dirs_file}" | uniq) +fi + +"${docker}" run \ + -it \ + -p "${port}:${port}" \ + -e "HOME=${HOME}" \ + -v "$HOME:${HOME}" \ + -w "${PWD}" \ + --user "$(id -u):$(id -g)" "${docker_run_args[@]}" \ + "${repo}:${tag}" \ + "${args[@]}"