docker上でcrondを動かしてみた

このサーバで使用しているDynamic DNSはMyDNS.JPなのだが、当然QNAPは海外のメージャーなDDNSしか対応していない=MyDNS.JPには対応していないので、DDNSのIPアドレスの更新を自前で行う必要がある。

そこでDDNSのIPアドレス更新コマンドをcrondで定期的に実行することになるのだが、当初QNAPネイティブのcrondを使っていたのだが、QNAPのファームウェアを更新してからQNAPネイティブなcrondでのコマンド実行が正常に動作しなくなった。

QNAPネイティブで動かしている限りQNAPに開発者登録をして常に最新情報をウォッチし続けなければ今回のような仕様変更に追随できなくなる。それどころか今回のようにファームウェアのアップデート時のQNAP再起動に伴うアプリの停止&起動が行われた瞬間にアプリが動かなくなるのが怖い。

そこでDDNSの更新コマンドをContainer Station(docker)上でcrondを動かす方向でQPKGを再作成するのだが…

どうせならcrondの実行計画は固定にしないでQNAPのWebUI上で変更できる汎用アプリにしたいと思ったので、docker上で動くcrondにホスト側の設定ファイルを読み込ませようと思ってネット上で「docker + crond」情報を検索するがヒットするのはDockerfileで「RUN echo 〜 >crontabs」か「COPY file crontabs」を記述する固定方式ばかり。

しかもQNAPではQPKGアプリをインストールした時のユーザーでホスト側のファイルオーナーが設定されてしまうが、docker内はrootで動いてて。crond固有の制限事項(crontabsファイルのオーナーやアクセス権限などの制限事項)の影響もあって、ホスト側のcrontabsファイルを直接docker内のcrondの設定ファイルにmountする方法では正常に動作しないことも考えられる。

そこで考えたのが、dockerのENTRYPOINTで指定・実行するシェルスクリプト内でcrontabコマンドをを使って設定ファイルを読み込ませることに。そして完成したのが以下のようなDockerfileとdocker-entrypoint.sh。

Dockerfile

FROM alpine:latest

RUN apk add --no-cache tzdata

COPY ./docker-entrypoint.sh /
RUN chmod 755 /docker-entrypoint.sh
ENTRYPOINT [ "/docker-entrypoint.sh" ]

CMD [ "crond", "-f" ]

docker-entrypoint.sh

#!/bin/sh
set -e

# Update crontabs settings
CRONTABS="/root/crontabs"
if [ -f ${CRONTABS} ]; then
  crontab ${CRONTABS}
fi

exec "$@"

あとは「docker build -t crond:latest .」って感じでビルドして、「docker run -d -v ./crontabs:/root/crontabs crond」って感じで実行するだけ。更新もホスト側でcrontabsファイルを編集して「docker restart crond」するだけ。

Share

3年ぶりの書き込みは…

この3年間、何も書き込みをしていなかった理由の一つはコロナであったことは明らかなんですが、それでも何事も無ければ新たに書き込みをすることはなかったかも知れないが、今回は3年ぶりに書き込みをすることに。

ことの発端は先月初めに使用しているサーバ(QNAP)の設定をミスって、最新版ファームウェアへのアップデートで間違ってベータ版のファームウェアをインストールしてしたのが、運の尽きだった。

これまでQNAPを使っていろいろ実験していた影響でQNAPの環境を汚していたことは事実だが、今回のベータ版のファームウェアへアップデートした途端にQNAP搭載のWebサーバが全く起動しなくなってしまったのだ!

当然このブログへもアクセスできなくなってしまったので、Google Search Consoleからエラーが入るようになったので、このままブログを辞めてしまおうかとも思ったのだが、最近QNAP上のContainer StationがほぼDocker化した影響もあり、サーバのSSL証明書の更新に使用するLet’s EncryptもDocker化していたので、WordPressもContainer Station(Docker)上で実行するようにしてしまえば、管理が楽かな〜などと考えて復活させてみることに。

また、ちょうどタイミング的にGWだったこと、コロナの影響で今年のGWの旅行の手配が遅れた影響でGWの希望の飛行機のチケットが手に入らず、高額なチケットを買ってまで海外旅行をするか悩んでいたところに、仕事でもGW中に片付けておきたい作業が出てきたので、今年のGWは海外旅行に行くことを諦めて、QNAPの復旧と環境整備に充てることにした。

QNAP本体はHDD上のデータをバックアップ、SQL内のデータをsqldumpで抜き出すなどしてから工場出荷時に初期化することで復旧は早かったんですが、問題はDocker対応(というかQDKでQNAPのパッケージ化)させていなかったWordPressたち。

今回同じようにContainer Station(Docker)に移したOpenPNEは簡単に動作させることができたのに、WordPressだけは何故かうまく動作せず、その原因究明までに少し時間がかかってしまったが無事に本日ほぼ復旧が終わったので、動作確認を兼ねて、3年ぶりの書き込みをすることに。

今回復旧に手間取った一番の理由が、QNAP上のWebサーバはLet’s EncryptでSSL化しているが、Container Station(Docker)上で動かしているWordPressは非SSLなので、QNAP側のSSLから非SSLのWordPressへのプロキシーの設定なのだが。

OpenPNEは単純なProxyPass / ProxyPassReverseの設定だけで何の問題なく動作したのに、WordPressでは「RequestHeader set X-Forwarded-Proto https」を設定しないと正しく動作しないということに気がつくまで時間がかかってしまったこと。

コロナも事実上終わり海外旅行にも行けるようになったけど、流石に3年のブランクは大きいというか怠癖がついてしまったというか、コロナ前のようにブログが復活できるか分かりませんが、リハビリも兼ねてボチボチやっていこうと思います。

Share

Docker vs Container Station

QNAPのNASに搭載されているのは正確にはDockerではなくContainer Stationだと言う事を忘れては行けない!!

sshでTS-431Pにログインできるのはadminアカウントのみ(≠管理者権限のアカウント)だし、dockerやdocker-composeなどのコマンドは存在しているが、ssh上でこれらのコマンドを使って作成したイメージやコンテナをContainer Stationから操作できないパターンがあったりして互換性に問題が山積みだ。

更にTS-431PはCPUがarm32系なので普通にDockerfileやdocker-compose.ymlにOfficialなイメージを指定すると存在しないために使えない事も多い。

これらの問題を解決するために、

  • コンテナ作成コマンドにdocker/docker-composeを使用せず、Container Stationのqbusコマンドで代用する。
  • arm32v7のOfficial互換イメージで使えそうなイメージに、Officialと同じtagをローカルでだけ付与する前処理を入れる形で誤魔化す。

という対策を行う事で何とかDocker Desktopで開発したアプリをTS-431P上にインストールしても使えそうな雰囲気になってきた。

ついでに、アプリをQDKでqpkg形式にする事で、QNAP上のApp Centerからインストールする事もできるようになって便利かな〜と思っている。

これまで実験してきた内容は整理できた段階で、一度ブログに記載しようとは思っているけど、今は未解決状態のmariadbのarm32v7イメージ作成をどう解決するかを考え中…

Share

ARM32でDockerは少数派!?

Dockerの基本的な使い方も問題なさそうだったので、Docker Desktop + Visual Studio Codeな環境を作成して、Docker composeの基本的な使い方を勉強しようと、比較的メジャーな組み合わせと思われるnginx + php + mysql (mariadb)なアプリを作成してみた。

Docker Desktopでは問題なく動作する事が確認できたので、早速QNAP上のDocker composeでビルドしようとするとmysql (mariadb)のイメージがDocker Hubから見つからないというエラーが発生する。

そう、今使っているQNAPのTS-431PのCPUはARM (arm32v7, armhf)なのだが、nginxやphpのARMv7 (32bit)用のイメージはあるのだが、mysql (mariadb)のARMv7 (32bit)用イメージはDocker Official Imagesには何故かないのだ。

同じDatabaseで言えばpostgresはARMv7 (32bit)用のイメージが存在しているのに…mysql (mariadb)が存在しないとは。

こればかりはどうしようもないので、仕方なくUn-Officialなイメージのlinuxserver/mariadbを利用するように定義ファイルを書き換える事で、ビルドそのものは問題なく実行できるようになったのだが…

各種設定など細かい部分でOfficialなmariadbのイメージとは差異があるようで、どの設定が異なり、どう設定すれば良いのか、全て正常に動作するようになるまでの地道な調整作業が必要なようだ。

Share

今更だがDockerを勉強中!?

QNAPを使い始めて早くも6年半。当時はContainer Stationもなければ、スレージプール機能も存在しなかった。

そんな中でQNAPを単なるファイルストレージとして使わず、LinuxサーバとしてOpenPNEなどをQNAP上で直接運用して来たのだが、最近のバージョンアップで最新のPHPに対応していないOpenPNE2が動作しなくなり、新機能のHybridMountを使おうにもストレージプールに変更しないと使えないし、App Centerに今まで存在していたアプリが消えて無くなるなど制約が多数発生するようになってきた。

QNAP上で運用していた様々なアプリに問題が生じるようになってきたので、そろそろアプリの運用方法も見直さないとやばいかな〜と思い始めたので、今更ながらDocker(Container Station)の使い方を勉強し始めた。

今までQNAP上でネイティブで運用していたアプリをDockerで置き換えできれば、今後何かあってもデータとDockerの定義ファイルさえ残っていれば、復旧させるのも、新しい環境へ移行するにも楽かなと思って。

しかし、まだまだ使い方を勉強し始めたばかりで、理解できていない部分も多いのか、QNAPという環境が特殊なのか、苦労する事も多い。

ネットの情報を元にコンテナを作ろうとしても、何故かpullしてくるイメージがIntel系になってしまい、今使っているQNAP(ARM)だと正常に動作しなかったり、buildして作成したイメージに名前を付けなかったり、同じ名前を付けると古いイメージの名無しになってしまって、Container Stationのイメージ一覧に表示されない、など癖があって何かと苦労する。

更にQNAPのWebUIではDockerfileをbuildする方法が用意されていないので、QNAPのWebUIからQNAP自身にssh接続するためのDockerfileを作ってみたが、docker runとかで使えるように最後のENTRYPOINTやCMDで直接shellを起動するようにしたら、QNAPのContainer Stationでは何故か正常に動作しない。

仕方がないので、何もしないコマンド(実際は「tail -F /dev/null」)でコンテナを実行状態にしてからWebUIのターミナルを起動する方法で誤魔化す事でQNAPにWebUIからssh接続できるようになった。

とりあえず、基本的なイメージ、ボリューム、コンテナを作成して、QNAP上で実行するところまでは問題なくできるようになったかな。

次はDocker Compose(QNAP上でのアプリケーションの作成)だが、中身が1コンテナだけのアプリってどんな意味があるのか理解できていないので、とりあえず複数コンテナを組み合わせたアプリの作成を覚えたいなと。

Share