20210227のdockerに関する記事は7件です。

オンプレ環境で使えるDiscordの読み上げBotを作りました

事の発端

知り合いとのDiscordサーバーでは土日に通話しながらゲームをするときに、テキストチャンネルで発言するのみで喋らない"聞き専"が結構います。
そこでチャットを読み上げてくれる「Shovel」というBotを導入しました。
キャプチャ.PNG
しかし、土日の夜は非常に人が多いのか、ボイスチャットに呼ぼうとしても呼べない時が何度かあり、そこで自分たち専用の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は大歓迎です。


  1. 単純に僕の検索能力不足...? 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

chatwootをdockerで動かしてみる

TL;DR

OSSのチャットツールであるchatwootをdockerを使って動かしてみます。
(内容は、ほぼほぼ備忘録です)

リポジトリのクローン

GitHubにあるchatwootのリポジトリをクローンしてきます。

git clone https://github.com/chatwoot/chatwoot.git

設定ファイルの作成

リポジトリ内にある設定ファイルのサンプルをリネームします。

cp .env.example .env

リネームした上記設定ファイルを編集します。ここでは、redisとpostgresのパスワードを設定します。
(パスワードは任意のものでOK)

.env
REDIS_PASSWORD=password

POSTGRES_PASSWORD=postgres

docker-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は記号に置き換えてください)

参考サイト

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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.04

2. Dockerfileの作成

コンテナを作るためのDockerfileを作成します。

Dockerfile
FROM <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.sh
algorithm_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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 --volumes 

Dockerの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
...........

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[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

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker-composeでApacheコンテナ起動時にcommandを実行する

昨年の2月くらいからリモートで業務するようになってから、1ヶ月くらいの出社期間を挟んでそろそろ1年近くになってきました。リモートでの業務自体は過去にフルリモートで数年勤務してたこともあるので問題はなかったのですが、最近テレカンの際に自分でも引くくらい話すのが下手になっているのを実感します。結構真面目に危機感を覚えました。

それはさておき掲題の件ですが、ぐーぐる先生に聞いても全然解決策が見つけられず、結構久々に苦戦しました。何かこれ、以前にも同じようなことでハマっていたような記憶があるので、備忘録として残しておきます。長くなってしまったので、お急ぎの方は「修正後」をご参照ください。

何がしたかったのか

php:7.4.12-apacheをベースに作成したApacheのコンテナ時に、シェルスクリプトを走らせたかったという所から始まりました。実際にはwp-cliを使ってWordPressを入れていて、固定ページなどの実装をgit管理出来るように擬似的なマイグレーションの仕組みを作ったのですが、いちいちコンテナに入ってコマンド実行というのがイケてない気がしたのでこれならばdocker-compose upするだけで勝手に適用されるかなというのが発端です。

何をしたのか

一部抜粋の形ですが、docker-compose.ymldockerfileはこんな感じです。

dockerfile
FROM 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.yml
version: '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.ymlcommandを定義すると、dockerfileCMDは無視される
    • つまりdockerfileCMD ["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にアクセスしてみると、見慣れた画面が帰ってきました。軽く確認した限りでは、概ね問題はなさそうです。これがベストプラクティスなのかはちょっと懐疑的ではあるんですが、ひとまずは期待していた動作を確認出来るようになったので今日の所はこれで勘弁してやろうと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む