- 投稿日:2021-02-27T16:21:29+09:00
オンプレ環境で使えるDiscordの読み上げBotを作りました
事の発端
知り合いとのDiscordサーバーでは土日に通話しながらゲームをするときに、テキストチャンネルで発言するのみで喋らない"聞き専"が結構います。
そこでチャットを読み上げてくれる「Shovel」というBotを導入しました。
しかし、土日の夜は非常に人が多いのか、ボイスチャットに呼ぼうとしても呼べない時が何度かあり、そこで自分たち専用のBot用サーバーを用意する案が上がります。Raspberry Piを入手
秋葉原に行って、Raspberry Pi4と電源などの一式を入手。
早速、以下の条件を満たす読み上げDiscord Botを探し始めます。
- ラズパイ上で動く
- Dockerでいける(環境を汚したくないため)
- オンプレ環境で使える
- 完結している、クラウドサービスを使っていない(Cloud Text-to-Speechなど)
しかし案外見つからず1、結局自分で作る事にしました。
成果物
よみのん
上の四つの条件を満たしたDiscord用読み上げBotです。
Discord.js+Open Jtalk+Dockerで作成しています。
Discord用のBOT KEYを発行した後に、適当にVPSや自前のラズパイによみのんをデプロイしてもらえば動きます。
詳しくはのよみのんのReadme.mdを見て下さい。Issue、Starは大歓迎です。
単純に僕の検索能力不足...? ↩
- 投稿日:2021-02-27T15:33:46+09:00
chatwootをdockerで動かしてみる
TL;DR
OSSのチャットツールであるchatwootをdockerを使って動かしてみます。
(内容は、ほぼほぼ備忘録です)リポジトリのクローン
GitHubにあるchatwootのリポジトリをクローンしてきます。
git clone https://github.com/chatwoot/chatwoot.git設定ファイルの作成
リポジトリ内にある設定ファイルのサンプルをリネームします。
cp .env.example .envリネームした上記設定ファイルを編集します。ここでは、redisとpostgresのパスワードを設定します。
(パスワードは任意のものでOK).envREDIS_PASSWORD=password POSTGRES_PASSWORD=postgresdocker-composeの設定
リポジトリ内の
docker-compose.yaml
を編集します。Postgresのパスワードとタイムゾーンを設定します。docker-compose.yaml# ...(省略) postgres: image: postgres:12 restart: always ports: - '5432:5432' volumes: - postgres:/data/postgres environment: - POSTGRES_DB=chatwoot - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres # 追加 - PGPASSWORD=postgres # 追加 - TZ=Asia/Tokyo # 追加 # ...(省略)コンテナの作成&実行
以下のコマンドを叩きます。
DBの初期化に失敗する場合、一度docker-compose up
でコンテナを起動した後、再度DBを初期化すると、成功するかもしれません。# コンテナをビルド $ docker-compose build # DBの初期化 $ docker-compose run --rm rails bundle exec rails db:reset # コンテナの起動 $ docker-compose upコンテナの停止は、Ctrl+Cで行います。
chatwootへアクセス
コンテナ起動後、ブラウザから
http://(IPアドレス):3000
にアクセスします。
ログイン画面が表示されるので、john(atmark)acme.inc / 123456でログインします。
(atmarkは記号に置き換えてください)参考サイト
- 投稿日:2021-02-27T14:00:55+09:00
Sagemakerの公式コンテナに好きなパッケージを追加して使う方法
概要
AWS の Sagemaker で
公式に用意されているもの以外に好きなパッケージを追加して使いたいと思った時
あまり日本語の情報が無かったので、
今回私が公式のコンテナを拡張するためにやった方法をまとめてみました。(1回やっただけで細かい動作確認などはまだ行っていないので、間違ってる所があったらごめんなさいm(__)m)
方法
1. 拡張したいコンテナのURLを探す
以下のサイトから自分が拡張したいコンテナのURLを選びます。
deep-learning-containers/available_images.md at master · aws/deep-learning-containers · GitHub大体の場合はGeneral Framework Containersの中から選べばいいと思います。
Elastic Inferenceを使いたい場合は多分Elastic Inference Containersから選べばOKです。
学習時に使うコンテナの場合はJob Typeがtrainingのものを、推論時に使うならinferenceのものを選んでください。
また、自分の使うpythonのバージョンに合ったものを選んでください。ページ上部にあるリージョンの表から、作ったコンテナを使いたいリージョンを選択し、
URLの前半部分は該当するURLに差し替えてください。例)東京リージョンで使う予定で、CPUインスタンスでTensorflow2.3.1を使って推論を実行したいなら
763104351884.dkr.ecr.ap-northeast-1.amazonaws.com/tensorflow-inference:2.3.1-cpu-py37-ubuntu18.042. Dockerfileの作成
コンテナを作るためのDockerfileを作成します。
DockerfileFROM <1.で選んだURL> RUN pip install <入れたいパッケージ> RUN apt-get install -y <入れたいもの>というように、
拡張したいdocker imageをFROMで呼び出してから、
RUNを使って追加したいパッケージを入れるようにします。3. コンテナの構築とECRへのアップロード
コマンドラインで
docker build -t <新しいコンテナの名前(任意)> .を実行し、新しいコンテナを構築します。
次に、
aws ecr get-login-password --region <1.で選んだリージョン> | docker login --username AWS --password-stdin <自分のアカウントID>.dkr.ecr.<1.で選んだリージョン>.amazonaws.comを実行してECRにログインした後、コマンドラインで以下の内容を実行してください。
(シェルスクリプト化してshコマンドで実行してもOK)push_docker_image.shalgorithm_name=<作ったコンテナの名前> region=<1.で選んだリージョン> account=$(aws sts get-caller-identity --query Account --output text) fullname="${account}.dkr.ecr.${region}.amazonaws.com/${algorithm_name}:latest" # If the repository doesn't exist in ECR, create it. aws ecr describe-repositories --repository-names "${algorithm_name}" > /dev/null 2>&1 if [ $? -ne 0 ] then aws ecr create-repository --repository-name "${algorithm_name}" > /dev/null fi # Build the docker image locally with the image name and then push it to ECR # with the full name. docker build -t ${algorithm_name} . docker tag ${algorithm_name} ${fullname} docker push ${fullname}これで作ったコンテナがECRにアップロードされたはずです。
4. 作ったコンテナを使ってSagemakerを使用する
例えば、Tensorflowの学習済みモデルを使ってSagemakerのモデルを作りたいなら、
モデルのオブジェクトを作る時のimage_uri引数として
さっきのfullnameにあたるURLを指定してやれば使えます。from sagemaker.tensorflow.model import TensorFlowModel model = TensorFlowModel(model_data="hoge.tar.gz", role=role, image_uri="<自分のアカウント番号>.dkr.ecr.<1.で選んだリージョン>.amazonaws.com/<作ったコンテナ名>")参考ページ
コンテナの拡張方法を説明したAWS公式のガイド:
構築済みのコンテナの拡張 - Amazon SageMaker公式コンテナのURLのリスト(1.で使ったものです):
deep-learning-containers/available_images.md at master · aws/deep-learning-containers · GitHub以下のサイトではSagemakerのモデルを作る時に使うクラスの仕様(引数などについて)が解説されてます。
全てのフレームワークで共通の仕様
Model — sagemaker 2.26.0 documentation各フレームワークごとの仕様
Frameworks — sagemaker 2.26.0 documentation例えば、Tensorflowを使うなら以下のページ
TensorFlow — sagemaker 2.26.0 documentation
- 投稿日:2021-02-27T12:05:56+09:00
Dockerfileとimageに封入したいディレクトリが違っているときのbuildコマンドの書き方
AWS ECRにpushするdocker imageを作成するときにいつも忘れてしまうので備忘録に。
以下のようなディレクトリ構成を仮定して、app以下(実際のアプリのコードを想定)のディレクトリもdockerのimageに封入したい場合
Project/ ├ docker / │ └ php/ │ └ Dockerfile ├ app/ │ └ service/ │ └ repository/ │ └ routes/ └ .dockerignoreこの場合のDocker buildコマンドは以下(Projectディレクトリでたたくとして)
docker build -f docker/php/Dockerfile . -t project_name
- 投稿日:2021-02-27T11:54:32+09:00
docker command まとめ
いつも忘れるからメモ、特に新しいことはありません。
使用していない Docker オブジェクトの削除(prune)
# イメージの prune $ docker image prune # 既存のコンテナ~使われていないイメージすべてを削除する $ docker image prune -a # 既存のコンテナ~使われていないイメージすべてを削除する、確認もしない $ docker image prune -a -f $ docker image prune -a --filter "until=24h" # コンテナの prune $ docker container prune $ docker container prune --filter "until=24h" # ボリュームの prune $ docker volume prune $ docker volume prune --filter "label!=keep" # ネットワークの prune $ docker network prune $ docker network prune --filter "until=24h" # 全てを prune $ docker system prune $ docker system prune -a # Docker 17.06.1 以上でボリュームも削除したい場合は、 --volumes フラグを使います $ docker system prune --volumesDockerのBuild Cacheの削除
$ docker builder prune
Docker 版 df
$ docker system df TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 5 2 2.884GB 343.2MB (11%) Containers 2 2 301kB 0B (0%) Local Volumes 0 0 0B 0B Build Cache 0 0 0B 0Bコンテナの中身を覗く
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5ed47462ec5b wnameless/oracle-xe-11g-r2 "/bin/sh -c '/usr/sb乧" 9 months ago Up 2 months 22/tcp, 8080/tcp, 0.0.0.0:49161->1521/tcp oracle11g 7ff96800acc6 mysql:5.7.28 "docker-entrypoint.s乧" 14 months ago Up 2 months 0.0.0.0:3306->3306/tcp, 33060/tcp mysql_host $ docker inspect mysql_host ...........以上
- 投稿日:2021-02-27T11:22:40+09:00
[Azure] DockerからAzure PowerShellを使う
前提
- dockerコマンドが使用できる環境
手順
コンテナーでの Azure PowerShell の使用
次の手順は、イメージをダウンロードし、対話型 PowerShell セッションを開始する
# イメージダウンロード docker pull mcr.microsoft.com/azure-powershell # 対話モードでコンテナー実行 docker run -it mcr.microsoft.com/azure-powershell pwshサインイン
PS /> Connect-AzAccount -UseDeviceAuthentication WARNING: To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code xxx to authenticate. WARNING: TenantId 'xxx' contains more than one active subscription. First one will be selected for further use. To select another subscription, use Set-AzContext.ブラウザでコードを入力して、サインイン
複数サブスクリプションがある場合は以下で指定
PS /> Set-AzContext -Subscription "xxxx-xxxx-xxxx-xxxx"クライアント証明書をホストからコンテナに送る
# docker ps でコンテナidを取得 docker ps # ホストからコンテナにコピー $ sudo docker cp my.cnf <コンテナID>:/etc/my.cnf参考
- 投稿日:2021-02-27T02:11:29+09:00
docker-composeでApacheコンテナ起動時にcommandを実行する
昨年の2月くらいからリモートで業務するようになってから、1ヶ月くらいの出社期間を挟んでそろそろ1年近くになってきました。リモートでの業務自体は過去にフルリモートで数年勤務してたこともあるので問題はなかったのですが、最近テレカンの際に自分でも引くくらい話すのが下手になっているのを実感します。結構真面目に危機感を覚えました。
それはさておき掲題の件ですが、ぐーぐる先生に聞いても全然解決策が見つけられず、結構久々に苦戦しました。何かこれ、以前にも同じようなことでハマっていたような記憶があるので、備忘録として残しておきます。長くなってしまったので、お急ぎの方は「修正後」をご参照ください。
何がしたかったのか
php:7.4.12-apache
をベースに作成したApacheのコンテナ時に、シェルスクリプトを走らせたかったという所から始まりました。実際にはwp-cli
を使ってWordPressを入れていて、固定ページなどの実装をgit管理出来るように擬似的なマイグレーションの仕組みを作ったのですが、いちいちコンテナに入ってコマンド実行というのがイケてない気がしたのでこれならばdocker-compose up
するだけで勝手に適用されるかなというのが発端です。何をしたのか
一部抜粋の形ですが、
docker-compose.yml
とdockerfile
はこんな感じです。dockerfileFROM php:7.4.12-apache # config file COPY ./php.ini /usr/local/etc/php/ # apt RUN apt-get update \ && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev libonig-dev mariadb-client \ && docker-php-ext-install pdo_mysql mysqli gd iconv # xdebug RUN pecl install xdebug && \ docker-php-ext-enable xdebug COPY ./xdebug.ini /usr/local/etc/php/conf.d/ RUN a2enmod rewrite # use bash shell SHELL ["/bin/bash", "-l", "-c"] EXPOSE 80 CMD ["apache2-foreground"]多分割とよく見る感じのdockerfileかと思います。
docker-compose.ymlversion: '3.7' services: app: depends_on: - db build: ./docker/app command: bash -c "sh /var/www/bin/migrations.sh" volumes: - ./bin:/var/www/bin - ./.data/app:/var/www/html:delegated - ./.data/log/app/:/var/log/apache2/ restart: always ports: - "8888:80"
command
にシェルスクリプトの実行コマンドを渡すことで、コンテナ起動時に自動で実行されるようにしました。これで、コンテナ再起動するだけで都度
/var/www/bin/migrations.sh
が実行されるので、プロジェクトメンバーの負担も軽減出来るかなという発想でした。何が起こったのか
シェルスクリプト自体は正常に動作していましたが、
Docker Desktop
でコンテナのログを見てるとシェルスクリプトの実行ログがループして出力されているような状態に陥りました。最初はシェルスクリプトが終了したら再度実行されている?と思ってシェルスクリプトにsleep 30d
とか乱暴なことを書いていましたが、よくよく調べてみるとどうも違いそうです。こんなのコミットしたらぶん殴られてる所でした。半ギレしながら調査していた所、そうではなく、コンテナがひたすら再起動を繰り返しているというのが実際のようです。
Docker Desktop
のコンテナステータスをよくよく見ていれば前述のようなわけのわからないことをしてなかった気もします。何故起こったのか
- シェルスクリプトが終了するとフォアグラウンドで作動しているプロセスが不在になり、コンテナは終了する
というのが原因のようです。この原因に到達した時に、物凄いデジャヴュを感じました。多分以前の案件でもやっぱり同じことをやらかしていると思います。また、この時点で、解決策に至れていなかったのは完全に見落としだったと思います。
修正しましょう
先程も書いたように、フォアグラウンドで作動するプロセスがなくなったらコンテナが終了するわけですから、フォアグラウンドで何かを動かし続ければいいのでしょう。ということで、乱暴に修正してみます。出典を記録し損ねてしまったのですが、「
bash
を対話モードで動作させればコンテナは終了しない」というのを見たのでやってみます。docker-compose.yml- command: bash -c "sh /var/www/bin/migrations.sh" + command: bash -c "sh /var/www/bin/migrations.sh && /bin/bash"
Docker Desktop
のコンテナログを見ている限り、先程のようにログが繰り返し出力されなくなりました。コンテナのステータスもRUNNINGのままですので、上手くいったように思えます。試しにこの状態で、コンテナを起動しているlocalhost:8080
にアクセスしてみます。すると、
ERR_EMPTY_RESPONSE
と返されました。うんともすんともです。修正がダメだった理由
ERR_CONNECTION_REFUSED
じゃなくてERR_EMPTY_RESPONSE
なのは想定していなかったので、一瞬頭が真っ白になりましたが、冒頭のdockerfile
を開いてみてようやく気づきました。
docker-compose.yml
でcommand
を定義すると、dockerfile
のCMD
は無視される
- つまり
dockerfile
のCMD ["apache2-foreground"]
は実行されていない- そのため、ApacheのコンテナなのにApacheが起動していない状態になっている
そりゃ見れるはずもありませんね…。
修正後
Apacheのコンテナを起動時に
command
でコマンドを渡す際にApacheの起動コマンドも一緒に渡すようにしました。docker-compose.yml- command: bash -c "sh /var/www/bin/migrations.sh && /bin/bash" + command: bash -c "sh /var/www/bin/migrations.sh && apache2-foreground"
先程と同様に
localhost:8080
にアクセスしてみると、見慣れた画面が帰ってきました。軽く確認した限りでは、概ね問題はなさそうです。これがベストプラクティスなのかはちょっと懐疑的ではあるんですが、ひとまずは期待していた動作を確認出来るようになったので今日の所はこれで勘弁してやろうと思います。