Docker Compose で、ベースイメージが更新された場合のみ再 up する

本記事は Docker/コンテナ仮想環境 Advent Calendar 2023 の3日目の記事だ。

2日目は @ko-he-8 氏の /var/lib/docker/が肥大化していたけどdocker system prune --volumesで解決しなかったので調べてみた #Docker だった。
なんかの拍子にコンテナが管理外になってしまっていて docker system prune で削除できないときのお話になっている。
開発用の仮想マシンをリセットせずに使い続けていたりすると、こういう状況に良くなるよね…


Docker Compose だけで雑に本番運用する際に、定期的にリビルドしたい

信頼できるオフィシャルイメージを元に、カスタムイメージをビルドして本番運用する場合、 CI 等でビルドしたイメージをコンテナレジストリに push し、それを本番環境側で pull するのが一般的なベストプラクティスだ。

しかし、クラスタも構築せず VM 1台でいくつかのコンテナを動かすような小規模な運用ほ場合、わざわざ CI やレジストリを準備するのも面倒だ。
このため、運用環境上で Docker Compose を使ってイメージのビルドやコンテナの起動を行ってしまう単純な構成にしたくなる。

そんな時、ベースイメージのセキュリティ更新に追従するために、定期的にイメージをリビルドした上で、必要な場合に限ってコンテナを再 create & up させる方法を考える。

BuildX 既定化による弊害

以前は、 docker-compose pull --no-paralleldocker-compose build --pull の標準出力のいずれかから、 新しいイメージが pull されたことを示す "Downloaded newer image" の文字列があるかどうかを確認し、 docker-compose up すればよかった。

ところが、 docker 23.0.0 にて、 Linux 環境における既定のビルダーが BuildKit というものに切り替わってしまった。
旧来の docker-compose V1 の docker-compose build ないし、 Docker Compose V2 の docker compose build 実行時は docker CLI を通じてビルドされる ため、この仕様変更の影響を受ける。
このため、規定の設定のままだと build の仕組みが変わってしまい、上述のベースイメージのダウンロードを検出できなくなった。

BuildKit は規定では出力をいい感じにまとめてしまうので、そのままだとベースイメージの pull があったかどうか判別できない。

環境変数で DOCKER_BUILDKIT=0 を設定しておけば、旧来の Legacy Builder でビルドをしてくれるが、いつまでサポートされるかわからないので、 BuildKit を使う方法でなんとかしたい。

幸い、 docker build --progress=plain の出力の指定 は、 docker compose build でも働いてくれる。

この出力から ^#[0-9]+\s+resolve\s+ の正規表現がヒットする場所を探してくれば検出できそうだ。

Docker Compose V2 に対する出力オプション

また、既に廃止済みの docker-compose V1 の代替として、 Docker Engine 20.10.13Docker Compose V2 プラグイン がインストールされるようになって以降、現在はこちらの docker compose コマンド使う必要がある。

Compose V2 は、多くの面では docker-compose V1 と互換があり、作成されるコンテナ名のセパレータが一致しない事 (これも --compatibility フラグ で互換性を維持できる)以外はおおむねそのまま利用できる。

ただ、コマンドの UI 出力の内容や、それに纏わるオプションは V1 から大きく変わっているので、そこらへんは調整してやる必要がある。

--ansi never オプションを指定すると、ANSI エスケープコードが無効化され、ターミナルの色がつかなくなったり、パイプ時に余計な文字コードが確実につかなくなる…はずなのだが、指定しても up した時のログぐらいにしか効果が出ないような気はする。
規定値だと auto なので、パイプ処理された場合はそもそも ANSI エスケープコードがつかないはずではあるが、とりあえずオプションの方でも never を強制しといた方が良さそうなので設定しておく。

--progress plain オプションを指定すると、インタラクティブな出力が無くなり、以下のようにパイプで処理しやすいプレーンなテキストが出力されるようになる。
Docker Engine 24.0.3 に同梱されている Docker Compose 2.19.0 移行で compose のグローバルオプションに昇格したオプションであるため、それより低いバージョンだと指定できない点に注意。

$ docker compose --progress plain pull
 alpine-built1 Skipped - No image to be pulled
 alpine-built2 Skipped - No image to be pulled
 alpine-pure2 Skipped - Image is already being pulled by alpine-pure1
 alpine-pure1 Pulling
 070eb51debd9 Pulling fs layer
 070eb51debd9 Downloading [>                                                  ]   28.1kB/2.808MB
 070eb51debd9 Downloading [==================================>                ]  1.911MB/2.808MB
 070eb51debd9 Verifying Checksum
 070eb51debd9 Download complete
 070eb51debd9 Extracting [>                                                  ]  32.77kB/2.808MB
 070eb51debd9 Extracting [==================================================>]  2.808MB/2.808MB
 070eb51debd9 Pull complete
 alpine-pure1 Pulled

docker compose build, up のステータスの出力は、標準出力ではなくて標準エラーの方に出るので、パイプラインつなぐときは注意。

実際のコード例

compose.yaml が存在するディレクトリを /var/lib/docker-compose-dir とした場合、以下のようにできるだろう。

cd /var/lib/docker-compose-dir && { \
  /usr/bin/docker compose --ansi never --progress=plain pull --no-parallel; \
  /usr/bin/docker compose --ansi never --progress=plain build --pull; \
} 2>&1 | \
grep -E "Downloaded newer image|\s+Pull complete\s*$|^#[0-9]+\s+resolve\s+" && \
/usr/bin/docker compose --ansi never up -d

--

さて、こういうコードは cron 等で定期的に実行させたい。
そういった場合、あとから状況を確認しやすくするために、 docker compose の各出力は journald にも書き込んでおきたい。

条件分岐を行うための grep と、 journald に記録するコマンド (logger 等) の両方にパイプしたい場合、 bash や BusyBox ash 等が持つ プロセス置換 が使えそうだ。
crontab が起動するコマンドは、 sh という名前で POSIX 標準互換モードで動かすディストリビューションが多い (debian (Ubuntu) 系, fedora (RHEL, CentOS) 系) ので、明示的に bash (または ash) を呼び出し、その中でプロセス置換を行う方が安全だろう。

例えば Ubuntu の crontab 内で定期的にイメージのリビルドを行う場合、以下のようにすると良いだろう。

cd /var/lib/docker-compose-dir && { \
  /usr/bin/docker compose --ansi never --progress=plain pull --no-parallel; \
  /usr/bin/docker compose --ansi never --progress=plain build --pull; \
} 2>&1 | \
bash -c "tee >( logger -i -t user/docker-auto-rebuild -p user.info )" | \
grep -E "Downloaded newer image|\s+Pull complete\s*$|^#[0-9]+\s+resolve\s+" && { \
  /usr/bin/docker compose --ansi never up -d 2>&1 | \
  logger -i -t user/docker-auto-recreate -p user.info; \
}

なお、実際には cron 内のコマンドでは改行できないので、改行は削除して記述しよう。

後ほどミュートを解除しておく PowerShell スクリプト

本記事は シェルスクリプト&PowerShell Advent Calendar 2023 の1日目の記事だ。
如何にハードルを下げるかを考え、しょーもない内容となることを意識している…と言い訳しておこう。

何故ミュートを解除したいのか

さて、一時的に PC をミュートにしておきたい事がある。

コロナ禍を経て、 Cisco や Polycom といったテレビ会議システムに替わって、 Zoom などのWeb会議ソフトが普及した。
しかし、近年出社を強要されるのが一般化してくると、結局以前のように会議室に集まって、離れた拠点の相手とビデオ会議を行うことになる。
このとき、全員各々のPCでビデオ会議には参加するものの、音声は卓上マイク&スピーカー使う事があり、ハウリングを避ける為に卓上マイクを使う人以外はスピーカー・マイクをミュートにするだろう。

ところが、会議終了後ミュートしっぱなしにしてしまい、通知等に気づきにくくなることがあるので、一定時間後にミュートを簡単に解除できるようにしておきたい。

それだけのために、スクリプト経由で MMDevice API 呼ぶのも仰々しいなぁと思っていた所、よく考えたらキーボードにあるミュート状態をトグルキーを仮想的に押せばいいじゃないかと気づいた。

ということで、早速 PowerShell でキーボードのマルチメディアキーを押すスクリプトを書いてみる。

早速コード例

続きを読む

電Go!! の ZUIKI コンは製造時期による違いがある?

電車でGO!!専用ワンハンドルコントローラー - 瑞起 ZUIKI (以下、 ZUIKIコン) には、 型番 : ZKNS-001 の通常版 と、 型番 : ZKNS-002 の EXCLUSIVE EDITION の二種類ある。
更に、2023年12月には「ズイキマスコン for Nintendo Switch™ RED (ZKNS-011) / BLUE (ZKNS-012)」がリブランドされて追加発売となった。

これらは、 Nintendo Swtich 上では同じように使えることから、外観以外は同じものにも見える。
しかしどうも、製造時期による微妙な違いもあるようだ。

その違いのせいで、 JR東日本トレインシミュレータ で ZUIKIコン 使うツールがな機能しなくなって困ったので、その対処をした話。

きっかけ

元々、2021年の発売当初から通常版の ZUIKIコン を購入しており、公式で対応している 電車でGo!! Switch 版 や ソニックパワードの 鉄道にっぽん! シリーズ Real Pro など に加え、 Switch版電車でGOワンハンドルマスコンで操作できるようにしてみました - Steam コミュニティー で紹介されてるツールを使って JR東トレシム で使っていたりしていた。

程よい重量感や操作感で臨場感が爆上がり… というか、無いと面白みが8割減レベルに気に入っており、最近 EXCLUSIVE EDITION を買い増した。

…ところが買い増しした ZKNS-002 は、Switch 版や 鉄道にっぽん! シリーズでは問題なく動くのに、上記ツールを使って JR東トレシム しようとすると以下のようなエラーが出て動かない。

Traceback (most recent call last):
  File "main.py", line 24, in <module>
  File "SwitchDenGo.py", line 32, in loadStatus
pygame.error: Invalid joystick button
[33064] Failed to execute script 'main' due to unhandled exception!

存在しない joystick 番号を指定されてエラーになってる。
…つまりボタン配置が違う?

しかしそもそも、この ZUIKIコン は汎用 USB コントローラ として認識されるモノだし、Windows OS 側のデバイスの設定を見ても、どちらも同じ "One Handle MasCon for Nintendo Switch" と認識され、全くボタン配置で認識されている。
なんでボタン配置がズレるのか、訳がわからないよ。

上記 Steam コミュニティー でも、同じような問題に遭遇している人が何人かいる。
しかも、 通常版 ZKNS-001 か EXCLUSIVE EDITION ZKNS-002 かを問わず発生するようだ。

つまり、型番違いによる仕様変更が原因ではない…?

意外なる原因

続きを読む

PC Manager をオフラインやプロキシ環境下でインストールする

システム最適化ソフト「Microsoft PC Manager」が、 v3.1.3 で日本語に対応したらしい。

元々中国向けに提供されていたものが、英語、それ以外の言語と順次展開が拡大されおり、今回めでたく日本語対応したようだ。
…あれ? こないだまで最新ベータ版は v3.2 だったような…?
まぁいいか。

Windows 11 だと何かとメモリを食いつぶされて、 16~32GB 程度のメモリでは VM や WSL の起動に失敗することが多々あるので、 Windows 98 や Me の時代を思い出すようなメモリクリーンアップ機能は、今の時代でも重宝される。

さて、この Microsoft PC Manager だが Microsoft の公式ページ からインストーラをダウンロードして実行しても、オフライン環境やプロキシ環境下だと「インストール ファイルをダウンロードできませんでした。後でもう一度お試しください。」等と表示されて、インストールに失敗する。

インストーラ (MSPCManagerSetup.exe) が実行時に実プログラムをダウンロードする必要があるからだ。

どこかにオフライン版のインストーラはないものか…
と調べていたら、 FANDOM の Wiki にオフラインインストーラのリンクの作り方が書いてあった。

続きを読む

個人用 Clipchamp から組織ユーザーへプロジェクトを無理やり移行する

この記事では、 個人アカウント用 Clipchamp から組織(法人)ユーザーの Clipchamp へプロジェクトを移行する方法、およびその応用で、個人用から別の個人用ユーザーに Clipchamp プロジェクトを移行(コピー)する方法を説明する。


去る7月31日に、 動画編集アプリ Clipchamp が組織アカウントに対応し、ビジネス向け Microsoft 365 に加わることが発表された。

これにより、 Microsoft での買収以降どのプランが商用利用可能なのか曖昧だった Clipchamp が、組織アカウント上で安心して商用利用できる事になる。
北米時間の 2023年10月15日 に Clipchamp が商用ユーザーで利用可能になったことが発表 され、 Microsoft 365 の対象プランのライセンスを持つ全てのユーザーに対し Clipchamp が一般公開された。

さて、 Clipchamp が組織アカウントに対応したことで、旧来の個人アカウント用 Clipchamp アカウントで作成していたプロジェクトを、組織アカウントに移行したくなる場合もあるだろう。

しかし FAQ などをみると、

職場アカウントで Microsoft Clipchamp にアクセスする方法 - Microsoft サポート

個人アカウント用に Clipchamp で作成されたプロジェクトを作業バージョンに移動できますか?

いいえ。

無慈悲。

仕事向けの Clipchamp - clipchamp.com

個人用アカウントの Clipchamp で作成したプロジェクトを職場アカウントに移行できますか?

現時点では、個人用アカウントで作成したプロジェクトを職場アカウントに移行することはできません。

こちらは、もうちょいマイルドだ。

将来的にやる気があるのかはわからんが、少なくとも現時点では、個人アカウントのデータの組織アカウントへの移行は、公式的にはできないらしい。

ところで、実際に組織アカウントで Clipchamp を使ってみると、プロジェクトファイルが OneDrive for Bussiness の <ルート>\動画\Clipchamp\<プロジェクト名>\ あたりの、 *.clipchamp という、 JSON が実体のファイルとして保存されていることに気づく。

個人用 Clipchamp の動作を思い出してみると、画像や音声などのアセットはローカルにキャッシュや保存されているものが参照されているだけで、別 PC でプロジェクトを開こうとすると、改めてアセットファイルを紐づける必要があった。

このため、 個人用 Clipchamp のプロジェクトも、この JSON ファイル程度の情報しかサーバーで管理されていないのではと推測できる。

つまり、何らかの方法でこの JSON ファイル相当の情報を個人用 Clipchamp から抜き出せれば、組織アカウントに移行できるかもしれない。

試行錯誤してみたところ、どうやら上手くいったようなので、その方法を紹介しよう。

続きを読む

超コスパ左手デバイス SIKAI CASE を安全に設定する

世の中には、「片手キーボード」とか「左手デバイス」と呼ばれるデバイスが存在する。

ペンを使ったお絵かきや、マウス中心の作業を行う際に使われるデバイスで、必要なショートカットキーなどを登録しておくことで、複雑な操作を簡略化して入力を行えるものだ。

こういった商品は、世の中にいろいろあるのだが、有名な商品はまぁ高い。

自分で好きなようにショートカットキーを登録できる汎用的なものだと、2万3万は余裕で飛ぶようなものばかりだ。

こういったジャンルには、いわゆる中華デバイスなどとも呼ばれる、機能を割り切った安価なデバイスが売られていることが多く、この「左手デバイス」も例外ではない。

そんな、中華左手デバイスの中で、デバイスとしては比較的評判が悪くない SIKAI CASE 片手キーボード を、少し安全に使う方法について、少し考えてみようと思う。

なお、この製品自体がどんなものなのかは、ここらへんの解説動画あたりが参考になるので、そちらをどうぞ。
(私自身も、この動画を見て買った)

「安全に使う」とは?

続きを読む

Git と OneDrive 等のクラウドストレージを併用する

ブログに書きたいネタとか雑多なメモを管理する際、Git によるバージョン管理と、クラウドストレージによる同期を併用したくなる。

具体的には、こんなことがしたい:

  • コミットに至らないメモ書きの段階では、クラウドストレージで同期させたい
    • ついでにそのメモ書きは、タブレット等の複数の端末から更新したい
  • ブログで記事を公開してからの差分を Git で管理

プライベートのリモートリポジトリ代わりに、ベアリポジトリを OneDrive に共有する話は見たことある (これ とか これ) のだが、私がやりたいこととはちょっと違うんだよな。
そもそも、 Microsoft 買収後に GitHub で無制限にプライベートリポジトリ作れるようになったので、 Git リポジトリの共有自体は GitHub とかで良いので。

以前、ローカルリポジトリをまるごと OneDrive で共有させてみたのだが、複数の端末で編集すると同期の競合が発生しまくってしまった。
特に .\.git ディレクトリ内でコンフリクトすると後処理が面倒くさすぎる。

どうにかならんもんか。

.\.git ディレクトリだけ同期除外

先に答えを言ってしまうと、クラウドストレージでの同期で特定のディレクトリの同期を除外させれば良い。

.\.git ディレクトリ内のコンフリクトが面倒なら、 .\.git ディレクトリだけ同期を除外させればいじゃない… という精神だ。

ただ、 OneDrive では一筋縄ではいかなかったので、少々トリッキーな方法を採っている。

そのやり方を、 Windows 上の OneDrive を例に紹介する。

1つ目の端末

続きを読む

GNS3 に VyOS 仮想ルーターを追加する長い道のり④ 応用編

本記事は 【アットホームな現場です】🎄★☆ネットワーク系エンジニア★☆アレコレアウトプット★☆🎄 Advent Calendar 2022 25日目の記事だ。
ごめんなさい、色々書いてたら結局分量が多くなって期限内に書き切れなかった。

GNS3 という OSS のネットワークエミュレータを、 Cisco の IOS などの取得なしに、無料のライセンス内で利用できるようにしようという話。

今回は最終回の応用編。
以前の投稿はこちら。



目指すゴール


今回は、上記の図のように、 ルーターを 2台 置いて、 ルーターを跨いだ端末間 (tmp-net-tools-1, -2) で通信ができるように構成していく。

続きを読む

GNS3 に VyOS 仮想ルーターを追加する長い道のり② イメージ準備編

本記事は 【アットホームな現場です】🎄★☆ネットワーク系エンジニア★☆アレコレアウトプット★☆🎄 Advent Calendar 2022 15日目の記事だ。 (空いていたので埋め)

GNS3 という OSS のネットワークエミュレータを、 Cisco の IOS などの取得なしに、無料のライセンス内で利用できるようにしようという話。

前回の環境導入編に続く第2回。

GNS3 のインストールと GNS3 VM へのアタッチが完了している状態から始める。

VyOS イメージの取得

続きを読む

GNS3 に VyOS 仮想ルーターを追加する長い道のり① 環境導入編

本記事は 【アットホームな現場です】🎄★☆ネットワーク系エンジニア★☆アレコレアウトプット★☆🎄 Advent Calendar 2022 8日目の記事だ。 (空いていたので埋め)

GNS3 という、オープンソースのネットワークエミュレータがある。

GUI 上で、様々なネットワーク機器を仮想環境に設置して、仮想ネットワークを構築できる、大変優れたツールだ。

実際に、ルータや端末を沢山用意して物理的に結線せずとも、 PC 上で簡単にネットワークを作成できるので、ネットワークの勉強の為に、いわゆる ネットワーク ラボ環境 を準備には最適だ。

しかし、一つ大きな問題がある。
GNS3 自体には、基本的なハードウェアのエミュレータしか含まれていないため、ルーターなどを使うには、 "Cisco の IOS" といった「ルーターのソフトウェア」を別途用意しなくてはならない。

すでに Cisco のルーターを持っていて、 IOS イメージなどが手に入るならよいのだが、そうではない場合合法的にこういったイメージを入手するのは(主に金銭的な意味で)厳しい。

ネットワークの検証や勉強をする目的であれば、何も Cisco のルーターでなくとも、使う分には問題ないはずだ。

…ということで、 VyOS という OSS のネットワークデバイスを、 Windows 上の GNS3 で使えるようにするまでの長い道のりを、数回に分けて紹介しようと思う。

とりあえず、今回は環境導入編。

OS

実行する Windows のバージョンは、 CPU が Intel なら Windows 10 で問題ないが、 CPU が AMD (Ryzen/Epic) の場合 Windows 11 以上が望ましい。
これは、 入れ子になった(ネストされた)仮想化による仮想マシン のサポートが、 OS 側に必要であるためだ。
(一応、 AMD のサポートは Windows 10 Build 19640 以上となっているが、 このバージョンはプレビュービルドしか存在しない)

一応、上記を満たしていなくても動作させることは可能だが、内部で仮想化支援機能が働かないので、 VyOS の動作が著しく遅くなる。

ちなみに、 ARM Windows はそもそもサポートされない。

VyOS と VyControl

続きを読む